Search in sources :

Example 1 with RequestContentDeserializationException

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

the class RequestInfoImplTest method getContent_throws_RequestContentDeserializationException_if_an_error_occurs_during_deserialization.

@Test
public void getContent_throws_RequestContentDeserializationException_if_an_error_occurs_during_deserialization() throws IOException {
    // given
    RequestInfo<TestContentObject> requestInfoSpy = spy((RequestInfo<TestContentObject>) RequestInfoImpl.dummyInstanceForUnknownRequests());
    ObjectMapper objectMapperSpy = spy(new ObjectMapper());
    byte[] rawBytes = new byte[] {};
    doReturn(rawBytes).when(requestInfoSpy).getRawContentBytes();
    RuntimeException expectedRootCause = new RuntimeException("splat");
    doThrow(expectedRootCause).when(objectMapperSpy).readValue(any(byte[].class), any(TypeReference.class));
    HttpMethod method = HttpMethod.CONNECT;
    String path = UUID.randomUUID().toString();
    TypeReference<TestContentObject> typeRef = new TypeReference<TestContentObject>() {
    };
    doReturn(method).when(requestInfoSpy).getMethod();
    doReturn(path).when(requestInfoSpy).getPath();
    // when
    requestInfoSpy.setupContentDeserializer(objectMapperSpy, typeRef);
    Throwable actualEx = catchThrowable(() -> requestInfoSpy.getContent());
    // then
    assertThat(actualEx, notNullValue());
    assertThat(actualEx, instanceOf(RequestContentDeserializationException.class));
    RequestContentDeserializationException rcde = (RequestContentDeserializationException) actualEx;
    assertThat(rcde.desiredObjectType, sameInstance(typeRef));
    assertThat(rcde.httpMethod, is(String.valueOf(method)));
    assertThat(rcde.requestPath, is(path));
    assertThat(actualEx.getCause(), is(expectedRootCause));
}
Also used : RequestContentDeserializationException(com.nike.riposte.server.error.exception.RequestContentDeserializationException) Assertions.catchThrowable(org.assertj.core.api.Assertions.catchThrowable) TypeReference(com.fasterxml.jackson.core.type.TypeReference) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) HttpMethod(io.netty.handler.codec.http.HttpMethod) Test(org.junit.Test)

Example 2 with RequestContentDeserializationException

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

the class BackstopperRiposteFrameworkErrorHandlerListenerTest method shouldHandleRequestContentDeserializationException.

@Test
public void shouldHandleRequestContentDeserializationException() {
    RequestInfo requestInfo = new RequestInfoImpl(null, HttpMethod.PATCH, null, null, null, null, null, null, null, false, true, false);
    verifyExceptionHandled(new RequestContentDeserializationException("intentional boom", null, requestInfo, new TypeReference<Object>() {
    }), singletonError(testProjectApiErrors.getMalformedRequestApiError()));
}
Also used : RequestContentDeserializationException(com.nike.riposte.server.error.exception.RequestContentDeserializationException) RequestInfoImpl(com.nike.riposte.server.http.impl.RequestInfoImpl) TypeReference(com.fasterxml.jackson.core.type.TypeReference) RequestInfo(com.nike.riposte.server.http.RequestInfo) Test(org.junit.Test)

Example 3 with RequestContentDeserializationException

