为什么HttpClient在请求成功后会抛出异常?
Why does HttpClient throw an exception when the request is successful?
我在 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
发送的明显不成功的请求和 Chrome Postman 发送的成功请求。 HttpClient
默认情况下在每个请求中包含 Expect: 100-continue
header。我按如下方式禁用它,请求又开始正常运行了。
m_httpClient.DefaultRequestHeaders.ExpectContinue = false;
(关于 为什么 这有效,我没有一个好的答案,但它让我暂时再次前进。)
Edit:它似乎以这种方式工作,因为 Akamai 严格解释 RFC 2616 8.2.3,它声明一个源服务器,如果它收到带有 [=13] 的请求=] header,
MUST either respond with 100 (Continue) status and continue to read from the input stream, or respond with a final status code
MUST NOT perform the requested method if it returns a final status code
所以 Akamai 仍在等待 100 响应代码,它永远不会得到,因此请求超时,这转化为 HttpClient
抛出的 TaskCanceledException
。
我仍然不知道为什么 HttpClient.DefaultRequestHeaders.ExpectContinue
默认 为 true
而不是 false
,但这是另一天的问题。
我在 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
发送的明显不成功的请求和 Chrome Postman 发送的成功请求。 HttpClient
默认情况下在每个请求中包含 Expect: 100-continue
header。我按如下方式禁用它,请求又开始正常运行了。
m_httpClient.DefaultRequestHeaders.ExpectContinue = false;
(关于 为什么 这有效,我没有一个好的答案,但它让我暂时再次前进。)
Edit:它似乎以这种方式工作,因为 Akamai 严格解释 RFC 2616 8.2.3,它声明一个源服务器,如果它收到带有 [=13] 的请求=] header,
MUST either respond with 100 (Continue) status and continue to read from the input stream, or respond with a final status code
MUST NOT perform the requested method if it returns a final status code
所以 Akamai 仍在等待 100 响应代码,它永远不会得到,因此请求超时,这转化为 HttpClient
抛出的 TaskCanceledException
。
我仍然不知道为什么 HttpClient.DefaultRequestHeaders.ExpectContinue
默认 为 true
而不是 false
,但这是另一天的问题。