-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Latest Proposal
HttpRequestException.StatusCode property
Rationale and Usage
A new nullable HttpRequestException.StatusCode property exposes a response's status code if it has been already received, otherwise it's set to null. This will enable a direct access to the status code on exceptions thrown from HttpClient's simple GET methods and HttpResponseMessage.EnsureSuccessStatusCode(). New HttpRequestException constructors taking a status code will initialize that property.
try
{
string response = httpClient.GetStringAsync(requestUri);
...
}
catch(HttpRequestException e)
{
if (e.StatusCode == HttpStatusCode.MovedPermanently)
{
...
}
}Proposed API
public class HttpRequestException : Exception
{
...
+ public HttpStatusCode? StatusCode { get; }
public HttpRequestException(string message)
{...}
+ public HttpRequestException(string message, HttpStatusCode? statusCode)
+ {...}
public HttpRequestException(string message, Exception inner)
{...}
+ public HttpRequestException(string message, Exception inner, HttpStatusCode? statusCode)
+ {...}
}Original Proposal
Proposed solution to dotnet/corefx#9227, dotnet/corefx#24253 and any related issues:
Linking in SteamRE/SteamKit#517 as well.
I've had the following issue in various codebases:
- Some HTTP-based code expects a 200-series response.
- The HTTP-based code uses
HttpResponseMessage.EnsureSuccessStatusCode() - The calling code catches the exception and wants to do something based on the status code.
- The calling code does not have access to the original HTTP response status code, or any headers, etc.
In the old .NET HTTP APIs, this was straightforward because WebException includes the status code and the response object, where available.
Adding StatusCode to HttpRequestException has been rejected in the above-linked issues due to it being of little use in most cases.
Would it be possible instead to create a subclass of HttpRequestException, and have EnsureSuccessStatusCode() throw that instead?
Something resembling the following ought to do the trick:
public class HttpResponseException : HttpRequestException
{
public HttpResponseException()
{
...
}
public HttpResponseException(string message, Exception innerException)
{
...
}
public HttpResponseException(string message, int statusCode)
{
...
}
public HttpResponseException(string message, int statusCode, Exception innerException)
{
...
}
public int StatusCode { get; }
}This would achieve the following:
HttpRequestExceptiondoes not have a majority-useless field.- Code that catches
HttpRequestExceptionwould continue to function as-is. - Networking errors, unreachable servers etc. will continue to throw
HttpRequestException. - New code can opt in to catching
HttpResponseException, and will then have access to the original HTTP Status Code.
Optionally, for consideration, the exception could also include the whole HttpResponseMessage object in line with good old WebException.