use of com.linkedin.restli.common.attachments.RestLiAttachmentReaderException in project rest.li by linkedin.
the class ParseqTraceDebugRequestHandler method handleRequest.
@Override
public void handleRequest(final RestRequest request, final RequestContext context, final ResourceDebugRequestHandler resourceDebugRequestHandler, final RestLiAttachmentReader attachmentReader, final RequestExecutionCallback<RestResponse> callback) {
//Find out the path coming after the "__debug" path segment
String fullPath = request.getURI().getPath();
int debugSegmentIndex = fullPath.indexOf(RestLiServer.DEBUG_PATH_SEGMENT);
final String debugHandlerPath = fullPath.substring(debugSegmentIndex + RestLiServer.DEBUG_PATH_SEGMENT.length() + 1);
assert (debugHandlerPath.startsWith(HANDLER_ID));
//Decide whether this is a user issued debug request or a follow up static content request for tracevis html.
if (debugHandlerPath.equals(TRACEVIS_PATH) || debugHandlerPath.equals(RAW_PATH)) {
//Execute the request as if it was a regular rest.li request through resource debug request handler.
//By using the returned execution report shape the response accordingly.
//Since we are executing the request as though its a normal rest.li request, we don't have to
//drain the incoming request attachments. Our concerns are only the scenarios listed in the onError() and onSuccess()
//in the callback.
resourceDebugRequestHandler.handleRequest(request, context, new RequestExecutionCallback<RestResponse>() {
@Override
public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
//this is sent back as a success so we handle it here instead.
if (requestAttachmentReader != null && !requestAttachmentReader.haveAllAttachmentsFinished()) {
try {
//Here we simply call drainAllAttachments. At this point the current callback assigned is likely the
//TopLevelReaderCallback in RestLiServer. When this callback is notified that draining is completed (via
//onDrainComplete()), then no action is taken (which is what is desired).
//
//We can go ahead and send the error back to the client while we continue to drain the
//bytes in the background. Note that it could be the case that even though there is an exception thrown,
//that application code could still be reading these attachments. In such a case we would not be able to call
//drainAllAttachments() successfully. Therefore we handle this exception and swallow.
requestAttachmentReader.drainAllAttachments();
} catch (RestLiAttachmentReaderException readerException) {
//Swallow here.
//It could be the case that the application code is still absorbing attachments.
//We back off and send the original response to the client. If the application code is not doing this,
//there is a chance for a resource leak. In such a case the framework can do nothing else.
}
}
//Drop all attachments to send back on the ground as well.
if (responseAttachments != null) {
responseAttachments.getResponseAttachmentsBuilder().build().abortAllDataSources(e);
}
sendDebugResponse(callback, executionReport, debugHandlerPath);
}
@Override
public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
//to drain them here.
if (responseAttachments != null) {
responseAttachments.getResponseAttachmentsBuilder().build().abortAllDataSources(new UnsupportedOperationException("Response attachments " + "may not be sent back for parseq trace debugging"));
}
sendDebugResponse(callback, executionReport, debugHandlerPath);
}
});
} else {
//We know that the request is a static content request. So here we figure out the internal path for the
//JAR resource from the request path. A request uri such as "/__debug/parseqtrace/trace.html" translates to
//"/tracevis/trace.html" for the resource path.
String resourcePath = debugHandlerPath.replaceFirst(HANDLER_ID, ENTRY_PATH_SEGMENT_TRACEVIS);
ClassLoader currentClassLoader = getClass().getClassLoader();
InputStream resourceStream = currentClassLoader.getResourceAsStream(resourcePath);
String mediaType = null;
if (resourceStream != null) {
mediaType = determineMediaType(resourcePath);
}
// If the requested file type is not supported by this debug request handler, return 404.
if (mediaType == null) {
callback.onError(new RestLiServiceException(HttpStatus.S_404_NOT_FOUND), null, null, null);
}
try {
sendByteArrayAsResponse(callback, IOUtils.toByteArray(resourceStream), mediaType);
} catch (IOException exception) {
callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR, exception), null, null, null);
}
}
}
Aggregations