Search in sources :

Example 6 with ContentType

use of com.linkedin.restli.common.ContentType in project rest.li by linkedin.

the class TestContentType method testNullContentType.

@Test
public void testNullContentType() throws MimeTypeParseException {
    ContentType contentType = ContentType.getContentType(null).get();
    // default to JSON for null content-type
    Assert.assertEquals(ContentType.JSON, contentType);
}
Also used : ContentType(com.linkedin.restli.common.ContentType) Test(org.testng.annotations.Test)

Example 7 with ContentType

use of com.linkedin.restli.common.ContentType in project rest.li by linkedin.

the class TestContentType method testGetRequestNullContentType.

@Test
public void testGetRequestNullContentType() throws MimeTypeParseException {
    ContentType contentType = ContentType.getRequestContentType(null, TEST_URI).get();
    Assert.assertEquals(ContentType.JSON, contentType);
}
Also used : ContentType(com.linkedin.restli.common.ContentType) Test(org.testng.annotations.Test)

Example 8 with ContentType

use of com.linkedin.restli.common.ContentType in project rest.li by linkedin.

the class RestLiSymbolTableRequestHandler method handleRequest.

@Override
public void handleRequest(RestRequest request, RequestContext requestContext, Callback<RestResponse> callback) {
    if (HttpMethod.GET != HttpMethod.valueOf(request.getMethod())) {
        LOGGER.error("GET is expected, but " + request.getMethod() + " received");
        callback.onError(RestException.forError(HttpStatus.S_405_METHOD_NOT_ALLOWED.getCode(), "Invalid method"));
        return;
    }
    // 
    // Determine response content type based on accept header.
    // Assume protobuf2 if no accept header is specified. Note that this is a deviation from the rest of rest.li
    // which assumes JSON as the default, for efficiency reasons.
    // 
    ContentType type;
    String mimeType = Optional.ofNullable(request.getHeader(RestConstants.HEADER_ACCEPT)).orElse(RestConstants.HEADER_VALUE_APPLICATION_PROTOBUF2);
    try {
        type = ContentType.getContentType(mimeType).orElseThrow(() -> new MimeTypeParseException("Invalid accept type: " + mimeType));
    } catch (MimeTypeParseException e) {
        LOGGER.error("Could not handle accept type", e);
        callback.onError(RestException.forError(HttpStatus.S_406_NOT_ACCEPTABLE.getCode(), "Invalid accept type: " + mimeType));
        return;
    }
    final String path = request.getURI().getRawPath();
    final List<UriComponent.PathSegment> pathSegments = UriComponent.decodePath(path, true);
    final SymbolTableProvider provider = SymbolTableProviderHolder.INSTANCE.getSymbolTableProvider();
    SymbolTable symbolTable = null;
    // at this point, `handleRequest` has verified that the incoming request is a symbolTable request.
    // The URL can be one of two options:
    // .../symbolTable/tableName
    // .../symbolTable
    // We check if the last path segments is "symbolTable", and if it is, we call provider.getResponseSymbolTable
    // because we do not know the table name.
    // Otherwise, we call provider.getSymbolTable
    int pathSize = pathSegments.size();
    try {
        if (pathSegments.get(pathSize - 1).getPath().equals(SYMBOL_TABLE_URI_PATH)) {
            symbolTable = provider.getResponseSymbolTable(request.getURI(), request.getHeaders());
        } else if (pathSegments.get(pathSize - 2).getPath().equals(SYMBOL_TABLE_URI_PATH)) {
            symbolTable = provider.getSymbolTable(pathSegments.get(pathSize - 1).getPath());
        } else {
            LOGGER.error("request is malformed for handling symbolTable" + request.getURI());
        }
    } catch (IllegalStateException e) {
        LOGGER.error("Exception retrieving symbol table for URI " + request.getURI());
        symbolTable = null;
    }
    if (symbolTable == null) {
        LOGGER.error("Did not find symbol table for path " + path);
        callback.onError(RestException.forError(HttpStatus.S_404_NOT_FOUND.getCode(), "Did not find symbol table"));
        return;
    }
    try {
        // Cache key is the name of the symbol table concatenated with the type used to serialize the payload.
        String cacheKey = symbolTable.getName() + ":" + type.getHeaderKey();
        ByteString serializedTable = _symbolTableNameToSerializedBytesCache.getIfPresent(cacheKey);
        if (serializedTable == null) {
            serializedTable = SymbolTableSerializer.toByteString(type.getCodec(), symbolTable);
            _symbolTableNameToSerializedBytesCache.put(cacheKey, serializedTable);
        }
        RestResponse restResponse = new RestResponseBuilder().setStatus(HttpStatus.S_200_OK.getCode()).setHeader(RestConstants.HEADER_CONTENT_TYPE, type.getHeaderKey()).setEntity(serializedTable).build();
        callback.onSuccess(restResponse);
    } catch (IOException e) {
        callback.onError(e);
    }
}
Also used : MimeTypeParseException(javax.activation.MimeTypeParseException) SymbolTableProvider(com.linkedin.data.codec.symbol.SymbolTableProvider) DefaultSymbolTableProvider(com.linkedin.data.codec.symbol.DefaultSymbolTableProvider) ContentType(com.linkedin.restli.common.ContentType) ByteString(com.linkedin.data.ByteString) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder) SymbolTable(com.linkedin.data.codec.symbol.SymbolTable) ByteString(com.linkedin.data.ByteString) IOException(java.io.IOException)

