4

I'm using HttpClient in the context of a web request to send another web request as follows:

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();
}

The request I'm tracking down is an HTTP PUT. For some reason, this code always throws a TaskCanceledException once it reaches the preset HttpClient.Timeout length, about 30 seconds. However, when I check the recipient of this request, I see that the datastore is always already updated with the information I'd sent within one second of the originating request.

I don't understand why or how the HttpClient instance would throw an exception when the request is actually successful. No cancellation token is being requested. Has anyone ever seen a behavior like this before?


* I tagged this question as related to Akamai because I can only observe this behavior when we flip a switch turning on Akamai services for the server receiving the request.

5
  • 2
    It sounds like you aren't actually getting a response. What do you see in Fiddler? Commented Jul 1, 2015 at 21:05
  • @SLaks I'm getting an HTTP 500 response which includes the stack trace of the TaskCanceledException. Commented Jul 1, 2015 at 21:08
  • 1
    Clearly an Unhanded exception occurring on the web server - and you have not shown us the web server code. I think this has gone as far as it can for the moment. Commented Jul 1, 2015 at 21:37
  • @SamAxe what's interesting about this situation is that when the Akamai switch is off, there's no exception. Moreover, the server has a fairly robust error logging service, and we can verify that no errors are logged when the client receives the task canceled exception. Commented Jul 1, 2015 at 21:50
  • @SLaks thanks for the prodding to do some more investigation via Fiddler; this got me going in the right direction. Commented Jul 2, 2015 at 3:51

1 Answer 1

4

I ended up inspecting the apparently unsuccessful request sent by HttpClient and a successful request sent by Chrome Postman. HttpClient by default includes the Expect: 100-continue header in each request. I disabled it as follows, and the request started behaving normally again.

m_httpClient.DefaultRequestHeaders.ExpectContinue = false;

(I don't have a good answer as to why this works, but it's gotten me moving forward again for the moment.)


Edit: It appears that it works this way because Akamai strictly interprets RFC 2616 8.2.3, which declares an origin server, if it receives a request with the Expect: 100-continue 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

So Akamai is still waiting for the 100 response code, which it never gets, so the request times out, which translates to the TaskCanceledException thrown by the HttpClient.

I still don't know why HttpClient.DefaultRequestHeaders.ExpectContinue defaults to true rather than false, but that's a question for another day.

Sign up to request clarification or add additional context in comments.

1 Comment

Some servers don't correctly handle the expect header. The twitter API used to be one of these. The Expect header is designed to allow a server to refuse an oversized request payload. Turning off expect header will do no harm if the server doesn't support it and will in fact increase performance by reducing a round trip.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.