Search in sources :

Example 1 with InvalidHttpRequestException

use of com.nike.riposte.server.error.exception.InvalidHttpRequestException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method shouldHandleInvalidHttpRequestExceptionWithNonNullCause.

@DataProvider(value = { "true", "false" })
@Test
public void shouldHandleInvalidHttpRequestExceptionWithNonNullCause(boolean useTooLongFrameExceptionAsCause) {
    // given
    Throwable cause = (useTooLongFrameExceptionAsCause) ? new TooLongFrameException("TooLongFrameException occurred") : new RuntimeException("runtime exception");
    String expectedCauseMetadataMessage = (useTooLongFrameExceptionAsCause) ? listener.TOO_LONG_FRAME_LINE_METADATA_MESSAGE : "Invalid HTTP request";
    String outerExceptionMessage = "message - " + UUID.randomUUID().toString();
    ApiError expectedApiErrorBase = (useTooLongFrameExceptionAsCause) ? listener.TOO_LONG_FRAME_LINE_API_ERROR_BASE : testProjectApiErrors.getMalformedRequestApiError();
    // when
    ApiExceptionHandlerListenerResult result = listener.shouldHandleException(new InvalidHttpRequestException(outerExceptionMessage, cause));
    // then
    assertThat(result.shouldHandleResponse).isTrue();
    assertThat(result.errors).isEqualTo(singletonError(new ApiErrorWithMetadata(expectedApiErrorBase, Pair.of("cause", expectedCauseMetadataMessage))));
    assertThat(result.extraDetailsForLogging.get(0).getLeft()).isEqualTo("exception_message");
    assertThat(result.extraDetailsForLogging.get(0).getRight()).isEqualTo(outerExceptionMessage);
    assertThat(result.extraDetailsForLogging.get(1).getLeft()).isEqualTo("exception_cause_details");
    assertThat(result.extraDetailsForLogging.get(1).getRight()).isEqualTo(cause.toString());
}
Also used : TooLongFrameException(io.netty.handler.codec.TooLongFrameException) ApiErrorWithMetadata(com.nike.backstopper.apierror.ApiErrorWithMetadata) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) ApiError(com.nike.backstopper.apierror.ApiError) InvalidHttpRequestException(com.nike.riposte.server.error.exception.InvalidHttpRequestException) ApiExceptionHandlerListenerResult(com.nike.backstopper.handler.listener.ApiExceptionHandlerListenerResult) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Example 2 with InvalidHttpRequestException

use of com.nike.riposte.server.error.exception.InvalidHttpRequestException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method shouldHandleInvalidHttpRequestExceptionWithNullCause.

@Test
public void shouldHandleInvalidHttpRequestExceptionWithNullCause() {
    ApiExceptionHandlerListenerResult result = listener.shouldHandleException(new InvalidHttpRequestException("message", null));
    assertThat(result.shouldHandleResponse).isTrue();
    assertThat(result.errors).isEqualTo(singletonError(new ApiErrorWithMetadata(testProjectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "Invalid HTTP request"))));
    assertThat(result.extraDetailsForLogging.get(0).getLeft()).isEqualTo("exception_message");
    assertThat(result.extraDetailsForLogging.get(0).getRight()).isEqualTo("message");
    assertThat(result.extraDetailsForLogging.get(1).getLeft()).isEqualTo("exception_cause_details");
    assertThat(result.extraDetailsForLogging.get(1).getRight()).isEqualTo("NO_CAUSE");
}
Also used : ApiErrorWithMetadata(com.nike.backstopper.apierror.ApiErrorWithMetadata) InvalidHttpRequestException(com.nike.riposte.server.error.exception.InvalidHttpRequestException) ApiExceptionHandlerListenerResult(com.nike.backstopper.handler.listener.ApiExceptionHandlerListenerResult) Test(org.junit.Test)

Example 3 with InvalidHttpRequestException

use of com.nike.riposte.server.error.exception.InvalidHttpRequestException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method shouldHandleInvalidHttpRequestExceptionWithNonNullCause.

