From efe65eb3c180642013c6a9ce6c0e3f1826554de8 Mon Sep 17 00:00:00 2001 From: Paul Evans Date: Tue, 22 Nov 2016 15:35:54 -0800 Subject: [PATCH] Add support for 403 responses (#7) * Add support for 403 responses --- .gitignore | 5 +++ ...rRiposteFrameworkErrorHandlerListener.java | 14 +++++++ .../exception/Forbidden403Exception.java | 37 +++++++++++++++++++ ...osteFrameworkErrorHandlerListenerTest.java | 6 +++ .../exception/Forbidden403ExceptionTest.java | 32 ++++++++++++++++ 5 files changed, 94 insertions(+) create mode 100644 riposte-spi/src/main/java/com/nike/riposte/server/error/exception/Forbidden403Exception.java create mode 100644 riposte-spi/src/test/java/com/nike/riposte/server/error/exception/Forbidden403ExceptionTest.java diff --git a/.gitignore b/.gitignore index a354daf1..dbc6fc86 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ gradle-app.setting out/ classes/ .idea_modules/ + +### Eclipse stuff +.project +.settings +.classpath diff --git a/riposte-spi/src/main/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListener.java b/riposte-spi/src/main/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListener.java index 7d86c8ab..1a8171d0 100644 --- a/riposte-spi/src/main/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListener.java +++ b/riposte-spi/src/main/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListener.java @@ -13,6 +13,7 @@ import com.nike.internal.util.StringUtils; import com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException; import com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException; +import com.nike.riposte.server.error.exception.Forbidden403Exception; import com.nike.riposte.server.error.exception.HostnameResolutionException; import com.nike.riposte.server.error.exception.InvalidCharsetInContentTypeHeaderException; import com.nike.riposte.server.error.exception.MethodNotAllowed405Exception; @@ -171,6 +172,19 @@ public ApiExceptionHandlerListenerResult shouldHandleException(Throwable ex) { extraDetails ); } + + if (ex instanceof Forbidden403Exception) { + Forbidden403Exception theEx = (Forbidden403Exception) ex; + List> extraDetails = new ArrayList<>(); + extraDetails.add(Pair.of("message", ex.getMessage())); + extraDetails.add(Pair.of("incoming_request_path", theEx.requestPath)); + extraDetails.add(Pair.of("authorization_header", theEx.authorizationHeader)); + extraDetails.addAll((theEx).extraDetailsForLogging); + return ApiExceptionHandlerListenerResult.handleResponse( + singletonError(projectApiErrors.getForbiddenApiError()), + extraDetails + ); + } if (ex instanceof MultipleMatchingEndpointsException) { MultipleMatchingEndpointsException theEx = (MultipleMatchingEndpointsException) ex; diff --git a/riposte-spi/src/main/java/com/nike/riposte/server/error/exception/Forbidden403Exception.java b/riposte-spi/src/main/java/com/nike/riposte/server/error/exception/Forbidden403Exception.java new file mode 100644 index 00000000..ece192f7 --- /dev/null +++ b/riposte-spi/src/main/java/com/nike/riposte/server/error/exception/Forbidden403Exception.java @@ -0,0 +1,37 @@ +/** + * + */ +package com.nike.riposte.server.error.exception; + +import java.util.ArrayList; +import java.util.List; + +import com.nike.internal.util.Pair; + +/** + * Thrown when a request does not have a valid authorization header. Represents a HTTP 403 response code. + * + * @author pevans + * + */ +public class Forbidden403Exception extends RuntimeException { + + public final String requestPath; + public final String authorizationHeader; + public final List> extraDetailsForLogging; + + public Forbidden403Exception(String message, String requestPath, String authorizationHeader) { + this(message, requestPath, authorizationHeader, new ArrayList<>()); + } + + public Forbidden403Exception(String message, String requestPath, String authorizationHeader, + List> extraDetailsForLogging) { + super(message); + + this.requestPath = requestPath; + this.authorizationHeader = authorizationHeader; + this.extraDetailsForLogging = extraDetailsForLogging; + } + private static final long serialVersionUID = 4921880566299500314L; + +} diff --git a/riposte-spi/src/test/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListenerTest.java b/riposte-spi/src/test/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListenerTest.java index 1822a3c1..3740c595 100644 --- a/riposte-spi/src/test/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListenerTest.java +++ b/riposte-spi/src/test/java/com/nike/backstopper/handler/riposte/listener/impl/BackstopperRiposteFrameworkErrorHandlerListenerTest.java @@ -11,6 +11,7 @@ import com.nike.fastbreak.exception.CircuitBreakerTimeoutException; import com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException; import com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException; +import com.nike.riposte.server.error.exception.Forbidden403Exception; import com.nike.riposte.server.error.exception.HostnameResolutionException; import com.nike.riposte.server.error.exception.InvalidCharsetInContentTypeHeaderException; import com.nike.riposte.server.error.exception.MethodNotAllowed405Exception; @@ -143,6 +144,11 @@ public void shouldHandleMethodNotAllowed405Exception() { public void should_handle_Unauthorized401Exception() { verifyExceptionHandled(new Unauthorized401Exception("foo", "/bar", "blah"), singletonError(testProjectApiErrors.getUnauthorizedApiError())); } + + @Test + public void should_handle_Forbidden403Exception() { + verifyExceptionHandled(new Forbidden403Exception("foo", "/bar", "blah"), singletonError(testProjectApiErrors.getForbiddenApiError())); + } @Test public void shouldHandleMultipleMatchingEndpointsException() { diff --git a/riposte-spi/src/test/java/com/nike/riposte/server/error/exception/Forbidden403ExceptionTest.java b/riposte-spi/src/test/java/com/nike/riposte/server/error/exception/Forbidden403ExceptionTest.java new file mode 100644 index 00000000..b637f2fc --- /dev/null +++ b/riposte-spi/src/test/java/com/nike/riposte/server/error/exception/Forbidden403ExceptionTest.java @@ -0,0 +1,32 @@ +package com.nike.riposte.server.error.exception; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import java.util.UUID; + +import org.junit.Before; +import org.junit.Test; + +public class Forbidden403ExceptionTest { + + @Before + public void setUp() throws Exception { + } + + @Test + public void should_honor_constructor_params() { + //given + String requestPath = UUID.randomUUID().toString(); + String authorizationHeader = UUID.randomUUID().toString(); + String message = UUID.randomUUID().toString(); + + //when + Forbidden403Exception ex = new Forbidden403Exception(message, requestPath, authorizationHeader); + + //then + assertThat(ex.getMessage(), is(message)); + assertThat(ex.requestPath, is(requestPath)); + assertThat(ex.authorizationHeader, is(authorizationHeader)); + } + +}