Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HttpClient - how to figure out if server is down faster?

I'm using .NET HttpClient to send requests to my server. I have set HttpClient.Timeout property to 10 seconds so i'm getting a A task was cancelled exception whenever the server fails to process my request in less than 10 seconds. Good until here.

However, if the server is shut down it takes for the HttpClient around ~20 seconds to return a proper exception such as the one in the picture. enter image description here

I would like to see this exception faster than 10 seconds to be able to distinguish between Server Down and Operation took too long scenarios. I can't find anything about this in msdn documentation. Is there any timeout that can be set on the HttpClient?

Here's how i'm constructing the HttpClient

 var webRequestHandler = new WebRequestHandler
        {
            UseProxy = false,
            Proxy = null,
            AllowPipelining = false,
            ContinueTimeout = TimeSpan.Zero,
            UseCookies = false,
            AllowAutoRedirect = false,
        };
 var httpClient = new HttpClient(webRequestHandler);
 httpClient.Timeout = timeout;

  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Accept", "application/json");
  httpClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", userAgent);
  httpClient.DefaultRequestHeaders.ExpectContinue = false;
like image 634
Dan Dinu Avatar asked Nov 20 '14 10:11

Dan Dinu


2 Answers

This answer just extends @brz's example.

You can use this approach that does not block the thread ( Task.Wait blocks the thread)

var timeout = Task.Delay(10000); // 10 seconds timeout
var request = httpClient.GetAsync("http://www.google.com");

await Task.WhenAny(timeout, request); // wait for either timeout or the request

if (timeout.IsCompleted) // if the timeout ended first, then handle it
{
    // handle timeout
}

// otherwise continue processing the request result
var response = await request;
like image 82
vtortola Avatar answered Sep 19 '22 16:09

vtortola


You can't handle this with timeouts, as mentioned in msdn:

A Domain Name System (DNS) query may take up to 15 seconds to return or time out. If your request contains a host name that requires resolution and you set Timeout to a value less than 15 seconds, it may take 15 seconds or more before a WebException is thrown to indicate a timeout on your request.

However, another approach would be wrapping your request in another task and handle timeout from there:

var task = Task.Run(() => { 
                var req = new HttpClient().GetAsync("http://www.google.com");
                if (!req.Wait(10000))//wait for 10 seconds
                    throw new TaskCanceledException(req);
            });
task.Wait();
like image 38
brz Avatar answered Sep 18 '22 16:09

brz