httpclient的一个错误

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了httpclient的一个错误相关的知识,希望对你有一定的参考价值。

这是以下报错信息,org.apache.http.ConnectionClosedException: Premature end of Content-Length delimited message body (expected: 44541; received: 44539

报错代码:EntityUtils.toByteArray(entity)
HttpResponse response = mClient.execute(method);
HttpEntity entity = entity = response.getEntity();
EntityUtils.toByteArray(entity)
以下问题困扰小弟很久了,还望各位大虾鼎力相助,小弟感激不尽。

参考技术A ConnectionClosedException连接关闭异常,你是连自己的还是连别的页面的追问

当然是连接别人的页面啊。这个问题怎么解决呢

使用 HttpClient 的随机 401 未经授权的错误

【中文标题】使用 HttpClient 的随机 401 未经授权的错误【英文标题】:Random 401 Unauthorized errors using HttpClient 【发布时间】:2017-03-03 18:36:37 【问题描述】:

我正在使用 HttpClient 调用 Web Api REST 端点,偶尔我会看到一个随机的 401 未授权状态。

这是我的 HttpClient 包装器,它是为了可重用性目的而创建的。我已经对其进行了修改,以保持这篇文章的简单性,而无需修改核心部分。

public class HttpHelper

        public const string JsonContentType = "application/json";

        public T PostAsJsonObject<T>(string uri, T t) where T : class
        
            using (HttpResponseMessage response = PostJsonHttpRequest(uri, JsonContentType, t))
            
                response.EnsureSuccessStatusCode();
                return response.Content.ReadAsAsync<T>().Result;
            
        

        private HttpResponseMessage PostJsonHttpRequest<T>(string uri, string contentType, T content) where T : class
        
            if (String.IsNullOrEmpty(uri))
            
                throw new ArgumentNullException("uri");
            
            HttpResponseMessage response = CreateHttpClient(contentType).PostAsJsonAsync(uri, content).Result;
            return response;
        

        private HttpClient CreateHttpClient(string contentType)
        
           var credentials = new NetworkCredential("srvuser", "somepwd", "somedomain");
           return new HttpClient(new HttpClientHandler  Credentials = credentials, PreAuthenticate = true );
        

这是我调用它的方式。

var httpHelper = new HttpHelper();
var response = httpHelper.PostAsJsonObject("https://xyz.pvt/inventory/api/orders", "234");

大多数时候它工作正常,但偶尔我会收到 401 Unauthorized 错误。我正在尝试找出可能导致它的原因。

System.Net.Http.HttpRequestException:响应状态码不 表示成功:401(未授权)。在 System.Net.Http.HttpResponseMessage.EnsureSuccessStatusCode() 在 HttpHelper.PostAsJsonObject[T](String uri, T t)

我查看了 asp.net 日志,发现了一个奇怪的模式。大多数时候,我会看到一对条目(401 后跟 200 OK),例如

2017-02-09 12:04:13 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 764 
2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2917

2017-02-09 12:04:16 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0 
2017-02-09 12:04:19 104.68.45.152 POST /inventory/api/orders/ - 80 somedomain\srvusr 132.64.78.120 HTTP/1.1 - 200 0 0 2230

但偶尔我只看到 401

2017-02-09 12:14:04 104.68.45.152 POST /inventory/api/orders/ - 80 - 132.64.78.120 HTTP/1.1 - 401 2 5 0

REST api 是使用在 .NET 4.6.1 和 IIS 7.5 上运行的 ASP.NET Web Api 2 实现的,它仅使用 Windows 身份验证进行设置。

不确定是什么原因导致身份验证偶尔失败。

更新:

这是我使用异步等待模式编写的新代码。

public class HttpHelper

        public const string JsonContentType = "application/json";

        private HttpClient CreateHttpClient(string url, string contentType)
        
            var handler = new HttpClientHandler
            
                Credentials = new CredentialCache   new Uri(url), "NTLM", new NetworkCredential("srvuser", "somepwd", "somedomain")  ,
                PreAuthenticate = true
            ;
            var httpClient = new HttpClient(handler);
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue(contentType));
            return httpClient;
        

        private async Task<HttpResponseMessage> PostJsonHttpRequestAsync<T>(string url, string contentType, T content) where T : class
        
            if (string.IsNullOrEmpty(url))
            
                var exception = new ArgumentNullException("url");
                throw exception;
            

            var response = await CreateHttpClient(url, contentType).PostAsJsonAsync(url, content);

            return response;
        

        public async Task<T> PostAsJsonObjectAsync<T>(string uri, T t) where T : class
        
            using (var response = await PostJsonHttpRequestAsync(uri, JsonContentType, t))
            
                return await response.Content.ReadAsAsync<T>(new[]
                    
                      new JsonMediaTypeFormatter
                      
                         SerializerSettings =  NullValueHandling = NullValueHandling.Ignore, TypeNameHandling = TypeNameHandling.Auto 
                      
                    .AsEnumerable());
            
        
    

