Search in sources :

Example 6 with StreamingCompressor

use of com.linkedin.r2.filter.compression.streaming.StreamingCompressor in project rest.li by linkedin.

the class TestStreamingCompression method testCompressThenDecompress.

private void testCompressThenDecompress(StreamingCompressor compressor, byte[] origin) throws CompressionException, ExecutionException, InterruptedException {
    ByteWriter writer = new ByteWriter(origin);
    EntityStream uncompressedStream = EntityStreams.newEntityStream(writer);
    EntityStream compressedStream = compressor.deflate(uncompressedStream);
    EntityStream decompressedStream = compressor.inflate(compressedStream);
    FutureCallback<byte[]> callback = new FutureCallback<byte[]>();
    decompressedStream.setReader(new ByteReader(callback));
    byte[] result = callback.get();
    Assert.assertEquals(result, origin);
}
Also used : EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) FutureCallback(com.linkedin.common.callback.FutureCallback)

Example 7 with StreamingCompressor

use of com.linkedin.r2.filter.compression.streaming.StreamingCompressor in project rest.li by linkedin.

the class ClientStreamCompressionFilter method onStreamResponse.

/**
   *  Decompresses server response
   */
@Override
public void onStreamResponse(StreamResponse res, RequestContext requestContext, Map<String, String> wireAttrs, NextFilter<StreamRequest, StreamResponse> nextFilter) {
    Boolean decompressionOff = (Boolean) requestContext.getLocalAttr(R2Constants.RESPONSE_DECOMPRESSION_OFF);
    if (decompressionOff == null || !decompressionOff) {
        //Check for header encoding
        String compressionHeader = res.getHeader(HttpConstants.CONTENT_ENCODING);
        //decompress if necessary
        if (compressionHeader != null) {
            final StreamEncodingType encoding = StreamEncodingType.get(compressionHeader.trim().toLowerCase());
            if (encoding == null) {
                nextFilter.onError(new IllegalArgumentException("Server returned unrecognized content encoding: " + compressionHeader), requestContext, wireAttrs);
                return;
            }
            final StreamingCompressor compressor = encoding.getCompressor(_executor);
            EntityStream uncompressedStream = compressor.inflate(res.getEntityStream());
            StreamResponseBuilder builder = res.builder();
            Map<String, String> headers = stripHeaders(builder.getHeaders(), HttpConstants.CONTENT_ENCODING, HttpConstants.CONTENT_LENGTH);
            res = builder.setHeaders(headers).build(uncompressedStream);
        }
    }
    nextFilter.onResponse(res, requestContext, wireAttrs);
}
Also used : EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) StreamingCompressor(com.linkedin.r2.filter.compression.streaming.StreamingCompressor) StreamEncodingType(com.linkedin.r2.filter.compression.streaming.StreamEncodingType)

Example 8 with StreamingCompressor

use of com.linkedin.r2.filter.compression.streaming.StreamingCompressor in project rest.li by linkedin.

the class ClientStreamCompressionFilter method onStreamRequest.

/**
   * Optionally compresses outgoing Stream requests
   * */
