Search in sources :

Example 1 with FullResponseInfo

use of com.nike.riposte.server.http.impl.FullResponseInfo in project riposte by Nike-Inc.

the class ExceptionHandlingHandler method processUnhandledError.

/**
 * Produces a generic error response. Call this if you know the error is a non-normal unhandled error of the "how
 * did we get here, this should never happen" variety, or if other attempts to deal with the error failed and you
 * need a guaranteed fallback that will produce a generic error response that follows our error contract. If you
 * have an error that happened during normal processing you should try {@link #processError(HttpProcessingState,
 * Object, Throwable)} instead in order to get an error response that is better tailored to the given error rather
 * than this one which guarantees a somewhat unhelpful generic error response.
 */
@NotNull
ResponseInfo<ErrorResponseBody> processUnhandledError(@NotNull HttpProcessingState state, Object msg, @NotNull Throwable cause) {
    RequestInfo<?> requestInfo = getRequestInfo(state, msg);
    // Run the error through the riposteUnhandledErrorHandler
    ErrorResponseInfo contentFromErrorHandler = riposteUnhandledErrorHandler.handleError(cause, requestInfo);
    ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>();
    setupResponseInfoBasedOnErrorResponseInfo(responseInfo, contentFromErrorHandler);
    return responseInfo;
}
Also used : ErrorResponseInfo(com.nike.riposte.server.error.handler.ErrorResponseInfo) ErrorResponseBody(com.nike.riposte.server.error.handler.ErrorResponseBody) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with FullResponseInfo

use of com.nike.riposte.server.http.impl.FullResponseInfo in project riposte by Nike-Inc.

the class ResponseSenderTest method setup.

@Before
public void setup() {
    ctx = TestUtil.mockChannelHandlerContext().mockContext;
    distributedTracingConfigMock = mock(DistributedTracingConfig.class);
    responseSender = new ResponseSender(null, null, distributedTracingConfigMock);
    requestInfo = mock(RequestInfo.class);
    httpHeaders = new DefaultHttpHeaders();
    responseInfo = new FullResponseInfo();
    responseInfo.setDesiredContentWriterEncoding(Charset.forName("UTF-8"));
    responseInfo.setDesiredContentWriterMimeType("application/json");
    when(requestInfo.getHeaders()).thenReturn(httpHeaders);
}
Also used : DistributedTracingConfig(com.nike.riposte.server.config.distributedtracing.DistributedTracingConfig) DefaultHttpHeaders(io.netty.handler.codec.http.DefaultHttpHeaders) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) Before(org.junit.Before)

Example 3 with FullResponseInfo

use of com.nike.riposte.server.http.impl.FullResponseInfo in project riposte by Nike-Inc.

the class ExceptionHandlingHandlerTest method setupResponseInfoBasedOnErrorResponseInfo_sets_response_content_and_httpStatusCode_and_adds_extra_headers.

