mirror of
https://github.com/zoriya/octokit.net.git
synced 2025-12-05 23:06:10 +00:00
213 lines
7.4 KiB
C#
213 lines
7.4 KiB
C#
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Net;
|
|
using System.Runtime.Serialization;
|
|
using System.Security;
|
|
using Octokit.Internal;
|
|
|
|
namespace Octokit
|
|
{
|
|
/// <summary>
|
|
/// Represents errors that occur from the GitHub API.
|
|
/// </summary>
|
|
[Serializable]
|
|
[SuppressMessage("Microsoft.Design", "CA1032:ImplementStandardExceptionConstructors",
|
|
Justification = "These exceptions are specific to the GitHub API and not general purpose exceptions")]
|
|
public class ApiException : Exception
|
|
{
|
|
// This needs to be hard-coded for translating GitHub error messages.
|
|
static readonly IJsonSerializer _jsonSerializer = new SimpleJsonSerializer();
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
#pragma warning disable CS0618 // Response() is obsolete but we need this as a default as Response passed down cannot be null
|
|
public ApiException() : this(new Response())
|
|
#pragma warning restore CS0618 // Response() is obsolete but we need this as a default as Response passed down cannot be null
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
/// <param name="message">The error message</param>
|
|
/// <param name="httpStatusCode">The HTTP status code from the response</param>
|
|
public ApiException(string message, HttpStatusCode httpStatusCode)
|
|
: this(GetApiErrorFromExceptionMessage(message), httpStatusCode, null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
/// <param name="message">The error message</param>
|
|
/// <param name="innerException">The inner exception</param>
|
|
public ApiException(string message, Exception innerException)
|
|
: this(GetApiErrorFromExceptionMessage(message), 0, innerException)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
/// <param name="response">The HTTP payload from the server</param>
|
|
public ApiException(IResponse response)
|
|
: this(response, null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
/// <param name="response">The HTTP payload from the server</param>
|
|
/// <param name="innerException">The inner exception</param>
|
|
public ApiException(IResponse response, Exception innerException)
|
|
: base(null, innerException)
|
|
{
|
|
Ensure.ArgumentNotNull(response, nameof(response));
|
|
|
|
StatusCode = response.StatusCode;
|
|
ApiError = GetApiErrorFromExceptionMessage(response);
|
|
HttpResponse = response;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException
|
|
/// </summary>
|
|
/// <param name="innerException">The inner exception</param>
|
|
protected ApiException(ApiException innerException)
|
|
{
|
|
Ensure.ArgumentNotNull(innerException, nameof(innerException));
|
|
|
|
StatusCode = innerException.StatusCode;
|
|
ApiError = innerException.ApiError;
|
|
}
|
|
|
|
protected ApiException(HttpStatusCode statusCode, Exception innerException)
|
|
: base(null, innerException)
|
|
{
|
|
ApiError = new ApiError();
|
|
StatusCode = statusCode;
|
|
}
|
|
|
|
protected ApiException(ApiError apiError, HttpStatusCode statusCode, Exception innerException)
|
|
: base(null, innerException)
|
|
{
|
|
Ensure.ArgumentNotNull(apiError, nameof(apiError));
|
|
|
|
ApiError = apiError;
|
|
StatusCode = statusCode;
|
|
}
|
|
|
|
public IResponse HttpResponse { get; private set; }
|
|
|
|
public override string Message
|
|
{
|
|
get { return ApiErrorMessageSafe ?? "An error occurred with this API request"; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// The HTTP status code associated with the response
|
|
/// </summary>
|
|
public HttpStatusCode StatusCode { get; private set; }
|
|
|
|
/// <summary>
|
|
/// The raw exception payload from the response
|
|
/// </summary>
|
|
public ApiError ApiError { get; private set; }
|
|
|
|
static ApiError GetApiErrorFromExceptionMessage(IResponse response)
|
|
{
|
|
string responseBody = response != null ? response.Body as string : null;
|
|
return GetApiErrorFromExceptionMessage(responseBody);
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
|
|
static ApiError GetApiErrorFromExceptionMessage(string responseContent)
|
|
{
|
|
try
|
|
{
|
|
if (!string.IsNullOrEmpty(responseContent))
|
|
{
|
|
return _jsonSerializer.Deserialize<ApiError>(responseContent) ?? new ApiError(responseContent);
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
|
|
return new ApiError(responseContent);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs an instance of ApiException.
|
|
/// </summary>
|
|
/// <param name="info">
|
|
/// The <see cref="SerializationInfo"/> that holds the
|
|
/// serialized object data about the exception being thrown.
|
|
/// </param>
|
|
/// <param name="context">
|
|
/// The <see cref="StreamingContext"/> that contains
|
|
/// contextual information about the source or destination.
|
|
/// </param>
|
|
protected ApiException(SerializationInfo info, StreamingContext context)
|
|
: base(info, context)
|
|
{
|
|
if (info == null) return;
|
|
StatusCode = (HttpStatusCode)info.GetInt32("HttpStatusCode");
|
|
ApiError = (ApiError)info.GetValue("ApiError", typeof(ApiError));
|
|
}
|
|
|
|
[SecurityCritical]
|
|
public override void GetObjectData(SerializationInfo info, StreamingContext context)
|
|
{
|
|
base.GetObjectData(info, context);
|
|
info.AddValue("HttpStatusCode", StatusCode);
|
|
info.AddValue("ApiError", ApiError);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the inner error message from the API response
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Returns null if ApiError is not populated
|
|
/// </remarks>
|
|
protected string ApiErrorMessageSafe
|
|
{
|
|
get
|
|
{
|
|
if (ApiError != null && !string.IsNullOrWhiteSpace(ApiError.Message))
|
|
{
|
|
return ApiError.Message;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the inner http response body from the API response
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Returns empty string if HttpResponse is not populated or if
|
|
/// response body is not a string
|
|
/// </remarks>
|
|
protected string HttpResponseBodySafe
|
|
{
|
|
get
|
|
{
|
|
return HttpResponse?.ContentType != null
|
|
&& !HttpResponse.ContentType.StartsWith("image/", StringComparison.OrdinalIgnoreCase)
|
|
&& HttpResponse.Body is string @string
|
|
? @string : string.Empty;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
var original = base.ToString();
|
|
return original + Environment.NewLine + HttpResponseBodySafe;
|
|
}
|
|
}
|
|
}
|