use of com.nike.riposte.server.error.exception.RequestContentDeserializationException 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) {
        // TODO: TooLongFrameException 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 = (ex instanceof TooLongFrameException) ? new ApiErrorWithMetadata(projectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "The request exceeded the maximum payload size allowed")) : projectApiErrors.getMalformedRequestApiError();
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(errorToUse), Arrays.asList(Pair.of("decoder_exception", "true"), Pair.of("decoder_exception_message", ex.getMessage())));
    }
    if (ex instanceof HostnameResolutionException) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()));
    }
    if (ex instanceof NativeIoExceptionWrapper) {
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(projectApiErrors.getTemporaryServiceProblemApiError()));
    }
    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())));
    }
    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 = 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.getUnauthorizedApiError()), extraDetails);
    }
    if (ex instanceof Forbidden403Exception) {
        Forbidden403Exception theEx = (Forbidden403Exception) ex;
        List<Pair<String, String>> 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;
        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"))), Arrays.asList(Pair.of("incomplete_http_call_timeout_millis", String.valueOf(theEx.timeoutMillis)), Pair.of("exception_message", theEx.getMessage())));
    }
    if (ex instanceof InvalidHttpRequestException) {
        InvalidHttpRequestException theEx = (InvalidHttpRequestException) ex;
        Throwable cause = theEx.getCause();
        String causeAsString = cause == null ? "null" : cause.toString();
        return ApiExceptionHandlerListenerResult.handleResponse(singletonError(new ApiErrorWithMetadata(projectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "Invalid HTTP request"))), Arrays.asList(Pair.of("exception_message", theEx.getMessage()), Pair.of("cause_details", causeAsString)));
    }
    return ApiExceptionHandlerListenerResult.ignoreResponse();
}
Also used : TooLongFrameException(io.netty.handler.codec.TooLongFrameException) HostnameResolutionException(com.nike.riposte.server.error.exception.HostnameResolutionException) ArrayList(java.util.ArrayList) 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) 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 4 with RequestContentDeserializationException

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

the class RequestInfoImpl method deserializeContent.

protected T deserializeContent() {
    //       valid return value. Can probably fix this by making isContentDeserializerSetup() smarter.
    if (!isContentDeserializerSetup())
        return null;
    try {
        Type inputType = contentDeserializerTypeReference.getType();
        if (inputType instanceof Class) {
            Class inputTypeClass = (Class) inputType;
            // If they want a String or CharSequence then return the getRawContent() string.
            if (String.class.equals(inputTypeClass) || CharSequence.class.equals(inputTypeClass)) {
                //noinspection unchecked
                return (T) getRawContent();
            }
        }
        // Not a String or CharSequence. Do our best to deserialize.
        byte[] bytes = getRawContentBytes();
        return (bytes == null) ? null : contentDeserializer.readValue(bytes, contentDeserializerTypeReference);
    } catch (Throwable e) {
        // Something went wrong during deserialization. Throw an appropriate error.
        logger.info("Unable to deserialize request content to desired object type - {}: {}", contentDeserializerTypeReference.getType().toString(), e.getMessage());
        throw new RequestContentDeserializationException("Unable to deserialize request content to desired object type.", e, this, contentDeserializerTypeReference);
    }
}
Also used : Type(java.lang.reflect.Type) RequestContentDeserializationException(com.nike.riposte.server.error.exception.RequestContentDeserializationException)

Aggregations

RequestContentDeserializationException (com.nike.riposte.server.error.exception.RequestContentDeserializationException)4 TypeReference (com.fasterxml.jackson.core.type.TypeReference)2 Test (org.junit.Test)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 ApiError (com.nike.backstopper.apierror.ApiError)1 ApiErrorWithMetadata (com.nike.backstopper.apierror.ApiErrorWithMetadata)1 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 InvalidHttpRequestException (com.nike.riposte.server.error.exception.InvalidHttpRequestException)1 MethodNotAllowed405Exception (com.nike.riposte.server.error.exception.MethodNotAllowed405Exception)1 MultipleMatchingEndpointsException (com.nike.riposte.server.error.exception.MultipleMatchingEndpointsException)1 NativeIoExceptionWrapper (com.nike.riposte.server.error.exception.NativeIoExceptionWrapper)1 NonblockingEndpointCompletableFutureTimedOut (com.nike.riposte.server.error.exception.NonblockingEndpointCompletableFutureTimedOut)1 PathNotFound404Exception (com.nike.riposte.server.error.exception.PathNotFound404Exception)1