@Test
public void setupResponseInfoBasedOnErrorResponseInfo_sets_response_content_and_httpStatusCode_and_adds_extra_headers() {
    // given
    ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>();
    ErrorResponseBody errorResponseBodyMock = mock(ErrorResponseBody.class);
    int httpStatusCode = 42;
    Map<String, List<String>> extraHeaders = new HashMap<>();
    extraHeaders.put("key1", Arrays.asList("foo", "bar"));
    extraHeaders.put("key2", Arrays.asList("baz"));
    ErrorResponseInfo errorInfoMock = mock(ErrorResponseInfo.class);
    doReturn(errorResponseBodyMock).when(errorInfoMock).getErrorResponseBody();
    doReturn(httpStatusCode).when(errorInfoMock).getErrorHttpStatusCode();
    doReturn(extraHeaders).when(errorInfoMock).getExtraHeadersToAddToResponse();
    // when
    handler.setupResponseInfoBasedOnErrorResponseInfo(responseInfo, errorInfoMock);
    // then
    assertThat(responseInfo.getContentForFullResponse(), is(errorResponseBodyMock));
    assertThat(responseInfo.getHttpStatusCode(), is(httpStatusCode));
    int numIndividualValuesInHeaderMap = extraHeaders.entrySet().stream().map(entry -> entry.getValue()).mapToInt(list -> list.size()).sum();
    assertThat(responseInfo.getHeaders().entries().size(), is(numIndividualValuesInHeaderMap));
    extraHeaders.entrySet().stream().forEach(expectedEntry -> assertThat(responseInfo.getHeaders().getAll(expectedEntry.getKey()), is(expectedEntry.getValue())));
}
Also used : CoreMatchers.is(org.hamcrest.CoreMatchers.is) Span(com.nike.wingtips.Span) Arrays(java.util.Arrays) ArgumentMatchers.eq(org.mockito.ArgumentMatchers.eq) ResponseInfo(com.nike.riposte.server.http.ResponseInfo) DataProviderRunner(com.tngtech.java.junit.dataprovider.DataProviderRunner) DO_NOT_FIRE_CONTINUE_EVENT(com.nike.riposte.server.handler.base.PipelineContinuationBehavior.DO_NOT_FIRE_CONTINUE_EVENT) Collections.singletonList(java.util.Collections.singletonList) CoreMatchers.notNullValue(org.hamcrest.CoreMatchers.notNullValue) Mockito.verifyNoInteractions(org.mockito.Mockito.verifyNoInteractions) ErrorResponseBody(com.nike.riposte.server.error.handler.ErrorResponseBody) Mockito.doThrow(org.mockito.Mockito.doThrow) DefaultHttpRequest(io.netty.handler.codec.http.DefaultHttpRequest) ProxyRouterEndpoint(com.nike.riposte.server.http.ProxyRouterEndpoint) Map(java.util.Map) ErrorResponseInfo(com.nike.riposte.server.error.handler.ErrorResponseInfo) Assertions(org.assertj.core.api.Assertions) Mockito.doReturn(org.mockito.Mockito.doReturn) RiposteErrorHandler(com.nike.riposte.server.error.handler.RiposteErrorHandler) IncompleteHttpCallTimeoutException(com.nike.riposte.server.error.exception.IncompleteHttpCallTimeoutException) ServerSpanNamingAndTaggingStrategy(com.nike.riposte.server.config.distributedtracing.ServerSpanNamingAndTaggingStrategy) HttpRequest(io.netty.handler.codec.http.HttpRequest) UUID(java.util.UUID) Collectors(java.util.stream.Collectors) TooManyOpenChannelsException(com.nike.riposte.server.error.exception.TooManyOpenChannelsException) List(java.util.List) ChannelAttributes(com.nike.riposte.server.channelpipeline.ChannelAttributes) Mockito.mock(org.mockito.Mockito.mock) HttpProcessingState(com.nike.riposte.server.http.HttpProcessingState) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) ArgumentMatchers.any(org.mockito.ArgumentMatchers.any) UnexpectedMajorErrorHandlingError(com.nike.riposte.server.error.exception.UnexpectedMajorErrorHandlingError) RequestInfo(com.nike.riposte.server.http.RequestInfo) HttpVersion(io.netty.handler.codec.http.HttpVersion) RunWith(org.junit.runner.RunWith) CoreMatchers.not(org.hamcrest.CoreMatchers.not) HashMap(java.util.HashMap) PipelineContinuationBehavior(com.nike.riposte.server.handler.base.PipelineContinuationBehavior) Mockito.spy(org.mockito.Mockito.spy) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) ChannelHandlerContext(io.netty.channel.ChannelHandlerContext) ArgumentCaptor(org.mockito.ArgumentCaptor) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Whitebox(com.nike.riposte.testutils.Whitebox) CoreMatchers.nullValue(org.hamcrest.CoreMatchers.nullValue) Before(org.junit.Before) Attribute(io.netty.util.Attribute) InvalidRipostePipelineException(com.nike.riposte.server.error.exception.InvalidRipostePipelineException) UseDataProvider(com.tngtech.java.junit.dataprovider.UseDataProvider) HttpMethod(io.netty.handler.codec.http.HttpMethod) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) Test(org.junit.Test) Mockito.times(org.mockito.Mockito.times) Mockito.verify(org.mockito.Mockito.verify) Channel(io.netty.channel.Channel) RiposteUnhandledErrorHandler(com.nike.riposte.server.error.handler.RiposteUnhandledErrorHandler) Mockito.never(org.mockito.Mockito.never) DistributedTracingConfig(com.nike.riposte.server.config.distributedtracing.DistributedTracingConfig) ProxyRouterProcessingState(com.nike.riposte.server.http.ProxyRouterProcessingState) Collections(java.util.Collections) ErrorResponseInfo(com.nike.riposte.server.error.handler.ErrorResponseInfo) HashMap(java.util.HashMap) ErrorResponseBody(com.nike.riposte.server.error.handler.ErrorResponseBody) Collections.singletonList(java.util.Collections.singletonList) List(java.util.List) ProxyRouterEndpoint(com.nike.riposte.server.http.ProxyRouterEndpoint) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) Test(org.junit.Test)

Example 4 with FullResponseInfo

use of com.nike.riposte.server.http.impl.FullResponseInfo in project riposte by Nike-Inc.

the class ExceptionHandlingHandler method processError.

/**
 * Attempts to process the given error using the "normal" error handler {@link #riposteErrorHandler} to produce the
 * most specific error response possible for the given error. If that fails for any reason then the unhandled error
 * handler will take over to guarantee the user gets a generic error response that still follows our error contract.
 * If you already know your error is a non-normal unhandled error of the "how did we get here, this should never
 * happen" variety you can (and should) directly call {@link #processUnhandledError(HttpProcessingState, Object,
 * Throwable)} instead.
 */
