HttpRequestException - 这是客户端还是服务器问题?

m-y*_*m-y 22 c# rest json dotnet-httpclient postman

前一段时间我使用HttpClient该类实现了一些使用REST Api的代码.

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 ...
    }
}
Run Code Online (Sandbox Code Playgroud)

对于测试和生产环境(每个环境都访问测试/生产环境),此代码似乎完全正常.最近,我们开始生产环境中获得HttpRequestException :System.Net.Http.HttpRequestException: Error while copying content to a stream.

这看起来有点奇怪,所以我使用Postman发送相同的消息,它工作得很好.我不确定为什么我们的代码失败了,Postman正在工作.我更改了json数据中的参数(状态从"NY"到"NV"),我们的.NET代码运行正常 - 当然我们不能只发送错误的json数据,所以这不是一个解决方案; 这更像是一个观察结果,完全相同的代码在不同内容下运行良好.


有趣的是,我们可以通过两个代码更改来解决这个问题.首先,Postman能够使用该RestSharp包生成有效的C#代码.或者,我从另一个指向使用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 ...
    }
}
Run Code Online (Sandbox Code Playgroud)

令人困惑的部分是Postman使用HTTP/1.1版本.所以,总结一下:

  • 如果我们将json数据(US州从"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
Run Code Online (Sandbox Code Playgroud)

示例Json:

{
    "stateCode": "NY",
    "packageID": "58330",
    "name": "58330-PRI-1",
    "documents": [
        {
            "type": "SPECIAL",
            "name": "Sample Document",
            "documentID": "3569976"
        }
    ],
    "descriptions": [
        {
            "city": "New York",
            "state": "NY"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪:

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.
Run Code Online (Sandbox Code Playgroud)

Twi*_*tem 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 ...
    }
}
Run Code Online (Sandbox Code Playgroud)

并查看是否获得有效的响应流。