public void onStreamRequest(StreamRequest req, final RequestContext requestContext, final Map<String, String> wireAttrs, final NextFilter<StreamRequest, StreamResponse> nextFilter) {
    //Set accepted encoding for compressed response
    String operation = (String) requestContext.getLocalAttr(R2Constants.OPERATION);
    if (!_acceptEncodingHeader.isEmpty() && _helper.shouldCompressResponseForOperation(operation)) {
        CompressionOption responseCompressionOverride = (CompressionOption) requestContext.getLocalAttr(R2Constants.RESPONSE_COMPRESSION_OVERRIDE);
        req = addResponseCompressionHeaders(responseCompressionOverride, req);
    }
    if (_requestContentEncoding != StreamEncodingType.IDENTITY) {
        final StreamRequest request = req;
        final StreamingCompressor compressor = _requestContentEncoding.getCompressor(_executor);
        CompressionOption option = (CompressionOption) requestContext.getLocalAttr(R2Constants.REQUEST_COMPRESSION_OVERRIDE);
        if (option == null || option != CompressionOption.FORCE_OFF) {
            final int threshold = option == CompressionOption.FORCE_ON ? 0 : _requestCompressionConfig.getCompressionThreshold();
            PartialReader reader = new PartialReader(threshold, new Callback<EntityStream[]>() {

                @Override
                public void onError(Throwable ex) {
                    nextFilter.onError(ex, requestContext, wireAttrs);
                }

                @Override
                public void onSuccess(EntityStream[] result) {
                    if (result.length == 1) {
                        StreamRequest uncompressedRequest = request.builder().build(result[0]);
                        nextFilter.onRequest(uncompressedRequest, requestContext, wireAttrs);
                    } else {
                        StreamRequestBuilder builder = request.builder();
                        EntityStream compressedStream = compressor.deflate(EntityStreams.newEntityStream(new CompositeWriter(result)));
                        Map<String, String> headers = stripHeaders(builder.getHeaders(), HttpConstants.CONTENT_LENGTH);
                        StreamRequest compressedRequest = builder.setHeaders(headers).setHeader(HttpConstants.CONTENT_ENCODING, compressor.getContentEncodingName()).build(compressedStream);
                        nextFilter.onRequest(compressedRequest, requestContext, wireAttrs);
                    }
                }
            });
            req.getEntityStream().setReader(reader);
            return;
        }
    }
    nextFilter.onRequest(req, requestContext, wireAttrs);
}
Also used : CompositeWriter(com.linkedin.r2.message.stream.entitystream.CompositeWriter) PartialReader(com.linkedin.r2.filter.compression.streaming.PartialReader) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) CompressionOption(com.linkedin.r2.filter.CompressionOption) StreamingCompressor(com.linkedin.r2.filter.compression.streaming.StreamingCompressor) Map(java.util.Map) TreeMap(java.util.TreeMap)

Example 9 with StreamingCompressor

use of com.linkedin.r2.filter.compression.streaming.StreamingCompressor in project rest.li by linkedin.

the class ClientStreamCompressionFilter method onStreamError.

@Override
public void onStreamError(Throwable ex, RequestContext requestContext, Map<String, String> wireAttrs, NextFilter<StreamRequest, StreamResponse> nextFilter) {
    if (ex instanceof StreamException) {
        Boolean decompressionOff = (Boolean) requestContext.getLocalAttr(R2Constants.RESPONSE_DECOMPRESSION_OFF);
        if (decompressionOff == null || !decompressionOff) {
            StreamException se = (StreamException) ex;
            StreamResponse response = se.getResponse();
            //Check for header encoding
            String compressionHeader = response.getHeader(HttpConstants.CONTENT_ENCODING);
            //decompress if necessary
            if (compressionHeader != null) {
                StreamEncodingType encoding = StreamEncodingType.get(compressionHeader.trim().toLowerCase());
                if (encoding != null) {
                    final StreamingCompressor compressor = encoding.getCompressor(_executor);
                    EntityStream uncompressedStream = compressor.inflate(response.getEntityStream());
                    StreamResponseBuilder builder = response.builder();
                    Map<String, String> headers = stripHeaders(builder.getHeaders(), HttpConstants.CONTENT_ENCODING, HttpConstants.CONTENT_LENGTH);
                    response = builder.setHeaders(headers).build(uncompressedStream);
                    ex = new StreamException(response);
                }
            }
        }
    }
    nextFilter.onError(ex, requestContext, wireAttrs);
}
Also used : EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) StreamingCompressor(com.linkedin.r2.filter.compression.streaming.StreamingCompressor) StreamEncodingType(com.linkedin.r2.filter.compression.streaming.StreamEncodingType) StreamException(com.linkedin.r2.message.stream.StreamException)

Example 10 with StreamingCompressor

use of com.linkedin.r2.filter.compression.streaming.StreamingCompressor in project rest.li by linkedin.

the class ServerStreamCompressionFilter method onStreamResponse.

/**
   * Optionally compresses outgoing response
   * */