@Test
public void shouldHandleInvalidHttpRequestExceptionWithNonNullCause() {
    ApiExceptionHandlerListenerResult result = listener.shouldHandleException(new InvalidHttpRequestException("message", new RuntimeException("runtime exception")));
    assertThat(result.shouldHandleResponse).isTrue();
    assertThat(result.errors).isEqualTo(singletonError(testProjectApiErrors.getMalformedRequestApiError()));
    assertThat(result.errors.first().getMetadata().get("cause")).isEqualTo("Invalid HTTP request");
    assertThat(result.extraDetailsForLogging.get(0).getLeft()).isEqualTo("exception_message");
    assertThat(result.extraDetailsForLogging.get(0).getRight()).isEqualTo("message");
    assertThat(result.extraDetailsForLogging.get(1).getLeft()).isEqualTo("cause_details");
    assertThat(result.extraDetailsForLogging.get(1).getRight()).isEqualTo("java.lang.RuntimeException: runtime exception");
}
Also used : InvalidHttpRequestException(com.nike.riposte.server.error.exception.InvalidHttpRequestException) ApiExceptionHandlerListenerResult(com.nike.backstopper.handler.listener.ApiExceptionHandlerListenerResult) Test(org.junit.Test)

Example 4 with InvalidHttpRequestException

use of com.nike.riposte.server.error.exception.InvalidHttpRequestException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListener method shouldHandleException.