Example 9 with ContentType

use of com.linkedin.restli.common.ContentType in project rest.li by linkedin.

the class ResponseUtils method encodeResult.

private static RestResponseBuilder encodeResult(String mimeType, URI requestUri, Map<String, String> requestHeaders, RestResponseBuilder builder, DataMap dataMap) {
    try {
        ContentType type = ContentType.getResponseContentType(mimeType, requestUri, requestHeaders).orElseThrow(() -> new RestLiServiceException(HttpStatus.S_406_NOT_ACCEPTABLE, "Requested mime type for encoding is not supported. Mimetype: " + mimeType));
        assert type != null;
        builder.setHeader(RestConstants.HEADER_CONTENT_TYPE, type.getHeaderKey());
        builder.setEntity(DataMapUtils.mapToByteString(dataMap, type.getCodec()));
    } catch (MimeTypeParseException e) {
        throw new RestLiServiceException(HttpStatus.S_406_NOT_ACCEPTABLE, "Invalid mime type: " + mimeType);
    }
    return builder;
}
Also used : MimeTypeParseException(javax.activation.MimeTypeParseException) ContentType(com.linkedin.restli.common.ContentType) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException)

Example 10 with ContentType

use of com.linkedin.restli.common.ContentType in project rest.li by linkedin.

the class StreamRestLiServer method handleStructuredDataResourceRequest.

