【问题标题】:Adding a default header only for POST request仅为 POST 请求添加默认标头
【发布时间】:2020-02-18 01:17:04
【问题描述】:

我正在尝试TypedHttpClient,如下所示。我正在寻找一种方法将DefaultRequestHeaders 仅添加到我的POST 请求中(而不是添加到其他请求中,例如GETPUT)。有没有办法做到这一点?

这是我的代码 sn-p。

var builder = services
     .AddHttpClient("MyService", client =>
      {
         client.BaseAddress = configuration.BaseAddress;

         // Need to default header only for "POST" request                    
         client.DefaultRequestHeaders.Add("MyHeader", "MyHeaderValue");
      })
      .AddTypedClient<IMyServiceClient, MyServiceRestClient>();

我正在尝试找到一种方法,其中client.DefaultRequestHeaders.Add("MyHeader", "MyHeaderValue") 行仅对POST 请求有效。

【问题讨论】:

  • 为什么不创建一个单独的服务呢?

标签: c# http asp.net-core asp.net-core-mvc asp.net-core-3.1


【解决方案1】:

一个可重用的 httpclient 配置最少,然后通过特定于 http 方法的执行来管理您的请求?

例如,考虑一个异步 POST 方法,它会覆盖配置请求/响应并使用您的 httpclient 执行的内部通用异步方法。您可以传入您需要的标头和/或在此方法中设置默认标头。

public async Task<KeyValuePair<HttpResponseMessage, T>> PostAsync<T>(Uri uri, object data, AuthenticationHeaderValue authHeader = null, Dictionary<string, string> headers = null)
{
   return await SendRequestAsync<T, object>(uri.ToString(), data, HttpMethod.Post, authHeader, headers);
}

内部方法如下:

private async Task<KeyValuePair<HttpResponseMessage, T>> SendRequestAsync<T, U>(string requestUri, U content, HttpMethod method, AuthenticationHeaderValue authHeader = null, Dictionary<string, string> headers = null)
{
    using (HttpRequestMessage request = new HttpRequestMessage())
    {
        request.Method = method;
        request.RequestUri = new Uri(requestUri, UriKind.Absolute);

        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        if (authHeader != null)
        {
            request.Headers.Authorization = authHeader;
        }

        string requestContent = null;

        if (content != null)
        {
            requestContent = JsonConvert.SerializeObject(content);
            request.Content = new StringContent(requestContent, Encoding.UTF8, "application/json");
        }

        if (headers != null)
        {
            foreach (var header in headers)
            {
                if (!request.Headers.Contains(header.Key))
                {
                    request.Headers.Add(header.Key, header.Value);
                }
            }
        }

        // _client would be a private implementation or injected version of your httpclient
        using (HttpResponseMessage response = await _client.SendAsync(request))
        {
            if (response.IsSuccessStatusCode)
            {
                if (response.Content != null)
                {
                    var rawJson = await response.Content.ReadAsStringAsync();

                    var mappedObj = JsonConvert.DeserializeObject<T>(rawJson);

                    var result = new KeyValuePair<HttpResponseMessage, T>(response, mappedObj);

                    return result;
                }
            }
            else
            {
                // do something else
            }

            return new KeyValuePair<HttpResponseMessage, T>(response, default(T));
        }
    }
}

【讨论】:

  • 我当然可以在调用SendAsync 时做到这一点,这也是我目前的实现。但是,为了简单起见,我在创建 TypedClient 时正在寻找一种方法。
  • 不确定这对客户是否可行,因为这是您请求的载体,而不是请求本身。
【解决方案2】:

我在这里实际上是愚蠢的。我意识到我可以通过DelegatingHandler 实现我想要的。

var builder = services
    .AddHttpClient("MyService", client =>
    {
        client.BaseAddress = configuration.BaseAddress;
    })
    .AddHttpMessageHandler<MySpecialHeaderDelegatingHandler>()
    .AddTypedClient<IMyServiceClient, MyServiceRestClient>();





public class MySpecialHeaderDelegatingHandler: DelegatingHandler
{
    private const string MySpecialHeader = "my-special-header";

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        EnsureMySpecialHeaderExists(request);
        return await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
    }

    private static void EnsureMySpecialHeaderExists(HttpRequestMessage request)
    {
        if (request.Method != HttpMethod.Post) return;

        if (!request.Headers.Contains(MySpecialHeader))
        {
            request.Headers.Add(MySpecialHeader, "MyHeaderValue");
        }
    }

【讨论】:

  • 很高兴你让它工作了,DelegatingHandlers 很棒,但在这里感觉有点矫枉过正。它中断一个已经在运行的请求,只是为了检查方法并添加标头。为什么在创建请求时不这样做?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-04
  • 2017-12-02
  • 2022-08-12
  • 2017-06-22
  • 2017-03-06
  • 1970-01-01
相关资源
最近更新 更多