using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
namespace RestEase
{
///
/// Exception thrown when a bad API response is received
///
public class ApiException : Exception
{
///
/// Gets the method used to make the request which failed
///
public HttpMethod RequestMethod { get; }
///
/// Gets the URI to which the request which failed wras made
///
public Uri RequestUri { get; }
///
/// Gets the HTTP status code received
///
public HttpStatusCode StatusCode { get; }
///
/// Gets the ReasonPhrase associated with the response
///
public string ReasonPhrase { get; }
///
/// Gets the headers associated with the response
///
public HttpResponseHeaders Headers { get; }
///
/// Gets the content headers associated with the response
///
public HttpContentHeaders? ContentHeaders { get; }
///
/// Gets the content associated with the response, if any
///
public string? Content { get; }
///
/// Gets a value indicating whether any content is associated with the response
///
public bool HasContent => !string.IsNullOrWhiteSpace(this.Content);
///
/// Initialises a new instance of the class with the given
///
/// Request which triggered the exception
/// provided by the
/// String content, as read from , if there is a response content
public ApiException(HttpRequestMessage request, HttpResponseMessage response, string? contentString)
: this(request.Method,
request.RequestUri,
response.StatusCode,
response.ReasonPhrase,
response.Headers,
response.Content?.Headers,
contentString)
{
}
///
/// Initialises a new instance of the class with the given components
///
/// used to make the request which failed
/// to which the request which failed was made
/// returned by the endpoint
/// provided by
/// s associated with the response
/// associated with the response content, if there is a response content
/// String content, as read from , if there is a response content
public ApiException(
HttpMethod requestMethod,
Uri requestUri,
HttpStatusCode statusCode,
string reasonPhrase,
HttpResponseHeaders headers,
HttpContentHeaders? contentHeaders,
string? contentString)
: base($"{requestMethod} \"{requestUri}\" failed because response status code does not indicate success: {(int)statusCode} ({reasonPhrase}).")
{
this.RequestMethod = requestMethod;
this.Data[nameof(this.RequestMethod)] = requestMethod.Method;
this.RequestUri = requestUri;
this.Data[nameof(this.RequestUri)] = requestUri;
this.StatusCode = statusCode;
this.Data[nameof(this.StatusCode)] = statusCode;
this.ReasonPhrase = reasonPhrase;
this.Data[nameof(this.ReasonPhrase)] = reasonPhrase;
this.Headers = headers;
this.ContentHeaders = contentHeaders;
this.Content = contentString;
}
///
/// Create a new , by reading the response asynchronously content as a string
///
/// Request which triggered the exception
/// Response received from the
/// A new created from the
public static async Task CreateAsync(HttpRequestMessage request, HttpResponseMessage response)
{
if (response.Content == null)
return new ApiException(request, response, null);
string? contentString = null;
try
{
using (var content = response.Content)
{
contentString = await content.ReadAsStringAsync().ConfigureAwait(false);
}
}
catch
{ } // Don't want to hide the original exception with a new one
return new ApiException(request, response, contentString);
}
}
}