鉴于.net HttpClient在设计时考虑了重用,并且在短期实例中应该是long lived和memory leaks have been reported。在为多个用户调用端点时,您希望使用不同的承载令牌(或任何授权标头)对给定端点进行静默调用的指南行是什么?
private void CallEndpoint(string resourceId, string bearerToken) {
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("bearer", bearerToken);
var response = await httpClient.GetAsync($"resource/{resourceid}");
}
鉴于上述代码可以由Web应用程序中的任意数量的线程调用,第一行中设置的标头很可能与调用资源时使用的标头不同。
不使用锁和维护无状态Web应用程序引起争用,为单个端点创建和部署HttpClients的建议方法是什么(我目前的做法是为每个端点创建一个客户端)?
生命周期
虽然HttpClient间接实现了IDisposable 接口,HttpClient的推荐用法是不要处理它 在每次请求之后。 HttpClient对象旨在用作as 您的应用程序需要发出HTTP请求。有一个对象 跨多个请求存在一个地方进行设置 DefaultRequestHeaders并阻止您重新指定内容 像每个请求一样使用CredentialCache和CookieContainer 必要的HttpWebRequest。
答案 0 :(得分:57)
如果您的标题通常是相同的,那么您可以设置DefaultRequestHeaders
。但是您不需要使用该属性来指定标头。正如您已经确定的那样,如果您将使用同一客户端拥有多个线程,那将无法工作。对一个线程上的默认标头的更改将影响在其他线程上发送的请求。
虽然您可以在客户端上设置默认标头并将其应用于每个请求,但标头实际上是请求的属性。因此,当标头特定于请求时,您只需将它们添加到请求中即可。
request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);
这意味着您无法使用不涉及创建HttpRequest
的简化方法。你需要使用
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
记录here。
通过扩展方法完成的GET和POST方法示例,允许您在发送之前操纵请求标头及更多HttpRequestMessage
:
public static Task<HttpResponseMessage> GetAsync
(this HttpClient httpClient, string uri, Action<HttpRequestMessage> preAction)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, uri);
preAction(httpRequestMessage);
return httpClient.SendAsync(httpRequestMessage);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<T>
(this HttpClient httpClient, string uri, T value, Action<HttpRequestMessage> preAction)
{
var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = new ObjectContent<T>
(value, new JsonMediaTypeFormatter(), (MediaTypeHeaderValue)null)
};
preAction(httpRequestMessage);
return httpClient.SendAsync(httpRequestMessage);
}
然后可以使用以下内容:
var response = await httpClient.GetAsync("token",
x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));