DefaultFailureHandler implements Handler<RoutingContext> { @Override public void handle(final RoutingContext ctx) { if (ctx.failed()) { if (ctx.response().ended()) { LOG.debug("skipping processing of failed route, response already ended"); } else { LOG.debug("handling failed route for request [method: {}, URI: {}, status: {}] - {}", ctx.request().method(), ctx.request().absoluteURI(), ctx.statusCode(), ctx.getBody(), ctx.failure()); if (ctx.failure() != null) { if (ctx.failure() instanceof ServiceInvocationException) { final ServiceInvocationException e = (ServiceInvocationException) ctx.failure(); sendError(ctx.response(), e.getErrorCode(), e.getMessage()); } else if (ctx.failure() instanceof HttpStatusException) { final HttpStatusException e = (HttpStatusException) ctx.failure(); sendError(ctx.response(), e.getStatusCode(), e.getMessage()); } else { LOG.debug("unexpected internal failure", ctx.failure()); sendError(ctx.response(), HttpURLConnection.HTTP_INTERNAL_ERROR, ctx.failure().getMessage()); } } else if (ctx.statusCode() != -1) { sendError(ctx.response(), ctx.statusCode(), null); } else { sendError(ctx.response(), HttpURLConnection.HTTP_INTERNAL_ERROR, "Internal Server Error"); } } } else { LOG.debug("skipping processing of non-failed route"); ctx.next(); } }  @Override void handle(final RoutingContext ctx);  }
@Test public void testHandlerDetectsEndedResponse() { final HttpServerResponse response = mock(HttpServerResponse.class); when(response.ended()).thenReturn(true); final RoutingContext ctx = mock(RoutingContext.class); when(ctx.response()).thenReturn(response); when(ctx.failed()).thenReturn(true); final DefaultFailureHandler handler = new DefaultFailureHandler(); handler.handle(ctx); verify(response, never()).setStatusCode(anyInt()); verify(response, never()).write(any(Buffer.class)); verify(response, never()).end(); }
@Test public void testHandlerSucceedsForExceptionsWithoutMessage() { final HttpServerRequest request = mock(HttpServerRequest.class, Mockito.RETURNS_MOCKS); final HttpServerResponse response = mock(HttpServerResponse.class); when(response.ended()).thenReturn(false); final RoutingContext ctx = mock(RoutingContext.class); when(ctx.request()).thenReturn(request); when(ctx.response()).thenReturn(response); when(ctx.failed()).thenReturn(true); when(ctx.failure()).thenReturn(new IllegalStateException()); final DefaultFailureHandler handler = new DefaultFailureHandler(); handler.handle(ctx); verify(response).setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR); verify(response, never()).write(any(Buffer.class)); verify(response).end(); }
@Test public void testHandlerWritesDetailMessageToBody() { final String detailMessage = "detail message"; final HttpServerRequest request = mock(HttpServerRequest.class, Mockito.RETURNS_MOCKS); final HttpServerResponse response = mock(HttpServerResponse.class); when(response.ended()).thenReturn(false); final RoutingContext ctx = mock(RoutingContext.class); when(ctx.request()).thenReturn(request); when(ctx.response()).thenReturn(response); when(ctx.failed()).thenReturn(true); when(ctx.failure()).thenReturn(new IllegalStateException(detailMessage)); final DefaultFailureHandler handler = new DefaultFailureHandler(); handler.handle(ctx); final ArgumentCaptor<Buffer> bufferCaptor = ArgumentCaptor.forClass(Buffer.class); verify(response).setStatusCode(HttpURLConnection.HTTP_INTERNAL_ERROR); verify(response).write(bufferCaptor.capture()); assertThat(bufferCaptor.getValue().toString()).isEqualTo(detailMessage); verify(response).end(); }
@Test public void testHandlerWritesDetailMessageAndErrorCodeToBody() { final String detailMessage = "bad request"; final HttpServerRequest request = mock(HttpServerRequest.class, Mockito.RETURNS_MOCKS); final HttpServerResponse response = mock(HttpServerResponse.class); when(response.ended()).thenReturn(false); final RoutingContext ctx = mock(RoutingContext.class); when(ctx.request()).thenReturn(request); when(ctx.response()).thenReturn(response); when(ctx.failed()).thenReturn(true); when(ctx.failure()).thenReturn(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, detailMessage)); final DefaultFailureHandler handler = new DefaultFailureHandler(); handler.handle(ctx); final ArgumentCaptor<Buffer> bufferCaptor = ArgumentCaptor.forClass(Buffer.class); verify(response).setStatusCode(HttpURLConnection.HTTP_BAD_REQUEST); verify(response).write(bufferCaptor.capture()); assertThat(bufferCaptor.getValue().toString()).isEqualTo(detailMessage); verify(response).end(); }
@Test public void testHandlerWithFailedContextAndEmptyFailure() { final RoutingContext ctx = mock(RoutingContext.class); final HttpServerRequest request = mock(HttpServerRequest.class, Mockito.RETURNS_MOCKS); final HttpServerResponse response = mock(HttpServerResponse.class, Mockito.RETURNS_MOCKS); when(response.ended()).thenReturn(false); when(ctx.request()).thenReturn(request); when(ctx.response()).thenReturn(response); when(ctx.failed()).thenReturn(true); when(ctx.failure()).thenReturn(null); when(ctx.statusCode()).thenReturn(HttpURLConnection.HTTP_UNAUTHORIZED); final DefaultFailureHandler handler = new DefaultFailureHandler(); handler.handle(ctx); verify(response).setStatusCode(HttpURLConnection.HTTP_UNAUTHORIZED); verify(response, never()).write(any(Buffer.class)); verify(response).end(); }