@NotNull
protected ResponseInfo<ErrorResponseBody> processError(@NotNull HttpProcessingState state, Object msg, @NotNull Throwable cause) {
    RequestInfo<?> requestInfo = getRequestInfo(state, msg);
    try {
        ErrorResponseInfo contentFromErrorHandler = riposteErrorHandler.maybeHandleError(cause, requestInfo);
        if (contentFromErrorHandler != null) {
            // The regular error handler did handle the error. Setup our ResponseInfo.
            ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>();
            setupResponseInfoBasedOnErrorResponseInfo(responseInfo, contentFromErrorHandler);
            return responseInfo;
        }
    } catch (Throwable errorHandlerFailed) {
        logger.error("An unexpected problem occurred while trying to handle an error.", errorHandlerFailed);
    }
    // so the riposteUnhandledErrorHandler should take care of it.
    return processUnhandledError(state, msg, cause);
}
Also used : ErrorResponseInfo(com.nike.riposte.server.error.handler.ErrorResponseInfo) ErrorResponseBody(com.nike.riposte.server.error.handler.ErrorResponseBody) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with FullResponseInfo

use of com.nike.riposte.server.http.impl.FullResponseInfo in project riposte by Nike-Inc.

the class ExceptionHandlingHandlerTest method setupResponseInfoBasedOnErrorResponseInfo_sets_response_content_and_httpStatusCode_and_ignores_extra_headers_if_extra_headers_is_null.

@Test
public void setupResponseInfoBasedOnErrorResponseInfo_sets_response_content_and_httpStatusCode_and_ignores_extra_headers_if_extra_headers_is_null() {
    // given
    ResponseInfo<ErrorResponseBody> responseInfo = new FullResponseInfo<>();
    ErrorResponseBody errorResponseBodyMock = mock(ErrorResponseBody.class);
    int httpStatusCode = 42;
    ErrorResponseInfo errorInfoMock = mock(ErrorResponseInfo.class);
    doReturn(errorResponseBodyMock).when(errorInfoMock).getErrorResponseBody();
    doReturn(httpStatusCode).when(errorInfoMock).getErrorHttpStatusCode();
    doReturn(null).when(errorInfoMock).getExtraHeadersToAddToResponse();
    // when
    handler.setupResponseInfoBasedOnErrorResponseInfo(responseInfo, errorInfoMock);
    // then
    assertThat(responseInfo.getContentForFullResponse(), is(errorResponseBodyMock));
    assertThat(responseInfo.getHttpStatusCode(), is(httpStatusCode));
    assertThat(responseInfo.getHeaders().entries().size(), is(0));
}
Also used : ErrorResponseInfo(com.nike.riposte.server.error.handler.ErrorResponseInfo) ErrorResponseBody(com.nike.riposte.server.error.handler.ErrorResponseBody) ProxyRouterEndpoint(com.nike.riposte.server.http.ProxyRouterEndpoint) FullResponseInfo(com.nike.riposte.server.http.impl.FullResponseInfo) Test(org.junit.Test)

Aggregations

FullResponseInfo (com.nike.riposte.server.http.impl.FullResponseInfo)5 ErrorResponseBody (com.nike.riposte.server.error.handler.ErrorResponseBody)4 ErrorResponseInfo (com.nike.riposte.server.error.handler.ErrorResponseInfo)4 DistributedTracingConfig (com.nike.riposte.server.config.distributedtracing.DistributedTracingConfig)2 ProxyRouterEndpoint (com.nike.riposte.server.http.ProxyRouterEndpoint)2 Before (org.junit.Before)2 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)1 ChannelAttributes (com.nike.riposte.server.channelpipeline.ChannelAttributes)1 ServerSpanNamingAndTaggingStrategy (com.nike.riposte.server.config.distributedtracing.ServerSpanNamingAndTaggingStrategy)1 IncompleteHttpCallTimeoutException (com.nike.riposte.server.error.exception.IncompleteHttpCallTimeoutException)1 InvalidRipostePipelineException (com.nike.riposte.server.error.exception.InvalidRipostePipelineException)1 TooManyOpenChannelsException (com.nike.riposte.server.error.exception.TooManyOpenChannelsException)1 UnexpectedMajorErrorHandlingError (com.nike.riposte.server.error.exception.UnexpectedMajorErrorHandlingError)1 RiposteErrorHandler (com.nike.riposte.server.error.handler.RiposteErrorHandler)1 RiposteUnhandledErrorHandler (com.nike.riposte.server.error.handler.RiposteUnhandledErrorHandler)1 PipelineContinuationBehavior (com.nike.riposte.server.handler.base.PipelineContinuationBehavior)1 DO_NOT_FIRE_CONTINUE_EVENT (com.nike.riposte.server.handler.base.PipelineContinuationBehavior.DO_NOT_FIRE_CONTINUE_EVENT)1 HttpProcessingState (com.nike.riposte.server.http.HttpProcessingState)1 ProxyRouterProcessingState (com.nike.riposte.server.http.ProxyRouterProcessingState)1 RequestInfo (com.nike.riposte.server.http.RequestInfo)1