use of com.nike.riposte.server.error.exception.RequestTooBigException in project riposte by Nike-Inc.
the class BackstopperRiposteFrameworkErrorHandlerListenerTest method should_handle_RequestTooBigException.
@Test
public void should_handle_RequestTooBigException() {
// given
String exMsg = UUID.randomUUID().toString();
RequestTooBigException ex = new RequestTooBigException(exMsg);
// when
ApiExceptionHandlerListenerResult result = listener.shouldHandleException(ex);
// then
assertThat(result.shouldHandleResponse).isTrue();
assertThat(result.errors).isEqualTo(singletonError(new ApiErrorWithMetadata(testProjectApiErrors.getMalformedRequestApiError(), Pair.of("cause", "The request exceeded the maximum payload size allowed"))));
assertThat(result.extraDetailsForLogging.get(0).getLeft()).isEqualTo("exception_message");
assertThat(result.extraDetailsForLogging.get(0).getRight()).isEqualTo(exMsg);
assertThat(result.extraDetailsForLogging.get(1).getLeft()).isEqualTo("decoder_exception");
assertThat(result.extraDetailsForLogging.get(1).getRight()).isEqualTo("true");
}
use of com.nike.riposte.server.error.exception.RequestTooBigException in project riposte by Nike-Inc.
the class RequestInfoSetterHandler method doChannelRead.
@Override
public PipelineContinuationBehavior doChannelRead(ChannelHandlerContext ctx, Object msg) {
try {
HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
if (state == null || state.isResponseSendingLastChunkSent() || !ctx.channel().isActive()) {
if (state == null)
logger.error("HttpProcessingState is null for this request. This should not be possible.");
// chunk and not process anything further.
return PipelineContinuationBehavior.DO_NOT_FIRE_CONTINUE_EVENT;
}
// We have a HttpProcessingState. Process the message and continue the pipeline processing.
if (msg instanceof HttpRequest) {
// This should be done by RoutingHandler already but it doesn't hurt to double check here, and it
// keeps this handler independent in case things get refactored again in the future.
handlerUtils.createRequestInfoFromNettyHttpRequestAndHandleStateSetupIfNecessary((HttpRequest) msg, state);
// The above method call should set RequestInfo on the state, even if the Netty HttpRequest obj was
// invalid (if it's invalid it will default to a synthetic/dummy RequestInfo that indicates an
// error). But if it *is* invalid, we want to throw an exception here to immediately invoke
// error handling behavior.
handlerUtils.throwExceptionIfNotSuccessfullyDecoded((HttpRequest) msg);
} else if (msg instanceof HttpContent) {
HttpContent httpContentMsg = (HttpContent) msg;
handlerUtils.throwExceptionIfNotSuccessfullyDecoded(httpContentMsg);
RequestInfo<?> requestInfo = state.getRequestInfo();
if (requestInfo == null) {
throw new IllegalStateException("Found a HttpContent msg without a RequestInfo stored in the HttpProcessingState. " + "This should be impossible");
}
int currentRequestLengthInBytes = requestInfo.addContentChunk(httpContentMsg);
int configuredMaxRequestSize = getConfiguredMaxRequestSize(state.getEndpointForExecution(), globalConfiguredMaxRequestSizeInBytes);
if (!isMaxRequestSizeValidationDisabled(configuredMaxRequestSize) && currentRequestLengthInBytes > configuredMaxRequestSize) {
throw new RequestTooBigException("Request raw content length exceeded configured max request size of " + configuredMaxRequestSize);
}
}
return PipelineContinuationBehavior.CONTINUE;
} finally {
// For HttpContent messages, either requestInfo.addContentChunk() has been called and the reference count
// increased (i.e. the RequestInfo is now responsible for releasing the content when
// requestInfo.releaseAllResources() is called), or an exception has been thrown. In any case, we
// are done with any message from a pipeline perspective and can reduce its reference count.
ReferenceCountUtil.release(msg);
}
}
use of com.nike.riposte.server.error.exception.RequestTooBigException 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();
}
Aggregations