HttpRequestException - проблема с клиентом или сервером?
Недавно я реализовал некоторый код для использования REST Api, используя класс HttpClient
.
using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") })
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...);
var uri = new Uri(@"rest/api/foo", UriKind.Relative);
var content = new StringContent(json.ToString());
using (var response = await client.PostAsync(uri, content))
{
// etc ...
}
}
Этот код, казалось, отлично справлялся как с тестовыми, так и с производственными средами (каждый из которых обращался к тестовому/производственному uri). В последнее время мы начали получать исключение HttpRequestException в производственной среде: System.Net.Http.HttpRequestException: Error while copying content to a stream.
Это показалось немного странным, поэтому я использовал Postman для отправки того же сообщения, и он работал отлично. Я не был уверен, почему наш код не работает, и Почтальон работает. Я изменил параметр в json-данных (состояние от "NY" до "NV" ), и наш .NET-код работал нормально - конечно, мы не можем просто отправлять неверные данные json, поэтому это не решение; это было скорее наблюдением, что тот же самый код отлично работал с различным контентом.
Интересно, что есть два изменения кода, которые мы могли бы сделать, чтобы решить эту проблему. Во-первых, Postman способен генерировать рабочий код С# с помощью RestSharp
. В качестве альтернативы я нашел ответ из другого вопроса, указывающего на использование HttpVersion 1.0:
using (var request = new HttpRequestMessage(HttpMethod.Post, uri))
{
request.Version = HttpVersion.Version10;
request.Content = new StringContent(json.ToString());
using (var response = await client.SendAsync(request))
{
// etc ...
}
}
Сбивая с толку часть, Postman использует версию HTTP/1.1. Итак, вкратце:
- Если мы изменим данные json (штат США от "NY" до "NV" ), код работает.
- Тот же самый точный json и код работают против тестового uri.
- Смена кода для использования пакета RestSharp работает.
- Выполняется изменение кода для использования HTTP/1.0 вместо HTTP/1.1.
Почему Postman способен работать с использованием HTTP/1.1, но HttpClient терпит неудачу? Это проблема с нашим клиентом (код работает для других штатов США)? Это ошибка в .NET Framework? Что-то не так с реализацией/хостингом REST Api от третьего лица?
Почтовые заголовки:
POST rest/api/foo HTTP/1.1
Host: thirdparty.com
Content-Type: application/json
Authorization: Basic SOME_ENCRYPTED_USER_PASS
Cache-Control: no-cache
Postman-Token: 2fa5b5a0-b5d3-bd4c-40f0-d2b55b60316b
Пример Json:
{
"stateCode": "NY",
"packageID": "58330",
"name": "58330-PRI-1",
"documents": [
{
"type": "SPECIAL",
"name": "Sample Document",
"documentID": "3569976"
}
],
"descriptions": [
{
"city": "New York",
"state": "NY"
}
]
}
StackTrace:
AggregateException: One or more errors occured.
HttpRequestException: Error while copying content to a stream.
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
SocketException: An existing connection was forcibly closed by the remote host.
Ответы
Ответ 1
Из-за того, что вы можете немного изменить данные и добиться успеха, я бы сказал, что ваши проблемы не имеют никакого отношения ни к одному из ваших кодов. Что делать, если их сервер кэшировал плохое значение и будет продолжать отправлять вам это значение, пока их кеш не очистится?
Попробуйте неявно сообщать серверу не использовать кешированные значения...
using (var client = new HttpClient() { BaseAddress = new Uri(@"https://thirdparty.com") })
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(...);
var uri = new Uri(@"rest/api/foo", UriKind.Relative);
var content = new StringContent(json.ToString());
client.DefaultRequestHeaders.CacheControl = CacheControlHeaderValue.Parse("no-cache");
using (var response = await client.PostAsync(uri, content))
{
// etc ...
}
}
и посмотрите, есть ли у вас действительный поток ответов.
Ответ 2
У вас есть антивирус/брандмауэр на компьютере, на котором запущен HttpClient? В прошлом у меня были проблемы с AVG, Mcafee, Norton и другими, которые молча блокировали запросы. Его довольно сложно выяснить, где именно, но может быть вкладка, где контролируются порты, отключение/отключение этого может помочь выявить проблему. Если это так, правильным решением является получение вашего "thirdparty.com" в белом списке соответствующих поставщиков/с.
Возможно, стоит посмотреть на заголовки ответов с вашего сервера? Не могли бы вы добавить их в свой вопрос? Только потому, что в прошлом я нашел заголовки Content-Security-Policy, предотвращающие выполнение некоторых моих запросов?