@Override
public void onStreamResponse(final StreamResponse res, final RequestContext requestContext, final Map<String, String> wireAttrs, final NextFilter<StreamRequest, StreamResponse> nextFilter) {
    StreamResponse response = res;
    try {
        String responseCompression = (String) requestContext.getLocalAttr(HttpConstants.ACCEPT_ENCODING);
        if (responseCompression == null) {
            throw new CompressionException(HttpConstants.ACCEPT_ENCODING + " not in local attribute.");
        }
        List<AcceptEncoding> parsedEncodings = AcceptEncoding.parseAcceptEncodingHeader(responseCompression, _supportedEncoding);
        StreamEncodingType selectedEncoding = AcceptEncoding.chooseBest(parsedEncodings);
        //Check if there exists an acceptable encoding
        if (selectedEncoding == null) {
            //Not acceptable encoding status
            response = new StreamResponseBuilder().setStatus(HttpConstants.NOT_ACCEPTABLE).build(EntityStreams.emptyStream());
        } else if (selectedEncoding != StreamEncodingType.IDENTITY) {
            final int threshold = (Integer) requestContext.getLocalAttr(HttpConstants.HEADER_RESPONSE_COMPRESSION_THRESHOLD);
            final StreamingCompressor compressor = selectedEncoding.getCompressor(_executor);
            PartialReader reader = new PartialReader(threshold, new Callback<EntityStream[]>() {

                @Override
                public void onError(Throwable ex) {
                    nextFilter.onError(ex, requestContext, wireAttrs);
                }

                @Override
                public void onSuccess(EntityStream[] results) {
                    if (// entity stream is less than threshold
                    results.length == 1) {
                        StreamResponse response = res.builder().build(results[0]);
                        nextFilter.onResponse(response, requestContext, wireAttrs);
                    } else {
                        EntityStream compressedStream = compressor.deflate(EntityStreams.newEntityStream(new CompositeWriter(results)));
                        StreamResponseBuilder builder = res.builder();
                        // remove original content-length header if presents.
                        if (builder.getHeader(HttpConstants.CONTENT_LENGTH) != null) {
                            Map<String, String> headers = stripHeaders(builder.getHeaders(), HttpConstants.CONTENT_LENGTH);
                            builder.setHeaders(headers);
                        }
                        StreamResponse response = builder.addHeaderValue(HttpConstants.CONTENT_ENCODING, compressor.getContentEncodingName()).build(compressedStream);
                        nextFilter.onResponse(response, requestContext, wireAttrs);
                    }
                }
            });
            res.getEntityStream().setReader(reader);
            return;
        }
    } catch (CompressionException e) {
        LOG.error(e.getMessage(), e.getCause());
    }
    nextFilter.onResponse(response, requestContext, wireAttrs);
}
Also used : StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) CompositeWriter(com.linkedin.r2.message.stream.entitystream.CompositeWriter) PartialReader(com.linkedin.r2.filter.compression.streaming.PartialReader) StreamEncodingType(com.linkedin.r2.filter.compression.streaming.StreamEncodingType) EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) Callback(com.linkedin.common.callback.Callback) StreamingCompressor(com.linkedin.r2.filter.compression.streaming.StreamingCompressor) AcceptEncoding(com.linkedin.r2.filter.compression.streaming.AcceptEncoding)

Aggregations

StreamingCompressor (com.linkedin.r2.filter.compression.streaming.StreamingCompressor)13 EntityStream (com.linkedin.r2.message.stream.entitystream.EntityStream)12 ByteArrayOutputStream (java.io.ByteArrayOutputStream)8 Test (org.testng.annotations.Test)8 FutureCallback (com.linkedin.common.callback.FutureCallback)7 StreamEncodingType (com.linkedin.r2.filter.compression.streaming.StreamEncodingType)4 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)4 StreamResponseBuilder (com.linkedin.r2.message.stream.StreamResponseBuilder)4 Bzip2Compressor (com.linkedin.r2.filter.compression.streaming.Bzip2Compressor)2 DeflateCompressor (com.linkedin.r2.filter.compression.streaming.DeflateCompressor)2 GzipCompressor (com.linkedin.r2.filter.compression.streaming.GzipCompressor)2 PartialReader (com.linkedin.r2.filter.compression.streaming.PartialReader)2 SnappyCompressor (com.linkedin.r2.filter.compression.streaming.SnappyCompressor)2 StreamException (com.linkedin.r2.message.stream.StreamException)2 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)2 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)2 CompositeWriter (com.linkedin.r2.message.stream.entitystream.CompositeWriter)2 DeflaterOutputStream (java.util.zip.DeflaterOutputStream)2 GZIPOutputStream (java.util.zip.GZIPOutputStream)2 BZip2CompressorOutputStream (org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream)2