@Override
public ApiExceptionHandlerListenerResult shouldHandleException(Throwable ex) {
    if (ex instanceof CircuitBreakerException) {
        CircuitBreakerException cbe = ((CircuitBreakerException) ex);
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(getApiErrorForCircuitBreakerException(cbe)), singletonList(Pair.of("circuit_breaker_id", String.valueOf(cbe.circuitBreakerId))));
    }
    if (ex instanceof NonblockingEndpointCompletableFutureTimedOut) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), singletonList(Pair.of("completable_future_timeout_value_millis", String.valueOf(((NonblockingEndpointCompletableFutureTimedOut) ex).timeoutValueMillis))));
    }
    if (ex instanceof DownstreamIdleChannelTimeoutException) {
        DownstreamIdleChannelTimeoutException idleEx = (DownstreamIdleChannelTimeoutException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), Arrays.asList(Pair.of("async_downstream_call_timeout_value_millis", String.valueOf(idleEx.timeoutValueMillis)), Pair.of("idle_channel_id", String.valueOf(idleEx.channelId))));
    }
    if (ex instanceof DownstreamChannelClosedUnexpectedlyException) {
        DownstreamChannelClosedUnexpectedlyException dsClosedEx = (DownstreamChannelClosedUnexpectedlyException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), singletonList(Pair.of("closed_channel_id", String.valueOf(dsClosedEx.channelId))));
    }
    if (ex instanceof DecoderException) {
        ApiError errorToUse = (ex instanceof TooLongFrameException) ? generateTooLongFrameApiError((TooLongFrameException) ex) : projectApiErrors.getMalformedRequestApiError();
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(errorToUse), withBaseExceptionMessage(ex, Pair.of("decoder_exception", "true")));
    }
    if (ex instanceof RequestTooBigException) {
        // TODO: RequestTooBigException should result in a 413 Payload Too Large error instead of generic 400 malformed request.
        // For now, we can at least let the caller know why it failed via error metadata.
        ApiError errorToUse = new ApiErrorWithMetadata(projectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "The request exceeded the maximum payload size allowed"));
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(errorToUse), withBaseExceptionMessage(ex, Pair.of("decoder_exception", "true")));
    }
    if (ex instanceof HostnameResolutionException) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), withBaseExceptionMessage(ex));
    }
    if (ex instanceof NativeIoExceptionWrapper) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), singletonList(causeDetailsForLogs(ex)));
    }
    if (ex instanceof RequestContentDeserializationException) {
        RequestContentDeserializationException theEx = (RequestContentDeserializationException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getMalformedRequestApiError()), Arrays.asList(Pair.of("method", theEx.httpMethod), Pair.of("request_path", theEx.requestPath), Pair.of("desired_object_type", theEx.desiredObjectType.getType().toString()), causeDetailsForLogs(ex)));
    }
    if (ex instanceof PathNotFound404Exception) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getNotFoundApiError()));
    }
    if (ex instanceof MethodNotAllowed405Exception) {
        MethodNotAllowed405Exception theEx = (MethodNotAllowed405Exception) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getMethodNotAllowedApiError()), Arrays.asList(Pair.of("incoming_request_path", theEx.requestPath), Pair.of("incoming_request_method", theEx.requestMethod)));
    }
    if (ex instanceof Unauthorized401Exception) {
        Unauthorized401Exception theEx = (Unauthorized401Exception) ex;
        List<Pair<String, String>> extraDetails = withBaseExceptionMessage(ex, Pair.of("incoming_request_path", theEx.requestPath));
        extraDetails.addAll((theEx).extraDetailsForLogging);
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getUnauthorizedApiError()), extraDetails);
    }
    if (ex instanceof Forbidden403Exception) {
        Forbidden403Exception theEx = (Forbidden403Exception) ex;
        List<Pair<String, String>> extraDetails = withBaseExceptionMessage(ex, Pair.of("incoming_request_path", theEx.requestPath));
        extraDetails.addAll((theEx).extraDetailsForLogging);
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getForbiddenApiError()), extraDetails);
    }
    if (ex instanceof MissingRequiredContentException) {
        MissingRequiredContentException theEx = (MissingRequiredContentException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getMissingExpectedContentApiError()), Arrays.asList(Pair.of("incoming_request_path", theEx.path), Pair.of("incoming_request_method", theEx.method), Pair.of("endpoint_class_name", theEx.endpointClassName)));
    }
    if (ex instanceof MultipleMatchingEndpointsException) {
        MultipleMatchingEndpointsException theEx = (MultipleMatchingEndpointsException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getGenericServiceError()), Arrays.asList(Pair.of("incoming_request_path", theEx.requestPath), Pair.of("incoming_request_method", theEx.requestMethod), Pair.of("matching_endpoints", StringUtils.join(theEx.matchingEndpointsDetails, ","))));
    }
    if (ex instanceof PathParameterMatchingException) {
        PathParameterMatchingException theEx = (PathParameterMatchingException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getGenericServiceError()), Arrays.asList(Pair.of("path_template", theEx.pathTemplate), Pair.of("non_matching_uri_path", theEx.nonMatchingUriPath)));
    }
    if (ex instanceof InvalidCharsetInContentTypeHeaderException) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getUnsupportedMediaTypeApiError()), singletonList(Pair.of("invalid_content_type_header", ((InvalidCharsetInContentTypeHeaderException) ex).invalidContentTypeHeader)));
    }
    if (ex instanceof TooManyOpenChannelsException) {
        TooManyOpenChannelsException theEx = (TooManyOpenChannelsException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()), Arrays.asList(Pair.of("num_current_open_channels", String.valueOf(theEx.actualOpenChannelsCount)), Pair.of("max_open_channels_limit", String.valueOf(theEx.maxOpenChannelsLimit))));
    }
    if (ex instanceof IncompleteHttpCallTimeoutException) {
        IncompleteHttpCallTimeoutException theEx = (IncompleteHttpCallTimeoutException) ex;
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(new ApiErrorWithMetadata(projectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "Unfinished/invalid HTTP request"))), withBaseExceptionMessage(ex, Pair.of("incomplete_http_call_timeout_millis", String.valueOf(theEx.timeoutMillis))));
    }
    if (ex instanceof InvalidHttpRequestException) {
        InvalidHttpRequestException theEx = (InvalidHttpRequestException) ex;
        Throwable cause = theEx.getCause();
        ApiError apiErrorToUse = (cause instanceof TooLongFrameException) ? generateTooLongFrameApiError((TooLongFrameException) cause) : new ApiErrorWithMetadata(projectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "Invalid HTTP request"));
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(apiErrorToUse), withBaseExceptionMessage(ex, causeDetailsForLogs(theEx)));
    }
    return ApiExceptionHandlerListenerResult.ignoreResponse();
}
Also used : MissingRequiredContentException(com.nike.riposte.server.error.exception.MissingRequiredContentException) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) HostnameResolutionException(com.nike.riposte.server.error.exception.HostnameResolutionException) Forbidden403Exception(com.nike.riposte.server.error.exception.Forbidden403Exception) TooManyOpenChannelsException(com.nike.riposte.server.error.exception.TooManyOpenChannelsException) IncompleteHttpCallTimeoutException(com.nike.riposte.server.error.exception.IncompleteHttpCallTimeoutException) RequestContentDeserializationException(com.nike.riposte.server.error.exception.RequestContentDeserializationException) MultipleMatchingEndpointsException(com.nike.riposte.server.error.exception.MultipleMatchingEndpointsException) ApiErrorWithMetadata(com.nike.backstopper.apierror.ApiErrorWithMetadata) PathParameterMatchingException(com.nike.riposte.server.error.exception.PathParameterMatchingException) Unauthorized401Exception(com.nike.riposte.server.error.exception.Unauthorized401Exception) Pair(com.nike.internal.util.Pair) NativeIoExceptionWrapper(com.nike.riposte.server.error.exception.NativeIoExceptionWrapper) RequestTooBigException(com.nike.riposte.server.error.exception.RequestTooBigException) InvalidCharsetInContentTypeHeaderException(com.nike.riposte.server.error.exception.InvalidCharsetInContentTypeHeaderException) PathNotFound404Exception(com.nike.riposte.server.error.exception.PathNotFound404Exception) InvalidHttpRequestException(com.nike.riposte.server.error.exception.InvalidHttpRequestException) CircuitBreakerException(com.nike.fastbreak.exception.CircuitBreakerException) NonblockingEndpointCompletableFutureTimedOut(com.nike.riposte.server.error.exception.NonblockingEndpointCompletableFutureTimedOut) DecoderException(io.netty.handler.codec.DecoderException) MethodNotAllowed405Exception(com.nike.riposte.server.error.exception.MethodNotAllowed405Exception) DownstreamChannelClosedUnexpectedlyException(com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException) ApiError(com.nike.backstopper.apierror.ApiError) DownstreamIdleChannelTimeoutException(com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException)

