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

时间:2015-07-01 21:03:37

标签: c# async-await dotnet-httpclient akamai

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

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。出于某种原因,此代码一旦达到预设的TaskCanceledException长度,大约30秒就会抛出HttpClient.Timeout。但是,当我检查此请求的收件人时,我发现数据存储总是已经使用我在原始请求的一秒内发送的信息进行了更新。< / p>

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

*我将此问题标记为与Akamai相关,因为当我们为接收请求的服务器启用Akamai服务时,我只能观察到此行为。

1 个答案:

答案 0 :(得分:3)

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

m_httpClient.DefaultRequestHeaders.ExpectContinue = false;

(对于为什么这是有效的,我没有一个好的答案,但它让我暂时再次前进。)

编辑:它似乎以这种方式工作,因为Akamai严格解释RFC 2616 8.2.3,如果它收到带Expect: 100-continue标头的请求,则声明原始服务器< / p>

  •   

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

  •   

    如果返回最终状态代码

    ,则不得执行所请求的方法

所以Akamai仍在等待100个响应代码,它永远不会得到,因此请求超时,转换为TaskCanceledException抛出的HttpClient

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