Search in sources :

Example 1 with ACCEPT_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING in project servicetalk by apple.

the class ContentEncodingHttpServiceFilter method create.

@Override
public StreamingHttpServiceFilter create(final StreamingHttpService service) {
    return new StreamingHttpServiceFilter(service) {

        @Override
        public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
            return Single.defer(() -> {
                final StreamingHttpRequest requestDecompressed;
                Iterator<? extends CharSequence> contentEncodingItr = request.headers().valuesIterator(CONTENT_ENCODING);
                final boolean hasContentEncoding = contentEncodingItr.hasNext();
                if (hasContentEncoding) {
                    BufferDecoder decoder = matchAndRemoveEncoding(decompressors.decoders(), BufferDecoder::encodingName, contentEncodingItr, request.headers());
                    if (decoder == null) {
                        return succeeded(responseFactory.unsupportedMediaType()).shareContextOnSubscribe();
                    }
                    requestDecompressed = request.transformPayloadBody(pub -> decoder.streamingDecoder().deserialize(pub, ctx.executionContext().bufferAllocator()));
                } else {
                    requestDecompressed = request;
                }
                return super.handle(ctx, requestDecompressed, responseFactory).map(response -> {
                    final CharSequence reqAcceptEncoding;
                    if (isPassThrough(request.method(), response) || (reqAcceptEncoding = request.headers().get(ACCEPT_ENCODING)) == null) {
                        return response;
                    }
                    BufferEncoder encoder = negotiateAcceptedEncodingRaw(reqAcceptEncoding, compressors, BufferEncoder::encodingName);
                    if (encoder == null || identityEncoder().equals(encoder)) {
                        return response;
                    }
                    addContentEncoding(response.headers(), encoder.encodingName());
                    return response.transformPayloadBody(bufPub -> encoder.streamingEncoder().serialize(bufPub, ctx.executionContext().bufferAllocator()));
                }).shareContextOnSubscribe();
            });
        }
    };
}
Also used : EmptyBufferDecoderGroup(io.servicetalk.encoding.api.EmptyBufferDecoderGroup) Function(java.util.function.Function) ArrayList(java.util.ArrayList) CharSequences.regionMatches(io.servicetalk.buffer.api.CharSequences.regionMatches) HEAD(io.servicetalk.http.api.HttpRequestMethod.HEAD) Single.succeeded(io.servicetalk.concurrent.api.Single.succeeded) INFORMATIONAL_1XX(io.servicetalk.http.api.HttpResponseStatus.StatusClass.INFORMATIONAL_1XX) Objects.requireNonNull(java.util.Objects.requireNonNull) BufferDecoderGroup(io.servicetalk.encoding.api.BufferDecoderGroup) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) Nullable(javax.annotation.Nullable) Iterator(java.util.Iterator) HeaderUtils.addContentEncoding(io.servicetalk.http.api.HeaderUtils.addContentEncoding) Single(io.servicetalk.concurrent.api.Single) NO_CONTENT(io.servicetalk.http.api.HttpResponseStatus.NO_CONTENT) CONNECT(io.servicetalk.http.api.HttpRequestMethod.CONNECT) HeaderUtils.negotiateAcceptedEncodingRaw(io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw) Identity.identityEncoder(io.servicetalk.encoding.api.Identity.identityEncoder) CharSequences(io.servicetalk.buffer.api.CharSequences) SUCCESSFUL_2XX(io.servicetalk.http.api.HttpResponseStatus.StatusClass.SUCCESSFUL_2XX) ACCEPT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING) List(java.util.List) NOT_MODIFIED(io.servicetalk.http.api.HttpResponseStatus.NOT_MODIFIED) BufferDecoder(io.servicetalk.encoding.api.BufferDecoder) CONTENT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) BufferDecoder(io.servicetalk.encoding.api.BufferDecoder)

Example 2 with ACCEPT_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING in project servicetalk by apple.

