Skip to content

Commit

Permalink
Merge pull request #104 from Archomeda/refactor/web-exceptions
Browse files Browse the repository at this point in the history
Refactor web API exceptions
  • Loading branch information
Archomeda authored Sep 28, 2021
2 parents 9ef0c49 + c4774db commit 9418e23
Show file tree
Hide file tree
Showing 18 changed files with 73 additions and 137 deletions.
3 changes: 2 additions & 1 deletion Gw2Sharp.Tests/WebApi/Exceptions/RequestExceptionTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using Gw2Sharp.WebApi.Exceptions;
using Gw2Sharp.WebApi.Http;
using Gw2Sharp.WebApi.V2.Models;
using NSubstitute;
using Xunit;

Expand All @@ -12,7 +13,7 @@ public class RequestExceptionTests
public void ConstructorTest()
{
var request = Substitute.For<IWebApiRequest>();
var response = Substitute.For<IWebApiResponse>();
var response = Substitute.For<IWebApiResponse<ErrorObject>>();
var innerException = new NotImplementedException();
string message = "test exception";

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Gw2Sharp.WebApi.Exceptions;
using Gw2Sharp.WebApi.Http;
using Gw2Sharp.WebApi.V2.Models;
using NSubstitute;
using Xunit;

Expand All @@ -11,7 +12,7 @@ public class UnexpectedStatusExceptionTests
public void ConstructorTest()
{
var request = Substitute.For<IWebApiRequest>();
var response = Substitute.For<IWebApiResponse>();
var response = Substitute.For<IWebApiResponse<ErrorObject>>();
string message = "test exception";

var exception = new UnexpectedStatusException(request, response);
Expand Down
12 changes: 6 additions & 6 deletions Gw2Sharp.Tests/WebApi/Middleware/ExceptionMiddlewareTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
using Gw2Sharp.WebApi.Exceptions;
using Gw2Sharp.WebApi.Http;
using Gw2Sharp.WebApi.Middleware;
using Gw2Sharp.WebApi.V2.Models;
using NSubstitute;
using Xunit;

Expand Down Expand Up @@ -46,7 +45,7 @@ public async Task ExceptionRequestTest(string errorText, HttpStatusCode statusCo
using (new AssertionScope())
{
Func<Task> act = () => middleware.OnRequestAsync(context, (c, t) => Task.FromResult(response));
var exception = (await act.Should().ThrowAsync<UnexpectedStatusException<ErrorObject>>()
var exception = (await act.Should().ThrowAsync<UnexpectedStatusException>()
.WithMessage(errorText))
.Which;

Expand All @@ -71,7 +70,7 @@ public async Task ExceptionNoJsonRequestTest(string body, HttpStatusCode statusC
using (new AssertionScope())
{
Func<Task> act = () => middleware.OnRequestAsync(context, (c, t) => Task.FromResult(response));
var exception = (await act.Should().ThrowAsync<UnexpectedStatusException<ErrorObject>>()
var exception = (await act.Should().ThrowAsync<UnexpectedStatusException>()
.WithMessage(body))
.Which;

Expand All @@ -83,21 +82,22 @@ public async Task ExceptionNoJsonRequestTest(string body, HttpStatusCode statusC
[Fact]
public async Task UnexpectedStatusExceptionRequestTest()
{
const string MESSAGE = "{\"error\":\"Some nice error message\"}";
const string MESSAGE = "Some nice error message";
const string JSON = "{\"error\":\"" + MESSAGE + "\"}";

var connection = Substitute.For<IConnection>();
var request = Substitute.For<IWebApiRequest>();
var context = new MiddlewareContext(connection, request);
var response = Substitute.For<IWebApiResponse>();
response.Content.Returns(MESSAGE);
response.Content.Returns(JSON);
response.StatusCode.Returns((HttpStatusCode)499);

var middleware = new ExceptionMiddleware();

Func<Task> act = () => middleware.OnRequestAsync(context, (c, t) => Task.FromResult(response));
(await act.Should().ThrowAsync<UnexpectedStatusException>())
.WithMessage(MESSAGE)
.Which.Response?.Content.Should().Be(MESSAGE);
.Which.Response?.Content.Message.Should().Be(MESSAGE);
}
}
}
6 changes: 3 additions & 3 deletions Gw2Sharp/WebApi/Exceptions/AuthorizationRequiredException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails to authorize (code 403).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
public class AuthorizationRequiredException : UnexpectedStatusException<ErrorObject>
/// <seealso cref="UnexpectedStatusException" />
public class AuthorizationRequiredException : UnexpectedStatusException
{
/// <summary>
/// Creates a new <see cref="AuthorizationRequiredException"/>.
Expand All @@ -18,7 +18,7 @@ public class AuthorizationRequiredException : UnexpectedStatusException<ErrorObj
/// <param name="error">The error.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/>, <paramref name="response"/> or <paramref name="error"/> is <c>null</c>.</exception>
public AuthorizationRequiredException(IWebApiRequest request, IWebApiResponse<ErrorObject> response, AuthorizationError error) :
base(request, response, response?.Content.Message ?? string.Empty)
base(request, response)
{
this.AuthorizationError = error;
}
Expand Down
6 changes: 3 additions & 3 deletions Gw2Sharp/WebApi/Exceptions/BadRequestException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a bad request was done (code 400).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
public class BadRequestException : UnexpectedStatusException<ErrorObject>
/// <seealso cref="UnexpectedStatusException" />
public class BadRequestException : UnexpectedStatusException
{
/// <summary>
/// Creates a new <see cref="BadRequestException"/>.
Expand All @@ -18,7 +18,7 @@ public class BadRequestException : UnexpectedStatusException<ErrorObject>
/// <param name="error">The error.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public BadRequestException(IWebApiRequest request, IWebApiResponse<ErrorObject> response, BadRequestError error) :
base(request, response, response?.Content.Message ?? string.Empty)
base(request, response)
{
this.BadRequestError = error;
}
Expand Down
5 changes: 3 additions & 2 deletions Gw2Sharp/WebApi/Exceptions/InvalidAccessTokenException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails to authorize due to an invalid API key (code 403).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
/// <seealso cref="AuthorizationRequiredException" />
public class InvalidAccessTokenException : AuthorizationRequiredException
{
/// <summary>
Expand All @@ -17,6 +17,7 @@ public class InvalidAccessTokenException : AuthorizationRequiredException
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public InvalidAccessTokenException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, AuthorizationError.InvalidKey) { }
base(request, response, AuthorizationError.InvalidKey)
{ }
}
}
5 changes: 3 additions & 2 deletions Gw2Sharp/WebApi/Exceptions/MembershipRequiredException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails to authorize due to the owner of the API key not being a member of the guild (code 403).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
/// <seealso cref="AuthorizationRequiredException" />
public class MembershipRequiredException : AuthorizationRequiredException
{
/// <summary>
Expand All @@ -17,6 +17,7 @@ public class MembershipRequiredException : AuthorizationRequiredException
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public MembershipRequiredException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, AuthorizationError.MembershipRequired) { }
base(request, response, AuthorizationError.MembershipRequired)
{ }
}
}
5 changes: 3 additions & 2 deletions Gw2Sharp/WebApi/Exceptions/MissingScopesException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails to authorize due to missing permissions (code 403).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
/// <seealso cref="AuthorizationRequiredException" />
public class MissingScopesException : AuthorizationRequiredException
{
/// <summary>
Expand All @@ -17,6 +17,7 @@ public class MissingScopesException : AuthorizationRequiredException
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public MissingScopesException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, AuthorizationError.MissingScopes) { }
base(request, response, AuthorizationError.MissingScopes)
{ }
}
}
7 changes: 4 additions & 3 deletions Gw2Sharp/WebApi/Exceptions/NotFoundException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a response cannot be found (code 404).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
public class NotFoundException : UnexpectedStatusException<ErrorObject>
/// <seealso cref="UnexpectedStatusException" />
public class NotFoundException : UnexpectedStatusException
{
/// <summary>
/// Creates a new <see cref="NotFoundException"/>.
Expand All @@ -17,6 +17,7 @@ public class NotFoundException : UnexpectedStatusException<ErrorObject>
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public NotFoundException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, response?.Content.Message ?? string.Empty) { }
base(request, response)
{ }
}
}
66 changes: 11 additions & 55 deletions Gw2Sharp/WebApi/Exceptions/RequestException.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using Gw2Sharp.WebApi.Http;
using Gw2Sharp.WebApi.V2.Models;

namespace Gw2Sharp.WebApi.Exceptions
{
/// <summary>
/// A generic request exception used for the web API.
/// </summary>
public class RequestException : RequestException<string>
public class RequestException : Exception
{
/// <summary>
/// Creates a new <see cref="RequestException" />.
Expand All @@ -15,7 +16,8 @@ public class RequestException : RequestException<string>
/// <param name="message">The message.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, string message) :
base(request, message) { }
this(request, null, message, null)
{ }

/// <summary>
/// Creates a new <see cref="RequestException" />.
Expand All @@ -24,8 +26,9 @@ public RequestException(IWebApiRequest request, string message) :
/// <param name="response">The response.</param>
/// <param name="message">The message.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, IWebApiResponse<string>? response, string message) :
base(request, response, message) { }
public RequestException(IWebApiRequest request, IWebApiResponse<ErrorObject>? response, string message) :
this(request, response, message, null)
{ }

/// <summary>
/// Creates a new <see cref="RequestException" />.
Expand All @@ -35,7 +38,8 @@ public RequestException(IWebApiRequest request, IWebApiResponse<string>? respons
/// <param name="innerException">The inner exception.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, string message, Exception? innerException) :
base(request, message, innerException) { }
this(request, null, message, innerException)
{ }

/// <summary>
/// Creates a new <see cref="RequestException" />.
Expand All @@ -44,55 +48,7 @@ public RequestException(IWebApiRequest request, string message, Exception? inner
/// <param name="response">The response.</param>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, IWebApiResponse<string>? response, string message, Exception innerException) :
base(request, response, message, innerException) { }
}


/// <summary>
/// A generic request exception used for the web API.
/// </summary>
/// <typeparam name="TResponse">The response object.</typeparam>
public class RequestException<TResponse> : Exception
{
/// <summary>
/// Creates a new <see cref="RequestException{TResponse}" />.
/// </summary>
/// <param name="request">The original request.</param>
/// <param name="message">The message.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, string message) :
this(request, null, message, null) { }

/// <summary>
/// Creates a new <see cref="RequestException{TResponse}" />.
/// </summary>
/// <param name="request">The original request.</param>
/// <param name="response">The response.</param>
/// <param name="message">The message.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, IWebApiResponse<TResponse>? response, string message) :
this(request, response, message, null) { }

/// <summary>
/// Creates a new <see cref="RequestException{TResponse}" />.
/// </summary>
/// <param name="request">The original request.</param>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="message"/> is <c>null</c>.</exception>
public RequestException(IWebApiRequest request, string message, Exception? innerException) :
this(request, null, message, innerException) { }

/// <summary>
/// Creates a new <see cref="RequestException{TResponse}" />.
/// </summary>
/// <param name="request">The original request.</param>
/// <param name="response">The response.</param>
/// <param name="message">The message.</param>
/// <param name="innerException">The inner exception.</param>
public RequestException(IWebApiRequest request, IWebApiResponse<TResponse>? response, string message, Exception? innerException) :
public RequestException(IWebApiRequest request, IWebApiResponse<ErrorObject>? response, string message, Exception? innerException) :
base(message, innerException)
{
this.Request = request ?? throw new ArgumentNullException(nameof(request));
Expand All @@ -107,6 +63,6 @@ public RequestException(IWebApiRequest request, IWebApiResponse<TResponse>? resp
/// <summary>
/// Gets the response.
/// </summary>
public IWebApiResponse<TResponse>? Response { get; }
public IWebApiResponse<ErrorObject>? Response { get; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails to authorize due to the owner not being a guild leader (code 403).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
/// <seealso cref="AuthorizationRequiredException" />
public class RestrictedToGuildLeadersException : AuthorizationRequiredException
{
/// <summary>
Expand All @@ -17,6 +17,7 @@ public class RestrictedToGuildLeadersException : AuthorizationRequiredException
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public RestrictedToGuildLeadersException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, AuthorizationError.AccessRestrictedToGuildLeaders) { }
base(request, response, AuthorizationError.AccessRestrictedToGuildLeaders)
{ }
}
}
7 changes: 4 additions & 3 deletions Gw2Sharp/WebApi/Exceptions/ServerErrorException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails due to an internal server error (code 500).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
public class ServerErrorException : UnexpectedStatusException<ErrorObject>
/// <seealso cref="UnexpectedStatusException" />
public class ServerErrorException : UnexpectedStatusException
{
/// <summary>
/// Creates a new <see cref="ServerErrorException"/>.
Expand All @@ -17,6 +17,7 @@ public class ServerErrorException : UnexpectedStatusException<ErrorObject>
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public ServerErrorException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, response?.Content.Message ?? string.Empty) { }
base(request, response)
{ }
}
}
7 changes: 4 additions & 3 deletions Gw2Sharp/WebApi/Exceptions/ServiceUnavailableException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace Gw2Sharp.WebApi.Exceptions
/// <summary>
/// A web API specific exception that's used when a request fails due to the service being unavailable (code 500).
/// </summary>
/// <seealso cref="UnexpectedStatusException{Error}" />
public class ServiceUnavailableException : UnexpectedStatusException<ErrorObject>
/// <seealso cref="UnexpectedStatusException" />
public class ServiceUnavailableException : UnexpectedStatusException
{
/// <summary>
/// Creates a new <see cref="ServiceUnavailableException"/>.
Expand All @@ -17,6 +17,7 @@ public class ServiceUnavailableException : UnexpectedStatusException<ErrorObject
/// <param name="response">The response.</param>
/// <exception cref="ArgumentNullException"><paramref name="request"/> or <paramref name="response"/> is <c>null</c>.</exception>
public ServiceUnavailableException(IWebApiRequest request, IWebApiResponse<ErrorObject> response) :
base(request, response, response?.Content.Message ?? string.Empty) { }
base(request, response)
{ }
}
}
Loading

0 comments on commit 9418e23

Please sign in to comment.