这是我最终调用它的方式。

static class TestMe

    static void Main()
    
        var httpHelper = new HttpHelper();
        var responseTask = httpHelper.PostAsJsonObjectAsync("https://xyz.pvt/inventory/api/orders", "234");

        responseTask.Wait(120000);
        var response = responseTask.Result;
        Console.WriteLine(response);
    

即使现在我也看到了同样的问题。仍然出现随机 401 Unauthorized 错误。

更新 2

我做了更多调查,发现这些神秘的 401 错误来自 IIS。当这些神秘的 401 错误发生时,IIS 日志有一个相应的 401 错误条目,但在这种情况下,请求永远不会到达 asp.net 管道。好像由于某种原因,请求被 IIS 退回并出现 401 错误。

无需过多深入,我知道 IIS 中的 windows 身份验证使用 2 个请求来根据 HttpClient 的配置方式来管理身份验证。所以一个成功的身份验证请求将有一个 401.2 后跟 200 OK。这是大多数时间发生的事情。有时我注意到有一个 401.2,然后是 401。重试尝试时的相同请求正常(401.2 后跟 200 OK)。

如果有人对此问题有所了解并有可能解决该问题,我将不胜感激。

【问题讨论】:

我正在对源代码进行一些小的更正,请多多包涵 可能是您在 asp.net 上下文中滥用异步。 ***.com/questions/13140523/… @Crowcoder,很抱歉造成混乱。以前我发布了一个不同的代码示例,我正在重构。请立即查看。 你还在打电话给.Result。我不知道这是否是你的问题,但这不应该在 asp.net 中完成。也许你可以使用 HttpClientHandler 进行预认证:***.com/questions/20260013/… 如果你看我的代码,我已经在做 PreAuthenticate = true。正如您在更新之前的代码示例中看到的那样,我已经开始摆脱 .Result 模式(它是大约 2 或 3 年前实现的遗留代码)并用异步等待模式替换它。让我看看这是否能解决问题。 【参考方案1】:

您确定您的代码甚至是问题所在吗?我不知道您的具体情况,但有可能网络服务器有时会无缘无故地向您发送 401 响应。

您可以执行以下操作来测试该理论:同时运行程序的两个(或更多)实例,最好是在不同的机器上运行。等到您收到 401 错误。如果您的代码的所有实例同时开始收到 401 错误,那么几乎可以肯定是 Web 服务器上的问题。

【讨论】:

当然,我会尝试的。顺便说一句...我有重试机制来解决这个问题。但我觉得这是一个创可贴修复。试图了解这些神秘的 401 错误的根本原因。

以上是关于httpclient的一个错误的主要内容,如果未能解决你的问题,请参考以下文章

如何解决 WebAssembly 应用程序中与 HttpClient 相关的错误

HttpClient 证书错误

C# HttpClient 是不是忽略 SSL 证书错误?

执行httpclient时出现奇怪的错误

Angular 4 错误:没有 HttpClient 的提供者

httpclient 返回content-length 错误的问题!