首页 文章

具有不同身份验证标头的HttpClient单实例

提问于
浏览
45

鉴于.net HttpClient在设计时考虑了重用,并且在短期实例中应该是long livedmemory leaks have been reported . 在为多个用户调用 endpoints 时,您希望使用不同的承载令牌(或任何授权标头)对给定 endpoints 进行静默呼叫的指南行是什么?

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

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

在不引起使用锁争用和维护无状态Web应用程序的情况下,为单个 endpoints 创建和部署HttpClients的建议方法是什么(我目前的做法是为每个 endpoints 创建一个客户端)?


生命周期尽管HttpClient间接实现了IDisposable接口,但HttpClient的推荐用法并不是在每次请求后都将其处理掉 . 只要您的应用程序需要发出HTTP请求,HttpClient对象就会存在 . 在多个请求之间存在一个对象,可以设置一个用于设置DefaultRequestHeaders的地方,并且可以防止您在每次请求时重新指定CredentialCache和CookieContainer之类的内容,这是HttpWebRequest所必需的 .

1 回答

  • 48

    如果您的 Headers 通常是相同的,那么您可以设置 DefaultRequestHeaders . 但是你没有确定,只是不会有多个线程使用同一个客户端 . 对一个线程上的默认标头的更改将影响在其他线程上发送的请求 .

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

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

    这意味着您可以't use the simplified methods that don' t涉及创建 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));
    

相关问题