1

I need to handle the timeout as a special case, but flurl does not give me expected exception on some cases.

Here is my simplified code to do so.

try
{           
    // Call Listener here with the result of the process
    using (IFlurlClient flurlClient = new FlurlClient(Url))
    {
        string response = await flurlClient
            .Configure(s => s.Timeout = TimeSpan.FromSeconds(130))
            .WithOAuthBearerToken(accessToken)
            .Request()
            .PostJsonAsync(result)
            .ReceiveString();

        Logger.LogInformation(response);
        ListenerResponse listenerResponse = JsonConvert.DeserializeObject<ListenerResponse>(response);
        Logger.LogInformation(listenerResponse.Success.ToString());

        if (!listenerResponse.Success)
        {
            throw new RejectedException("Listener rejected the request.");
        }
    }
}
catch (FlurlHttpTimeoutException ex)
{
    // throws with this message: "Call timed out: POST https://..."
    Logger.LogError(ex, $"Could not reach to Listener at: {Url}.");
    throw;
}
catch (FlurlHttpException ex)
{
    // throws with this message: "Call failed. Connection timed out POST https://..."
    Logger.LogError(ex, ex.Message); 
    throw;
}

What's happening is when I set the timeout below a certain value (<130), flurl throws the expected FlurlHttpTimeoutException. But if I set the timeout above that value(>=130), flurl this time throws the more general FlurlHttpException.

Notice that the exception messages differ slightly:

FlurlHttpTimeoutException

Call timed out: POST https://...

FlurlHttpException

Call failed. Connection timed out POST https://...

Has anyone any idea how I can fix it to behave as expected - throwing FlurlHttpTimeoutException for all timeout values?

Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
  • When it's >130, what is the type/details of FlurlHttpException.InnerException? Also, is this a Xamarin/Android project? – Todd Menier Apr 29 '20 at 12:50
  • I have found the trick to get it working by chance, it was the `SocketHttpHandler.PooledConnectionLifetime`. When I increased it over 130 it started throwing the correct exception. And this is a dotnet core 2.1 project for aws lambdas. – Tolga Evcimen Apr 29 '20 at 15:53

1 Answers1

0

I ended up doing something like this that solved the issue, not sure if that's the right approach to go at it, but it did the trick.

/// <summary>
/// Gets a flurl client
/// </summary>
/// <returns></returns>
private IFlurlClient GetFlurlClient()
{
    return new FlurlClient(new HttpClient(new SocketsHttpHandler
    {
        PooledConnectionLifetime = TimeSpan.FromSeconds(ListenerTimeout + 10)
    })
    {
        BaseAddress = new Uri(ListenerUrl)
    })
        .Configure(s => s.Timeout = TimeSpan.FromSeconds(ListenerTimeout));
}
Tolga Evcimen
  • 7,112
  • 11
  • 58
  • 91
  • @Todd Menier, can you confirm this is a valid work around? It sure takes care of the problem but not sure if I'm introducing any side effects here. – Tolga Evcimen Apr 29 '20 at 15:55
  • The side effects would be that you're taking control of FlurlClient instance management away from Flurl (but it looks like you might want to manage that yourself anyway), and you'll lose the ability to fake HTTP calls in tests. I'd recommend using a [factory](https://flurl.dev/docs/configuration/#httpclientfactory) instead. – Todd Menier Apr 29 '20 at 18:29
  • Good suggestion, I'll change it to utilize the factory, looks more solid anyways. Though it's confusing that all my unit tests are still passing (I'm faking with `HttpTest` for this method many times). – Tolga Evcimen Apr 29 '20 at 21:45