Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RestSharp GetAsync ignores response error status codes

The comment on RestSharp's GetAsync<> method explicitly mentions:

Execute the request using GET HTTP method. Exception will be thrown if the request does not succeed.

I'm not sure how to interpret that. I'd expect it to throw an exception when a non-succes HTTP status code is returned. This does not seem to be the case. When a 404 or 500 status is returned, the method happily tries to deserialize the response. Only when the response body contains invalid json (or xml, or whatever is 'accepted') will an error be thrown.

Am I missing something? How should I, using these async methods, handle such error responses?

like image 925
Vincent Sels Avatar asked Feb 28 '26 07:02

Vincent Sels


2 Answers

That behavior threw me off too.

Looking at the source code for RestClientExtensions at GitHub, the GetAsyncmethod is implemented as:

public static async Task<T> GetAsync<T>(this IRestClient client, IRestRequest request, CancellationToken cancellationToken = default)
{
    var response = await client.ExecuteGetAsync<T>(request, cancellationToken);
    ThrowIfError(response);
    return response.Data;
}

You would expect that ThrowIfErrorwould look at the HTTP Status Code, but looking at RestSharp documentation for error handling, it says:

If there is a network transport error (network is down, failed DNS lookup, etc), RestResponse.ResponseStatus will be set to ResponseStatus.Error, otherwise it will be ResponseStatus.Completed.

If an API returns a 404, ResponseStatus will still be Completed.

Which you can confirm by looking at ThrowIfError implementation:

static void ThrowIfError(IRestResponse response)
{
    var exception = response.ResponseStatus switch
    {
        ResponseStatus.Aborted   => new WebException("Request aborted", response.ErrorException),
        ResponseStatus.Error     => response.ErrorException,
        ResponseStatus.TimedOut  => new TimeoutException("Request timed out", response.ErrorException),
        ResponseStatus.None      => null,
        ResponseStatus.Completed => null,
        _                        => throw response.ErrorException ?? new ArgumentOutOfRangeException()
    };

    if (exception != null)
        throw exception;
}

As for your question:

How should I, using these async methods, handle such error responses?

You can't :(.

I believe you would have to implement your own async implementation of Get<T>.

Here's an example of what I did:

private Task<T> GetAsync<T>(RestRequest request)
{
    return Task.Run(() =>
    {
        var response = client.Get<T>(request);
        if (response.IsSuccessful)
            return response.Data;

        //handle the errors as you wish. In my case, the api I work with always
        //returns a bad request with a message property when it occurs...
        var errorData = JsonConvert.DeserializeObject<ApiMessage>(response.Content);
        throw new Exception(errorData.Message);
    });
}

public class ApiMessage
{
    public string Message { get; set; }
}

Usage:

public Task<MyModel> SomeRequest()
{
    var request = new RestRequest()
    {
        Resource = "some-resource",
    };

    return GetAsync<MyModel>(request);
}

Source:

like image 93
Mari Faleiros Avatar answered Mar 02 '26 05:03

Mari Faleiros


Use RestClient.ExecuteTaskAsync() method instead which gives you access to useful properties of IRestResponse such as StatusCode, ErrorException & ErrorMessage etc

like image 23
Caltor Avatar answered Mar 02 '26 04:03

Caltor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!