use of com.nike.riposte.server.http.HttpProcessingState in project riposte by Nike-Inc.
the class RequestContentDeserializerHandler method doChannelRead.
@Override
public PipelineContinuationBehavior doChannelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof LastHttpContent) {
HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
Endpoint<?> endpoint = state.getEndpointForExecution();
RequestInfo reqInfo = state.getRequestInfo();
// Don't bother trying to deserialize until we have an endpoint and the request content has fully arrived
if (endpoint != null && reqInfo.isCompleteRequestWithAllChunks()) {
// Setup the content deserializer if desired
TypeReference<?> contentTypeRef = endpoint.requestContentType();
if (contentTypeRef != null) {
// A non-null TypeReference is available, so deserialization is possible. Retrieve the appropriate
// deserializer and setup the RequestInfo so that it can lazily deserialize when requested.
ObjectMapper deserializer = endpoint.customRequestContentDeserializer(reqInfo);
if (deserializer == null)
deserializer = defaultRequestContentDeserializer;
//noinspection unchecked
reqInfo.setupContentDeserializer(deserializer, contentTypeRef);
}
}
}
return PipelineContinuationBehavior.CONTINUE;
}
use of com.nike.riposte.server.http.HttpProcessingState in project riposte by Nike-Inc.
the class RequestFilterHandler method handleFilterLogic.
protected PipelineContinuationBehavior handleFilterLogic(ChannelHandlerContext ctx, Object msg, BiFunction<RequestAndResponseFilter, RequestInfo, RequestInfo> normalFilterCall, BiFunction<RequestAndResponseFilter, RequestInfo, Pair<RequestInfo, Optional<ResponseInfo<?>>>> shortCircuitFilterCall) {
HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
RequestInfo<?> currentReqInfo = state.getRequestInfo();
// Run through each filter.
for (RequestAndResponseFilter filter : filters) {
try {
// See if we're supposed to do short circuit call or not
if (filter.isShortCircuitRequestFilter()) {
Pair<RequestInfo, Optional<ResponseInfo<?>>> result = shortCircuitFilterCall.apply(filter, currentReqInfo);
if (result != null) {
currentReqInfo = requestInfoUpdateNoNulls(currentReqInfo, result.getLeft());
// See if we need to short circuit.
ResponseInfo<?> responseInfo = (result.getRight() == null) ? null : result.getRight().orElse(null);
if (responseInfo != null) {
// full, not chunked.
if (responseInfo.isChunkedResponse()) {
throw new IllegalStateException("RequestAndResponseFilter should never return a " + "chunked ResponseInfo when short circuiting.");
}
state.setRequestInfo(currentReqInfo);
state.setResponseInfo(responseInfo);
// Fire the short-circuit event that will get the desired response info sent to the caller.
ctx.fireChannelRead(LastOutboundMessageSendFullResponseInfo.INSTANCE);
// Tell this event to stop where it is.
return PipelineContinuationBehavior.DO_NOT_FIRE_CONTINUE_EVENT;
}
}
} else {
currentReqInfo = requestInfoUpdateNoNulls(currentReqInfo, normalFilterCall.apply(filter, currentReqInfo));
}
} catch (Throwable ex) {
logger.error("An error occurred while processing a request filter. This error will be ignored and the " + "filtering/processing will continue normally, however this error should be fixed (filters should " + "never throw errors). filter_class={}", filter.getClass().getName(), ex);
}
}
// All the filters have been processed, so set the state to whatever the current request info says.
state.setRequestInfo(currentReqInfo);
// No short circuit if we reach here, so continue normally.
return PipelineContinuationBehavior.CONTINUE;
}
use of com.nike.riposte.server.http.HttpProcessingState 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()) {
if (state == null)
logger.error("HttpProcessingState is null for this request. This should not be possible.");
// 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) {
throwExceptionIfNotSuccessfullyDecoded((HttpRequest) msg);
RequestInfo<?> requestInfo = new RequestInfoImpl<>((HttpRequest) msg);
state.setRequestInfo(requestInfo);
} else if (msg instanceof HttpContent) {
HttpContent httpContentMsg = (HttpContent) msg;
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 TooLongFrameException("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.http.HttpProcessingState in project riposte by Nike-Inc.
the class ExceptionHandlingHandler method doExceptionCaught.
@Override
public PipelineContinuationBehavior doExceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// We expect to end up here when handlers previously in the pipeline throw an error, so do the normal
// processError call.
HttpProcessingState state = getStateAndCreateIfNeeded(ctx, cause);
if (state.isResponseSendingStarted()) {
logger.info("A response has already been started. Ignoring this exception since it's secondary. NOTE: This often " + "occurs when an error happens repeatedly on multiple chunks of a request or response - only the " + "first one is processed into the error sent to the user. The original error is probably higher up in " + "the logs. ignored_secondary_exception=\"{}\"", cause.toString());
return PipelineContinuationBehavior.DO_NOT_FIRE_CONTINUE_EVENT;
} else {
ResponseInfo<ErrorResponseBody> responseInfo = processError(state, null, cause);
if (shouldForceConnectionCloseAfterResponseSent(cause))
responseInfo.setForceConnectionCloseAfterResponseSent(true);
state.setResponseInfo(responseInfo);
}
return PipelineContinuationBehavior.CONTINUE;
}
use of com.nike.riposte.server.http.HttpProcessingState in project riposte by Nike-Inc.
the class ResponseSenderHandler method sendResponse.
protected void sendResponse(ChannelHandlerContext ctx, Object msg) throws JsonProcessingException {
try {
HttpProcessingState state = ChannelAttributes.getHttpProcessingStateForChannel(ctx).get();
if (state.isResponseSendingLastChunkSent()) {
if (logger.isDebugEnabled()) {
runnableWithTracingAndMdc(() -> logger.debug("A response has already been sent. " + "Ignoring this method call to send response."), ctx).run();
}
return;
}
RequestInfo<?> requestInfo = state.getRequestInfo();
if (requestInfo == null)
requestInfo = RequestInfoImpl.dummyInstanceForUnknownRequests();
ResponseInfo<?> responseInfo = state.getResponseInfo();
Endpoint<?> endpointExecuted = state.getEndpointForExecution();
ObjectMapper customSerializer = (endpointExecuted == null) ? null : endpointExecuted.customResponseContentSerializer(requestInfo);
if (msg != null && msg instanceof ChunkedOutboundMessage) {
// Chunked message. Stream it out.
responseSender.sendResponseChunk(ctx, requestInfo, responseInfo, (ChunkedOutboundMessage) msg);
} else {
// Full message. Send it.
if (containsErrorResponseBody(responseInfo)) {
//noinspection unchecked
responseSender.sendErrorResponse(ctx, requestInfo, (ResponseInfo<ErrorResponseBody>) responseInfo);
} else
responseSender.sendFullResponse(ctx, requestInfo, responseInfo, customSerializer);
}
} catch (Throwable t) {
runnableWithTracingAndMdc(() -> logger.error("An unexpected error occurred while attempting to send a response.", t), ctx).run();
throw t;
}
}
Aggregations