0

I am making a HEAD request to an external server to identify if my credentials are valid. However, the external server (that I don't have control over) is processing my request as if it's a GET (and starts generating a CSV to stream that can take up to 30 minutes to generate.)

If my credentials are incorrect, I immediately get back a 401. If the request takes a long time (more than 10 seconds), I know my credentials are correct b/c the external server has started to generate the CSV.

I want my request to timeout after 10 seconds. But I'm having issues w/ HttpWebRequest.Timeout and HttpWebRequest.ReadWriteTimeout... the values don't seem to be acknowledged & my request will wait seemingly forever for the full response.

How do I get the timeouts to actually happen?

Here's what I've got:

public async Task<bool> GetResponse(string url, string username, string secret)
{
    HttpWebRequest _request = new HttpWebRequest(url);
    NetworkCredential _credential = new NetworkCredential(username, secret);
    CredentialCache _credentialCache = new CredentialCache { { url, "Basic", _credential } };
    _request.PreAuthenticate = true;
    _request.Credentials = _credentialCache;

    // I set all 3 of these timeouts while testing but none of them seem to be acknowledged.
    _request.ContinueTimeout = 10000;
    _request.ReadWriteTimeout = 10000;
    _request.Timeout = 10000;

    try
    {
        using (HttpWebResponse _response = await _request.GetResponseAsync())
        {
            if (_response.StatusCode == HttpStatusCode.OK && _response.ContentType.Contains("text/csv")
            {
                return true; // successfully retrieved response.
            }

            return false; // failed to retrieve successful response.
        }
    }
    catch (WebException ex)
    {
        if (ex.Status = WebExceptionStatus.Timeout)
        {
            return true; // timeout == success.
        }

        return false;
    }
}

JED
  • 1,538
  • 2
  • 19
  • 47

1 Answers1

0

It took me way too long to figure out... HttpWebRequest.GetResponseAsync() does not acknowledge the Timeout. But HttpWebRequest.GetResponse() does. You have to use the synchronous version.

Also, I only needed to set the Timeout, not the ReadWriteTimeout or ContinueTimeout.

EDIT

I ultimately decided to use HttpClient instead of HttpWebRequest. Here's what that looks like:

public sealed class MyClass : IMyClass
{
    private static readonly HttpClient _httpClient = new HttpClient();

    public async Task<bool> MyMethod(string url, string username, string secret)
    {
        try
        {
            CancellationTokenSource _cts = new CancellationTokenSource(Timespan.FromSeconds(10));
           _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
                "Basic",
                Convert.ToBase64String(Encoding.UTF8.GetBytes($"{username}:{secret}")))); 
            HttpResponseMessage _response = await _httpClient.SendAsync(
                new HttpRequestMessage(HttpMethod.Head, model.ApiUrl),
                HttpCompletionOption.ResponseHeadersRead,
                _cts.Token);

            switch (_response.StatusCode)
            {
                case HttpStatusCode.OK:
                    return true;
                default:
                    return false;
            }
        }
        catch (TaskCanceledException)
        {
            return true;
        }
    }
}
JED
  • 1,538
  • 2
  • 19
  • 47