9

由于 Microsoft建议创建HttpClient一次并在程序的整个生命周期中重复使用,我想知道如何更新DefaultRequestHeaders,例如,令牌已过期并且需要刷新。

DefaultRequestHeaders更多的是不是线程安全的(据我所知),并且在那里定义的标头列表由所有潜在的待处理请求共享。带有新标记Clear()的列表和标题似乎不是明智的做法。Add()


更新

更准确地说,我不想/不需要为每个请求更改请求标头。仅当我获得 HTTP 401 状态代码时。

4

1 回答 1

6

当您在 DI 容器注册阶段注册 IHttpClient 或使用其他模式(如工厂或单例)返回带有自定义消息处理程序的 IHttpClient 实例时,将消息处理程序与您的 HttpClient 连接起来。检查出站呼叫并添加必要的标头。

https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/httpclient-message-handlers

示例标头消息处理程序

class MessageHandler1 : DelegatingHandler
    {


    private int _count = 0;

    protected override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
    {
        System.Threading.Interlocked.Increment(ref _count);
        request.Headers.Add("X-Custom-Header", _count.ToString());
        return base.SendAsync(request, cancellationToken);
    }
}

示例记录器消息处理程序:

class LoggingHandler : DelegatingHandler

{
    StreamWriter _writer;

public LoggingHandler(Stream stream)
{
    _writer = new StreamWriter(stream);
}

protected override async Task<HttpResponseMessage> SendAsync(
    HttpRequestMessage request, System.Threading.CancellationToken cancellationToken)
{
    var response = await base.SendAsync(request, cancellationToken);

    if (!response.IsSuccessStatusCode)
    {
        _writer.WriteLine("{0}\t{1}\t{2}", request.RequestUri, 
            (int)response.StatusCode, response.Headers.Date);
    }
    return response;
}

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        _writer.Dispose();
    }
    base.Dispose(disposing);
}

}

将其添加到管道

HttpClient client = HttpClientFactory.Create(new Handler1(), new Handler2(), new Handler3());

线程问题

关于线程问题或并发性,方法HttpRequestMessage上的参数SendAsync将是每个请求。如果您将标头添加到request.Headers集合中,您将仅更新该请求实例的标头(即,不是全局的)

request.Headers或者在实例上使用 Authorization 属性:

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

请参阅下面的 MSDN 链接

https://msdn.microsoft.com/en-us/library/system.net.http.httprequestmessage

如果您DefaultRequestHeaders在 HttpClient 的静态、共享、单例、Lifestyle.Singleton 等实例上使用,那么您将遇到线程问题并且需要适当的同步来更新DefaultRequestHeaders集合。

于 2018-04-21T08:02:37.657 回答