the class ContentEncodingHttpRequesterFilter method applyEncodingAndDecoding.

private Single<StreamingHttpResponse> applyEncodingAndDecoding(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
    return Single.defer(() -> {
        boolean decompressResponse = false;
        CharSequence encodings = decompressors.advertisedMessageEncoding();
        if (encodings != null && !request.headers().contains(ACCEPT_ENCODING)) {
            request.headers().set(ACCEPT_ENCODING, encodings);
            decompressResponse = true;
        }
        BufferEncoder encoder = request.contentEncoding();
        final StreamingHttpRequest encodedRequest;
        if (encoder != null && !identityEncoder().equals(encoder)) {
            addContentEncoding(request.headers(), encoder.encodingName());
            encodedRequest = request.transformPayloadBody(pub -> encoder.streamingEncoder().serialize(pub, delegate.executionContext().bufferAllocator()));
        } else {
            encodedRequest = request;
        }
        Single<StreamingHttpResponse> respSingle = delegate.request(encodedRequest);
        return (decompressResponse ? respSingle.map(response -> {
            Iterator<? extends CharSequence> contentEncodingItr = response.headers().valuesIterator(CONTENT_ENCODING);
            final boolean hasContentEncoding = contentEncodingItr.hasNext();
            if (!hasContentEncoding) {
                return response;
            }
            BufferDecoder decoder = matchAndRemoveEncoding(decompressors.decoders(), BufferDecoder::encodingName, contentEncodingItr, response.headers());
            if (decoder == null) {
                throw new UnsupportedContentEncodingException(response.headers().get(CONTENT_ENCODING, "<null>").toString());
            }
            return response.transformPayloadBody(pub -> decoder.streamingDecoder().deserialize(pub, delegate.executionContext().bufferAllocator()));
        }) : respSingle).shareContextOnSubscribe();
    });
}
Also used : ACCEPT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING) Iterator(java.util.Iterator) HeaderUtils.addContentEncoding(io.servicetalk.http.api.HeaderUtils.addContentEncoding) Single(io.servicetalk.concurrent.api.Single) Objects.requireNonNull(java.util.Objects.requireNonNull) BufferDecoderGroup(io.servicetalk.encoding.api.BufferDecoderGroup) ContentEncodingHttpServiceFilter.matchAndRemoveEncoding(io.servicetalk.http.api.ContentEncodingHttpServiceFilter.matchAndRemoveEncoding) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) Identity.identityEncoder(io.servicetalk.encoding.api.Identity.identityEncoder) BufferDecoder(io.servicetalk.encoding.api.BufferDecoder) CONTENT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) Iterator(java.util.Iterator) BufferDecoder(io.servicetalk.encoding.api.BufferDecoder)

Example 3 with ACCEPT_ENCODING

use of io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING in project servicetalk by apple.

the class ServiceTalkContentEncodingTest method runTest.