Example 5 with InvalidHttpRequestException

use of com.nike.riposte.server.error.exception.InvalidHttpRequestException in project riposte by Nike-Inc.

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method should_handle_TooLongFrameException_as_expected.

@DataProvider(value = { "NORMAL_TOO_LONG_HEADERS_ERROR                      |   true", "NORMAL_TOO_LONG_HEADERS_ERROR                      |   false", "NORMAL_TOO_LONG_LINE_ERROR                         |   true", "NORMAL_TOO_LONG_LINE_ERROR                         |   false", "NULL_EXCEPTION_MESSAGE                             |   true", "NULL_EXCEPTION_MESSAGE                             |   false", "EXCEPTION_MESSAGE_DOES_NOT_END_IN_BYTES            |   true", "EXCEPTION_MESSAGE_DOES_NOT_END_IN_BYTES            |   false", "HEADER_EXCEPTION_MESSAGE_MAX_SIZE_NOT_AN_INTEGER   |   true", "HEADER_EXCEPTION_MESSAGE_MAX_SIZE_NOT_AN_INTEGER   |   false", "LINE_EXCEPTION_MESSAGE_MAX_SIZE_NOT_AN_INTEGER     |   true", "LINE_EXCEPTION_MESSAGE_MAX_SIZE_NOT_AN_INTEGER     |   false" }, splitBy = "\\|")
@Test
public void should_handle_TooLongFrameException_as_expected(TooLongFrameExceptionScenario scenario, boolean wrappedInInvalidHttpRequestException) {
    Throwable ex = (wrappedInInvalidHttpRequestException) ? new InvalidHttpRequestException("foo", scenario.exception) : scenario.exception;
    verifyExceptionHandled(ex, singletonError(scenario.expectedApiError(listener)));
}
Also used : Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) InvalidHttpRequestException(com.nike.riposte.server.error.exception.InvalidHttpRequestException) DataProvider(com.tngtech.java.junit.dataprovider.DataProvider) Test(org.junit.Test)

Aggregations

InvalidHttpRequestException (com.nike.riposte.server.error.exception.InvalidHttpRequestException)5 Test (org.junit.Test)4 ApiErrorWithMetadata (com.nike.backstopper.apierror.ApiErrorWithMetadata)3 ApiExceptionHandlerListenerResult (com.nike.backstopper.handler.listener.ApiExceptionHandlerListenerResult)3 ApiError (com.nike.backstopper.apierror.ApiError)2 DataProvider (com.tngtech.java.junit.dataprovider.DataProvider)2 TooLongFrameException (io.netty.handler.codec.TooLongFrameException)2 Assertions.catchThrowable (org.assertj.core.api.Assertions.catchThrowable)2 CircuitBreakerException (com.nike.fastbreak.exception.CircuitBreakerException)1 Pair (com.nike.internal.util.Pair)1 DownstreamChannelClosedUnexpectedlyException (com.nike.riposte.server.error.exception.DownstreamChannelClosedUnexpectedlyException)1 DownstreamIdleChannelTimeoutException (com.nike.riposte.server.error.exception.DownstreamIdleChannelTimeoutException)1 Forbidden403Exception (com.nike.riposte.server.error.exception.Forbidden403Exception)1 HostnameResolutionException (com.nike.riposte.server.error.exception.HostnameResolutionException)1 IncompleteHttpCallTimeoutException (com.nike.riposte.server.error.exception.IncompleteHttpCallTimeoutException)1 InvalidCharsetInContentTypeHeaderException (com.nike.riposte.server.error.exception.InvalidCharsetInContentTypeHeaderException)1 MethodNotAllowed405Exception (com.nike.riposte.server.error.exception.MethodNotAllowed405Exception)1 MissingRequiredContentException (com.nike.riposte.server.error.exception.MissingRequiredContentException)1 MultipleMatchingEndpointsException (com.nike.riposte.server.error.exception.MultipleMatchingEndpointsException)1 NativeIoExceptionWrapper (com.nike.riposte.server.error.exception.NativeIoExceptionWrapper)1