private void handleStructuredDataResourceRequest(StreamRequest request, RoutingResult routingResult, Callback<?> callback, Function<ContentType, Callback<RestLiResponse>> restLiResponseCallbackConstructor, Consumer<RestRequest> fallbackRequestProcessor) {
    ContentType reqContentType, respContentType;
    try {
        // TODO: We should throw exception instead of defaulting to JSON when the request content type is non-null and
        // unrecognized. This behavior was inadvertently changed in commit d149605e4181349b64180bdfe0b4d24a294dc6f6
        // when this logic was moved from DataMapUtils.readMapWithExceptions() to DataMapConverter.dataMapToByteString().
        reqContentType = ContentType.getContentType(request.getHeader(RestConstants.HEADER_CONTENT_TYPE)).orElse(ContentType.JSON);
        String respMimeType = routingResult.getContext().getResponseMimeType();
        respContentType = ContentType.getResponseContentType(respMimeType, request.getURI(), request.getHeaders()).orElseThrow(() -> new RestLiServiceException(HttpStatus.S_406_NOT_ACCEPTABLE, "Requested mime type for encoding is not supported. Mimetype: " + respMimeType));
    } catch (MimeTypeParseException e) {
        callback.onError(e);
        return;
    }
    StreamDataCodec reqCodec = reqContentType.getStreamCodec();
    StreamDataCodec respCodec = respContentType.getStreamCodec();
    if (_useStreamCodec && reqCodec != null && respCodec != null) {
        final RequestContext requestContext = routingResult.getContext().getRawRequestContext();
        TimingContextUtil.beginTiming(requestContext, FrameworkTimingKeys.SERVER_REQUEST_RESTLI_DESERIALIZATION.key());
        reqCodec.decodeMap(EntityStreamAdapters.toGenericEntityStream(request.getEntityStream())).handle((dataMap, e) -> {
            TimingContextUtil.endTiming(requestContext, FrameworkTimingKeys.SERVER_REQUEST_RESTLI_DESERIALIZATION.key());
            Throwable error = null;
            if (e == null) {
                try {
                    handleResourceRequest(request, routingResult, dataMap, restLiResponseCallbackConstructor.apply(respContentType));
                } catch (Throwable throwable) {
                    error = throwable;
                }
            } else {
                error = buildPreRoutingStreamException(new RoutingException("Cannot parse request entity", HttpStatus.S_400_BAD_REQUEST.getCode(), e), request);
            }
            if (error != null) {
                log.error("Fail to handle structured stream request", error);
                callback.onError(error);
            }
            // handle function requires a return statement although there is no more completion stage.
            return null;
        });
    } else {
        // Fallback to fully-buffered request and response processing.
        Messages.toRestRequest(request).handle((restRequest, e) -> {
            if (e == null) {
                try {
                    fallbackRequestProcessor.accept(restRequest);
                } catch (Throwable throwable) {
                    e = throwable;
                }
            }
            if (e != null) {
                log.error("Fail to handle structured toRest request", e);
                callback.onError(e);
            }
            // handle function requires a return statement although there is no more completion stage.
            return null;
        });
    }
}
Also used : MimeTypeParseException(javax.activation.MimeTypeParseException) ContentType(com.linkedin.restli.common.ContentType) StreamDataCodec(com.linkedin.data.codec.entitystream.StreamDataCodec) ByteString(com.linkedin.data.ByteString) RequestContext(com.linkedin.r2.message.RequestContext)

Aggregations

ContentType (com.linkedin.restli.common.ContentType)21 Test (org.testng.annotations.Test)14 ByteString (com.linkedin.data.ByteString)4 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)4 MimeTypeParseException (javax.activation.MimeTypeParseException)3 RestRequest (com.linkedin.r2.message.rest.RestRequest)2 RestResponse (com.linkedin.r2.message.rest.RestResponse)2 MultiplexerUriBuilder (com.linkedin.restli.client.uribuilders.MultiplexerUriBuilder)2 IOException (java.io.IOException)2 DataMap (com.linkedin.data.DataMap)1 StreamDataCodec (com.linkedin.data.codec.entitystream.StreamDataCodec)1 DefaultSymbolTableProvider (com.linkedin.data.codec.symbol.DefaultSymbolTableProvider)1 SymbolTable (com.linkedin.data.codec.symbol.SymbolTable)1 SymbolTableProvider (com.linkedin.data.codec.symbol.SymbolTableProvider)1 MultiPartMIMEWriter (com.linkedin.multipart.MultiPartMIMEWriter)1 MessageHeadersBuilder (com.linkedin.r2.message.MessageHeadersBuilder)1 RequestContext (com.linkedin.r2.message.RequestContext)1 RestResponseBuilder (com.linkedin.r2.message.rest.RestResponseBuilder)1 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)1 ByteStringWriter (com.linkedin.r2.message.stream.entitystream.ByteStringWriter)1