@Override
protected void runTest(final HttpProtocol protocol, final Encoder clientEncoding, final Decoders clientDecoder, final Encoders serverEncoder, final Decoders serverDecoder, boolean valid) throws Throwable {
    try (ServerContext serverContext = HttpServers.forAddress(localAddress(0)).protocols(protocol.config).appendServiceFilter(service -> new StreamingHttpServiceFilter(service) {

        @Override
        public Single<StreamingHttpResponse> handle(final HttpServiceContext ctx, final StreamingHttpRequest request, final StreamingHttpResponseFactory responseFactory) {
            return delegate().handle(ctx, request, responseFactory).map(resp -> {
                // content encoding should be stripped by the time the decoding is done.
                assertThat(resp.headers().get(ACCEPT_ENCODING), nullValue());
                CharSequence contentEncoding = resp.headers().get(CONTENT_ENCODING);
                boolean found = contentEncoding == null && (serverEncoder.list.isEmpty() || !request.headers().contains(ACCEPT_ENCODING));
                for (BufferEncoder be : serverEncoder.list) {
                    if (contentEncoding == null && contentEqualsIgnoreCase(be.encodingName(), identityEncoder().encodingName()) || contentEncoding != null && contentEqualsIgnoreCase(be.encodingName(), contentEncoding)) {
                        found = true;
                        break;
                    }
                }
                return found || !valid ? resp : responseFactory.ok().payloadBody(Publisher.from("server error: invalid " + CONTENT_ENCODING + ": " + contentEncoding), appSerializerUtf8FixLen());
            }).onErrorReturn(AssertionError.class, cause -> responseFactory.ok().payloadBody(Publisher.from("server error: " + cause.toString()), appSerializerUtf8FixLen()));
        }
    }).appendServiceFilter(new ContentEncodingHttpServiceFilter(serverEncoder.list, serverDecoder.group)).listenBlockingAndAwait((ctx, request, responseFactory) -> {
        String requestPayload = request.payloadBody(textSerializerUtf8());
        if (payloadAsString((byte) 'a').equals(requestPayload)) {
            return responseFactory.ok().payloadBody(payloadAsString((byte) 'b'), textSerializerUtf8());
        } else {
            return responseFactory.badRequest().payloadBody(requestPayload, textSerializerUtf8());
        }
    });
        BlockingHttpClient client = HttpClients.forSingleAddress(serverHostAndPort(serverContext)).protocols(protocol.config).appendClientFilter(new ContentEncodingHttpRequesterFilter(clientDecoder.group)).appendClientFilter(c -> new StreamingHttpClientFilter(c) {

            @Override
            protected Single<StreamingHttpResponse> request(final StreamingHttpRequester delegate, final StreamingHttpRequest request) {
                return Single.defer(() -> {
                    assertHeader(() -> clientEncoding.encoder == null ? null : clientEncoding.encoder.encodingName(), request.headers().get(CONTENT_ENCODING), true);
                    assertHeader(clientDecoder.group::advertisedMessageEncoding, request.headers().get(ACCEPT_ENCODING), false);
                    return delegate.request(request).shareContextOnSubscribe();
                });
            }
        }).buildBlocking()) {
        HttpResponse response = client.request(client.get("/").contentEncoding(clientEncoding.encoder).payloadBody(payloadAsString((byte) 'a'), textSerializerUtf8()));
        if (valid) {
            assertThat(response.status(), is(OK));
            // content encoding should be stripped by the time the decoding is done.
            assertThat(response.headers().get(CONTENT_ENCODING), nullValue());
            assertEquals(payloadAsString((byte) 'b'), response.payloadBody(textSerializerUtf8()));
        } else {
            assertThat(response.status(), is(UNSUPPORTED_MEDIA_TYPE));
        }
    }
}
Also used : StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) Publisher(io.servicetalk.concurrent.api.Publisher) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) Supplier(java.util.function.Supplier) UNSUPPORTED_MEDIA_TYPE(io.servicetalk.http.api.HttpResponseStatus.UNSUPPORTED_MEDIA_TYPE) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) IsNull.nullValue(org.hamcrest.core.IsNull.nullValue) HttpSerializers.appSerializerUtf8FixLen(io.servicetalk.http.api.HttpSerializers.appSerializerUtf8FixLen) HttpSerializers.textSerializerUtf8(io.servicetalk.http.api.HttpSerializers.textSerializerUtf8) ContentEncodingHttpRequesterFilter(io.servicetalk.http.api.ContentEncodingHttpRequesterFilter) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) AddressUtils.serverHostAndPort(io.servicetalk.transport.netty.internal.AddressUtils.serverHostAndPort) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) MatcherAssert.assertThat(org.hamcrest.MatcherAssert.assertThat) Assertions.assertEquals(org.junit.jupiter.api.Assertions.assertEquals) Nullable(javax.annotation.Nullable) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) AddressUtils.localAddress(io.servicetalk.transport.netty.internal.AddressUtils.localAddress) ServerContext(io.servicetalk.transport.api.ServerContext) Single(io.servicetalk.concurrent.api.Single) HttpResponse(io.servicetalk.http.api.HttpResponse) Identity.identityEncoder(io.servicetalk.encoding.api.Identity.identityEncoder) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) OK(io.servicetalk.http.api.HttpResponseStatus.OK) CharSequences.contentEqualsIgnoreCase(io.servicetalk.buffer.api.CharSequences.contentEqualsIgnoreCase) ACCEPT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING) ContentEncodingHttpServiceFilter(io.servicetalk.http.api.ContentEncodingHttpServiceFilter) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) Matchers.is(org.hamcrest.Matchers.is) CONTENT_ENCODING(io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING) StreamingHttpRequester(io.servicetalk.http.api.StreamingHttpRequester) BlockingHttpClient(io.servicetalk.http.api.BlockingHttpClient) ContentEncodingHttpRequesterFilter(io.servicetalk.http.api.ContentEncodingHttpRequesterFilter) StreamingHttpResponseFactory(io.servicetalk.http.api.StreamingHttpResponseFactory) ContentEncodingHttpServiceFilter(io.servicetalk.http.api.ContentEncodingHttpServiceFilter) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse) HttpResponse(io.servicetalk.http.api.HttpResponse) StreamingHttpClientFilter(io.servicetalk.http.api.StreamingHttpClientFilter) StreamingHttpServiceFilter(io.servicetalk.http.api.StreamingHttpServiceFilter) ServerContext(io.servicetalk.transport.api.ServerContext) Single(io.servicetalk.concurrent.api.Single) HttpServiceContext(io.servicetalk.http.api.HttpServiceContext) BufferEncoder(io.servicetalk.encoding.api.BufferEncoder) StreamingHttpRequest(io.servicetalk.http.api.StreamingHttpRequest) StreamingHttpResponse(io.servicetalk.http.api.StreamingHttpResponse)

