Как установить заголовок content-md5 в методе GET с помощью HttpClient? - PullRequest
0 голосов
/ 02 мая 2020

У меня есть следующий код для установки content-md5 в моем запросе метода GET с использованием HttpClient

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

Я не могу использовать HttpRequestMessage контент для его установки, потому что это не метод POST. При использовании Почтальон работает как брелок, но не работает при использовании HttpClient.GetAsync. Клиент запрашивает hma c на сервере следующим образом:

{ "content_to_hash": "my content" }

Сервер выдаст такой ответ

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

Сейчас Я должен получить доступ к GET-запросу, используя этот hma c, где это проблема, потому что я не могу установить в заголовке httpClient GET-запроса.

Вот изображение

enter image description here

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

После прочтения 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 ha sh в качестве байтов, я также добавил конструктор в NoContentMd5 для byte[] тоже.

Единственная потенциальная проблема, связанная с этим, заключается в том, что она включает заголовок Content-Length: 0. Надеюсь, с API, с которым вы работаете, все в порядке.

Существует альтернативное решение, описанное в в этом ответе на вопрос с похожей проблемой. Я бы поспорил против его использования, поскольку он уязвим к изменениям в деталях реализации HttpRequestHeaders (потому что он использует отражение, поэтому, если MS изменит код, он может сломаться).

0 голосов
/ 02 мая 2020

Помимо того, что отправка тела с GET-запросом не считается хорошей практикой (см. HTTP GET с телом запроса ), вы можете попробовать это:

using (var content = new StringContent(string.Empty))
using (var request = new HttpRequestMessage
{
    Method = HttpMethod.Get,
    RequestUri = new Uri("http://localhost"),
    Content = content
})
{
    request.Headers.TryAddWithoutValidation("content-md5", "value");;
    using (var response = await httpClient.SendAsync(request))
    {
        response.EnsureSuccessStatusCode();
    }
}

ОБНОВЛЕНИЕ:

Правильно было бы установить свойство ContentMD5 для HttpContentHeaders, например:

content.Headers.ContentMD5 = Convert.FromBase64String(hashString);

Но, как вы указали в комментарии, попытка отправить содержимое в запросе GET вызывает ошибку.

...