consume - httpclient c#
HttpRequestException-¿Es esto un problema de cliente o servidor? (2)
Hace un tiempo, implementé un código para consumir un REST Api usando la clase 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 ...
}
}
Este código parece funcionar perfectamente bien contra los entornos de prueba y producción (cada uno de los cuales accede a un uri de prueba / producción). Recientemente, comenzamos a obtener una HttpRequestException solo en el entorno de producción : System.Net.Http.HttpRequestException: Error while copying content to a stream.
Esto me pareció un poco extraño, así que usé Postman para enviar el mismo mensaje y funcionó bien. No estaba seguro de por qué nuestro código estaba fallando y Cartero estaba trabajando. Cambié un parámetro en los datos json (el estado de "NY" a "NV") y nuestro código .NET funcionó bien; por supuesto, no podemos simplemente enviar los datos JSON incorrectos, por lo que esta no es una solución; esto fue más una observación de que el mismo código funcionaba bien con diferente contenido.
Lo interesante es que hay dos cambios de código que podríamos hacer para resolver esto. En primer lugar, Postman puede generar códigos de C # en funcionamiento con el paquete RestSharp
. Alternativamente, encontré una respuesta de otra pregunta que apunta al uso de 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 ...
}
}
La parte confusa es que Postman usa la versión HTTP / 1.1. Entonces, en resumen:
- Si cambiamos los datos json (Estado de EE. UU. De "NY" a "NV"), el código funciona.
- La misma json exacta y el código funcionan contra la prueba uri.
- Cambiar el código para usar el paquete RestSharp funciona.
- Cambiar el código para usar HTTP / 1.0 en lugar de HTTP / 1.1 funciona.
¿Por qué diablos puede trabajar Postman usando HTTP / 1.1 pero HttpClient falla? ¿Es esto un problema con nuestro cliente (el código funciona para otros estados de EE. UU.)? ¿Es esto un error en .NET Framework? ¿Hay algún problema con la implementación / hosting del REST Api del tercero?
Encabezados de cartero:
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
Muestra 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.
¿Tienes Antivirus / Firewall en la máquina que ejecuta el HttpClient? En el pasado, tuve problemas con AVG, McAfee, Norton y otros que bloqueaban silenciosamente las solicitudes. Es bastante complicado averiguar exactamente dónde, pero puede haber una pestaña donde se monitorean los puertos, desmarcar / deshabilitar esto podría ayudar a identificar el problema. Si ese es el caso, la solución adecuada es obtener su "thirdparty.com" en una lista blanca de los proveedores apropiados.
¿Puede valer la pena mirar los encabezados de respuesta de su servidor también? ¿Podría agregarlos a su pregunta? ¿Solo porque, en el pasado, he encontrado encabezados de Content-Security-Policy que impiden que se completen algunas de mis solicitudes?
Debido al hecho de que puede cambiar los datos ligeramente y tener éxito, diría que sus problemas no tienen nada que ver con ninguno de sus códigos. ¿Qué sucede si su servidor ha guardado en caché un valor incorrecto y continuará enviándole ese valor hasta que se borre su caché?
Intente implícitamente decirle al servidor que no use valores en caché ...
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 ...
}
}
y vea si obtiene un flujo de respuesta válido.