@Override public void onDrainComplete() { _topLevelReaderCallback.onStreamError(Messages.toStreamException(RestException.forError(500, "Serious error. " + "There should never be a call to drain part data when decoding the first part in a multipart mime response."))); }
private static void validateHeaders(RestRequest request) throws RestException { boolean supported; try { supported = ContentType.getContentType(request.getHeader(RestConstants.HEADER_CONTENT_TYPE)).isPresent(); } catch (MimeTypeParseException e) { throw RestException.forError(HttpStatus.S_400_BAD_REQUEST.getCode(), "Invalid content type"); } if (!supported) { _log.warn("Unsupported content type: " + request.getHeader(RestConstants.HEADER_CONTENT_TYPE)); // TODO Add back the check for content type. // throw RestException.forError(HttpStatus.S_415_UNSUPPORTED_MEDIA_TYPE.getCode(), "Unsupported content type"); } }
if (contentType.getBaseType().equalsIgnoreCase(RestConstants.HEADER_VALUE_MULTIPART_RELATED)) callback.onError(RestException.forError(415, "This server cannot handle requests with a content type of multipart/related")); return true; callback.onError(RestException.forError(406, "This server cannot handle requests with an accept type of multipart/related")); return true; callback.onError(RestException.forError(400, "Unable to parse content or accept types.")); return true;
@Override public void onStreamError(Throwable throwable) { //At this point this could be a an exception thrown due to malformed data or this could be an exception thrown //due to an invocation of a callback. For example, an exception thrown due to an invocation of a callback could occur when //handleResourceRequest(). Though this should never happen because handleResourceRequest() catches everything //and invokes the corresponding RequestExecutionCallback. if (throwable instanceof MultiPartIllegalFormatException) { //If its an illegally formed request, then we send back 400. _streamResponseCallback.onError(Messages.toStreamException(RestException.forError(400, "Illegally formed multipart payload"))); return; } //Otherwise this is an internal server error. R2 will convert this to a 500 for us. As mentioned this should never happen. _streamResponseCallback.onError(throwable); } }
@Override public void handleRestRequest(RestRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<RestResponse> callback) { try { _restHandler.handleRequest(req, requestContext, new TransportCallbackAdapter<RestResponse>(callback)); } catch (Exception e) { callback.onResponse(TransportResponseImpl.<RestResponse>error(RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e))); } }
/** * Extracts individual requests from the given REST request. * * @return a non-empty map of individual requests * @throws RestException if the payload of the RestRequest is ill-formed, contains no individual requests, or contains * more than allowable individual requests. */ private IndividualRequestMap extractIndividualRequests(RestRequest restRequest) throws RestException { validateHeaders(restRequest); DataMap data = DataMapUtils.readMap(restRequest); MultiplexedRequestContent multiplexedRequestContent = DataTemplateUtil.wrap(data, MultiplexedRequestContent.class); IndividualRequestMap individualRequests = multiplexedRequestContent.getRequests(); int totalCount = totalRequestCount(individualRequests); if (totalCount == 0) { throw RestException.forError(HttpStatus.S_400_BAD_REQUEST.getCode(), "No individual requests to process"); } if (totalCount > _maximumRequestsNumber) { throw RestException.forError(HttpStatus.S_400_BAD_REQUEST.getCode(), "The server is configured to serve up to " + _maximumRequestsNumber + " requests, but received " + totalCount); } return individualRequests; }
@Override public void handleStreamRequest(final StreamRequest req, final Map<String, String> wireAttrs, final RequestContext requestContext, final TransportCallback<StreamResponse> callback) { try { _streamHandler.handleRequest(req, requestContext, new TransportCallbackAdapter<StreamResponse>(callback)); } catch (Exception e) { final Exception ex = RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e); callback.onResponse(TransportResponseImpl.<StreamResponse>error(ex)); } } }
@Override public void handleRestRequest(RestRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<RestResponse> callback) { final RestRequestHandler handler = getHandler(req.getURI(), _restHandlers, DEFAULT_REST_HANDLER); try { handler.handleRequest(req, requestContext, new TransportCallbackAdapter<RestResponse>(callback)); } catch (Exception e) { callback.onResponse(TransportResponseImpl.<RestResponse>error(RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e))); } }
@Override public void handleStreamRequest(StreamRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<StreamResponse> callback) { final StreamRequestHandler handler = getHandler(req.getURI(), _streamHandlers, DEFAULT_STREAM_HANDLER); try { handler.handleRequest(req, requestContext, new TransportCallbackAdapter<StreamResponse>(callback)); } catch (Exception e) { final Exception ex = RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e); callback.onResponse(TransportResponseImpl.<StreamResponse>error(ex)); } }
@Override public void handleRestRequest(RestRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<RestResponse> callback) { final URI address = req.getURI(); RestRequestHandler handler = _restHandlers.get(address); if (handler == null) { callback.onResponse(TransportResponseImpl.success(RestStatus.responseForStatus(RestStatus.NOT_FOUND, "No resource for URI:" + address))); return; } try { handler.handleRequest(req, requestContext, new TransportCallbackAdapter<RestResponse>(callback)); } catch (Exception e) { callback.onResponse(TransportResponseImpl.<RestResponse>error(RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e))); } }
if (contentTypeString == null) _streamResponseCallback.onError(Messages.toStreamException(RestException.forError(400, "Incorrect multipart/related payload. First part must contain the Content-Type!"))); return; _streamResponseCallback.onError(Messages.toStreamException(RestException.forError(400, "Unable to parse Content-Type: " + contentTypeString))); return; _streamResponseCallback.onError(Messages.toStreamException(RestException.forError(415, "Unknown Content-Type for first part of multipart/related payload: " + contentTypeString))); return;
@Override public void onFinished() { //Verify we actually had some parts. User attachments do not have to be present but for multipart/related //there must be atleast some payload. if (_requestPayload == null) { _streamResponseCallback.onError(Messages.toStreamException(RestException.forError(400, "Did not receive any parts in the multipart mime request!"))); return; } //At this point, this means that the multipart mime envelope didn't have any attachments (apart from the //json/pson payload). Technically the rest.li client would not create a payload like this, but to keep the protocol //somewhat flexible we will allow it. //If there had been more attachments, then onNewPart() above would be invoked and we would have passed the //attachment reader onto the framework. //It is also important to note that this callback (TopLevelReaderCallback) will no longer be used. We provide //null to the application developer since there are no attachments present. Therefore it is not possible for this //callback to ever be used again. This is a bit different then the onNewPart() case above because in that case //there is a valid non-null attachment reader provided to the resource method. In that case application developers //could call drainAllAttachments() without registering a callback which would then lead to onDrainComplete() being //invoked. _restRequestBuilder.setEntity(_requestPayload); RestRequest restRequest = _restRequestBuilder.build(); //We have no attachments so we pass null for the reader. // Debug request should have already handled by one of the request handlers. _fallback.handleResourceRequest(restRequest, _routingResult, toRestResponseCallback(_streamResponseCallback, _routingResult.getContext())); }
@Override public void handleStreamRequest(StreamRequest req, Map<String, String> wireAttrs, RequestContext requestContext, TransportCallback<StreamResponse> callback) { final URI address = req.getURI(); final StreamRequestHandler handler = _streamHandlers.get(address); if (handler == null) { final RestResponse response = RestStatus.responseForStatus(RestStatus.NOT_FOUND, "No resource for URI: " + address); callback.onResponse(TransportResponseImpl.success(Messages.toStreamResponse(response))); req.getEntityStream().setReader(new DrainReader()); return; } try { handler.handleRequest(req, requestContext, new TransportCallbackAdapter<StreamResponse>(callback)); } catch (Exception e) { final Exception ex = RestException.forError(RestStatus.INTERNAL_SERVER_ERROR, e); callback.onResponse(TransportResponseImpl.<StreamResponse>error(ex)); } }
callback.onError(Messages.toStreamException(RestException.forError(400, "Unable to parse Content-Type: " + header))); return true;