为什么HttpClient在请求成功时抛出异常

本文关键字:抛出异常 成功 请求 HttpClient 为什么 | 更新日期: 2023-09-27 18:00:39

我在web请求的上下文中使用HttpClient发送另一个web请求,如下所示:

private async Task SendManagerInfoAsync(Uri baseUri, string accessToken, object obj,
    string apiPath, HttpMethod httpMethod)
{
    string authToken = await GetManagerAuthToken(baseUri, accessToken)
        .ConfigureAwait(false);
    string url = new Uri(baseUri, apiPath).AbsoluteUri;
    var request = new HttpRequestMessage(httpMethod, url)
    {
        Content = new StringContent(JsonConvert.SerializeObject(obj))
    };
    request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
    request.Headers.Add("Authorization", authToken);
    // For whatever reason, always throws a TaskCanceledException.
    var response = await m_httpClient.SendAsync(request).ConfigureAwait(false);
    response.EnsureSuccessStatusCode();
}

我正在追踪的请求是一个HTTP PUT。出于某种原因,一旦达到预设的HttpClient.Timeout长度(大约30秒),此代码总是抛出一个TaskCanceledException。但是,当我检查此请求的收件人时,我发现数据存储总是已经用我在发起请求后一秒内发送的信息进行了更新。

我不明白当请求实际成功时,HttpClient实例为什么或如何抛出异常。没有请求取消令牌。以前有人见过这样的行为吗?


*我将此问题标记为与Akamai有关,因为只有当我们为接收请求的服务器打开Akamai服务时,我才能观察到这种行为

为什么HttpClient在请求成功时抛出异常

我最终检查了HttpClient发送的明显不成功的请求和Chrome Postman发送的成功请求。默认情况下,HttpClient在每个请求中包括Expect: 100-continue报头。我按如下方式禁用了它,请求重新开始正常运行。

m_httpClient.DefaultRequestHeaders.ExpectContinue = false;

(对于为什么这样做,我没有一个很好的答案,但这让我暂时又向前迈进了。)


编辑:它似乎是这样工作的,因为Akamai严格解释RFC 2616 8.2.3,如果它接收到带有Expect: 100-continue标头的请求,则声明源服务器

  • 必须以100(继续)状态响应并继续从输入流中读取,或者以最终状态代码响应

  • 如果返回最终状态代码,则不得执行请求的方法

因此,Akamai仍在等待100个响应代码,但它从未得到,因此请求超时,这转化为HttpClient抛出的TaskCanceledException

我仍然不知道为什么HttpClient.DefaultRequestHeaders.ExpectContinue默认true而不是false,但这是另一天的问题。