Search in sources :

Example 1 with RestLiAttachmentReaderException

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);
        }
    }
}
Also used : RestResponse(com.linkedin.r2.message.rest.RestResponse) InputStream(java.io.InputStream) IOException(java.io.IOException) RestLiAttachmentReaderException(com.linkedin.restli.common.attachments.RestLiAttachmentReaderException) RestLiAttachmentReader(com.linkedin.restli.common.attachments.RestLiAttachmentReader)

Aggregations

RestResponse (com.linkedin.r2.message.rest.RestResponse)1 RestLiAttachmentReader (com.linkedin.restli.common.attachments.RestLiAttachmentReader)1 RestLiAttachmentReaderException (com.linkedin.restli.common.attachments.RestLiAttachmentReaderException)1 IOException (java.io.IOException)1 InputStream (java.io.InputStream)1