具有不同身份验证标头的HttpClient单个实例 [英] HttpClient single instance with different authentication headers

查看:64
本文介绍了具有不同身份验证标头的HttpClient单个实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

鉴于.net HttpClient在设计时考虑了重用,因此旨在成为寿命很短已报告了内存泄漏实例。在为多个用户调用端点时,您希望使用不同的承载令牌(或任何授权标头)对给定端点进行宁静调用的指导原则是什么?

Given that the .net HttpClient has been designed with reuse in mind and is intended to be long lived and memory leaks have been reported in short lived instances. What guide lines are there where you want to make restful calls to a given endpoint using different bearer tokens (or any authorization header) when calling the endpoint for multiple users?

private void CallEndpoint(string resourceId, string bearerToken) {
  httpClient.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("bearer", bearerToken);
  var response = await httpClient.GetAsync($"resource/{resourceid}");
}

鉴于上面的代码可以被Web应用程序上的任意数量的线程调用很可能第一行中设置的标头与调用资源时使用的标头不同。

Given the above code could be called by any number of threads on a web application it is easily possible that the header set in the first line is not the same one that is used when calling the resource.

不使用锁引起争用并维护无状态Web应用程序为单个端点创建和配置HttpClient的推荐方法是什么(我目前的做法是为每个端点创建单个客户端)?

Without causing contention using locks and maintaining a stateless web application what is the recommended approach to creating and disposing HttpClients for a single endpoint (My current practice is to create a single client per endpoint)?


生命周期

尽管HttpClient间接实现了IDisposable
接口,但建议HttpClient的用法不是在每次请求后都丢弃
。只要您的应用程序需要发出HTTP请求,HttpClient对象就可以生存
。在多个请求中都存在一个对象
可以设置
DefaultRequestHeaders的位置,并防止您必须在每个请求中重新指定
之类的东西,例如CredentialCache和CookieContainer,这与HttpWebRequest所需的
一样

Although HttpClient does indirectly implement the IDisposable interface, the recommended usage of HttpClient is not to dispose of it after every request. The HttpClient object is intended to live for as long as your application needs to make HTTP requests. Having an object exist across multiple requests enables a place for setting DefaultRequestHeaders and prevents you from having to respecify things like CredentialCache and CookieContainer on every request, as was necessary with HttpWebRequest.


推荐答案

如果标头通常相同,则可以设置 DefaultRequestHeaders 。但是您不需要使用该属性来指定标题。正如您已经确定的那样,如果您要使用同一客户端使用多个线程,那将是行不通的。在一个线程上更改默认标头会影响在其他线程上发送的请求。

If your headers are usually going to be the same then you can set the DefaultRequestHeaders. But you don't need to use that property to specify headers. As you've determined, that just wouldn't work if you're going to have multiple threads using the same client. Changes to the default headers made on one thread would impact requests sent on other threads.

尽管您可以在客户端上设置默认标头并将其应用于每个请求,但标头确实是请求的属性。因此,当标头特定于请求时,只需将它们添加到请求中。

Although you can set default headers on the client and apply them to each request, the headers are really properties of the request. So when the headers are specific to a request, you would just add them to the request.

request.Headers.Authorization = new AuthenticationHeaderValue("bearer", bearerToken);

这意味着您不能使用不涉及创建<$ c $的简化方法c> HttpRequest 。您需要使用

That means you can't use the simplified methods that don't involve creating an HttpRequest. You'll need to use

public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)

已记录此处

有些人发现使用扩展方法将代码更新标头的代码与方法的其余部分隔离很有帮助。

Some have found it helpful to use extension methods to isolate the code that updates the headers from the rest of a method.

GET和POST方法的示例通过扩展方法完成的操作,该方法允许您在发送请求之前处理请求标头和 HttpRequestMessage

Example of GET and POST methods done through an extension method that allow you to manipulate the request header and more of the HttpRequestMessage before it is sent:

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);
}

这些可以像下面这样使用:

These could then be used like the following:

var response = await httpClient.GetAsync("token",
    x => x.Headers.Authorization = new AuthenticationHeaderValue("basic", clientSecret));

这篇关于具有不同身份验证标头的HttpClient单个实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