Aggregations

Single (io.servicetalk.concurrent.api.Single)3 BufferEncoder (io.servicetalk.encoding.api.BufferEncoder)3 Identity.identityEncoder (io.servicetalk.encoding.api.Identity.identityEncoder)3 ACCEPT_ENCODING (io.servicetalk.http.api.HttpHeaderNames.ACCEPT_ENCODING)3 CONTENT_ENCODING (io.servicetalk.http.api.HttpHeaderNames.CONTENT_ENCODING)3 BufferDecoder (io.servicetalk.encoding.api.BufferDecoder)2 BufferDecoderGroup (io.servicetalk.encoding.api.BufferDecoderGroup)2 HeaderUtils.addContentEncoding (io.servicetalk.http.api.HeaderUtils.addContentEncoding)2 Iterator (java.util.Iterator)2 Objects.requireNonNull (java.util.Objects.requireNonNull)2 Nullable (javax.annotation.Nullable)2 CharSequences (io.servicetalk.buffer.api.CharSequences)1 CharSequences.contentEqualsIgnoreCase (io.servicetalk.buffer.api.CharSequences.contentEqualsIgnoreCase)1 CharSequences.regionMatches (io.servicetalk.buffer.api.CharSequences.regionMatches)1 Publisher (io.servicetalk.concurrent.api.Publisher)1 Single.succeeded (io.servicetalk.concurrent.api.Single.succeeded)1 EmptyBufferDecoderGroup (io.servicetalk.encoding.api.EmptyBufferDecoderGroup)1 HeaderUtils.negotiateAcceptedEncodingRaw (io.servicetalk.encoding.api.internal.HeaderUtils.negotiateAcceptedEncodingRaw)1 BlockingHttpClient (io.servicetalk.http.api.BlockingHttpClient)1 ContentEncodingHttpRequesterFilter (io.servicetalk.http.api.ContentEncodingHttpRequesterFilter)1