首页 > 解决方案 > 如何使用 HttpClient 在 GET 方法中设置 content-md5 标头?

问题描述

我有以下代码使用HttpClient在我的 GET 方法请求中设置 content-md5

httpClient.DefaultRequestHeaders.TryAddWithoutValidation("content-md5", "value");

我不能使用HttpRequestMessage内容来设置它,因为它不是 POST 方法。使用Postman时,它就像一个魅力,但在使用HttpClient.GetAsync. 客户端向服务器请求一个 hmac,如下所示

{ "content_to_hash": "my content" }

服务器会给出这样的响应

{ "content_md5": "88af7ceab9fdafb76xxxxx", "date": "Sat, 02 May 2020 00:13:16 +0700", "hmac_value": "WfHgFyT792IENmK8Mqz9LysmP8ftOP00qA=" }

现在我必须使用问题所在的 hmac 访问 GET 请求,因为我无法在 httpClient GET 请求标头中进行设置。

这是图像

在此处输入图像描述

标签: c#.netdotnet-httpclient

解决方案


通过阅读HttpClient和相关的源代码,您无法解决这个问题并将标头添加到实际的请求对象标头中。有一个无效标头的内部列表,其中包括任何Content-*标头。它必须在内容对象上。

因此,我建议的解决方案是创建自己的内容对象:

public class NoContentMd5 : HttpContent
{
    protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
    {
        return Task.CompletedTask;
    }

    protected override bool TryComputeLength(out long length)
    {
        length = 0;
        return false;
    }

    public NoContentMd5(byte[] contentMd5)
    {
        this.Headers.ContentMD5 = contentMd5;
    }

    public NoContentMd5(string contentMd5)
    {
        this.Headers.TryAddWithoutValidation("Content-MD5", contentMd5);
    }
}

这将添加Content-MD5带有您选择的值的标头,但请求将不包含正文。

您将遇到的下一个问题是您尝试使用内容发出 GET 请求,而辅助client.GetAsync(...)方法不支持该请求。您必须创建自己的请求对象并client.SendAsync(...)改为使用:

HttpClient client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://localhost/my/test/uri");
request.Content = new NoContentMd5("d41d8cd98f00b204e9800998ecf8427e ");
var result = await client.SendAsync(request);

请注意,如果您将 Content-MD5 哈希作为字节,我还添加了一个构造函数NoContentMd5byte[]

唯一的潜在问题是它包含一个Content-Length: 0标题。希望您使用的 API 没问题。

此问题的答案中描述了一种替代解决方案,具有类似的问题。我反对使用它,因为它容易受到HttpRequestHeaders(因为它使用反射,所以如果 MS 更改代码,它可能会破坏)的实现细节的变化。


推荐阅读