Search in sources :

Example 6 with LastHttpContent

use of io.netty.handler.codec.http.LastHttpContent in project netty by netty.

the class Http2ServerDowngraderTest method testDowngradeTrailers.

@Test
public void testDowngradeTrailers() throws Exception {
    EmbeddedChannel ch = new EmbeddedChannel(new Http2ServerDowngrader());
    Http2Headers headers = new DefaultHttp2Headers();
    headers.set("key", "value");
    assertTrue(ch.writeInbound(new DefaultHttp2HeadersFrame(headers, true)));
    LastHttpContent trailers = ch.readInbound();
    try {
        assertThat(trailers.content().readableBytes(), is(0));
        assertThat(trailers.trailingHeaders().get("key").toString(), is("value"));
        assertFalse(trailers instanceof FullHttpRequest);
    } finally {
        trailers.release();
    }
    assertThat(ch.readInbound(), is(nullValue()));
    assertFalse(ch.finish());
}
Also used : FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) EmbeddedChannel(io.netty.channel.embedded.EmbeddedChannel) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) Test(org.junit.Test)

Example 7 with LastHttpContent

use of io.netty.handler.codec.http.LastHttpContent in project riposte by Nike-Inc.

the class ResponseSender method synchronizeAndSetupResponseInfoAndFirstChunk.

protected void synchronizeAndSetupResponseInfoAndFirstChunk(ResponseInfo<?> responseInfo, HttpResponse actualResponseObject, RequestInfo requestInfo, ChannelHandlerContext ctx) {
    // Set the content type header.
    //      NOTE: This is ok even if the response doesn't have a body - in the case of chunked messages we don't
    //            know whether body content will be coming later or not so we have to be proactive here in case
    //            there *is* body content later.
    //      ALSO NOTE: The responseInfo may have already had a Content-Type header specified (e.g. reverse proxied
    //            response), but the way we build the header this will be ok. If responseInfo wanted to override it
    //            we allow that, and if not then the Content-Type in the headers will be honored, and if both of
    //            those are unspecified then the default mime type and charset are used.
    responseInfo.getHeaders().set(CONTENT_TYPE, buildContentTypeHeader(responseInfo));
    // Set the HTTP status code on the ResponseInfo object from the actualResponseObject if necessary.
    if (responseInfo.getHttpStatusCode() == null)
        responseInfo.setHttpStatusCode(actualResponseObject.getStatus().code());
    // Make sure a trace ID is in the headers.
    if (!responseInfo.getHeaders().contains(TraceHeaders.TRACE_ID)) {
        // All responses must contain a trace ID. Try to get it from the request
        //      since it wasn't already in the response.
        String traceId = extractDistributedTraceId(requestInfo, ctx);
        if (traceId == null) {
            // Couldn't find a valid trace ID anywhere, so just create a dummy one, and log what happened so if
            //      someone searches for that ID they'll find something explaining what happened.
            traceId = TraceAndSpanIdGenerator.generateId();
            String warningMsg = "Generating a dummy Trace ID for response header because a real Trace ID did not exist. This " + "probably happened because the request was not processed by the channel pipeline. dummy_trace_id=" + traceId;
            runnableWithTracingAndMdc(() -> logger.warn(warningMsg), ctx).run();
        }
        responseInfo.getHeaders().set(TraceHeaders.TRACE_ID, traceId);
    }
    // Handle any keep-alive stuff
    if (responseInfo.isForceConnectionCloseAfterResponseSent()) {
        // We'll be closing the connection after this response is sent, so send the appropriate Connection header.
        responseInfo.getHeaders().set(CONNECTION, HttpHeaders.Values.CLOSE);
    } else if (requestInfo.isKeepAliveRequested()) {
        //      what the content length will be.
        if (actualResponseObject instanceof LastHttpContent) {
            responseInfo.getHeaders().set(CONTENT_LENGTH, ((LastHttpContent) actualResponseObject).content().readableBytes());
        } else {
            //      If we have one of those responses, we mark it with content-length 0
            if (isContentAlwaysEmpty(responseInfo)) {
                responseInfo.getHeaders().remove(TRANSFER_ENCODING);
                responseInfo.getHeaders().set(CONTENT_LENGTH, 0);
            } else {
                // Not a must-be-empty-payload status code. For these there might be a payload and we can't know the
                //      content length since it's being sent to us in chunks, so we have to set the
                //      Transfer-Encoding header to chunked in order for the response sending to be successful
                //      (otherwise the receiving client would just hang waiting for the connection to be closed).
                // See http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6
                // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1 for the technical explanation.
                // See http://en.wikipedia.org/wiki/Chunked_transfer_encoding for a more straightforward explanation
                responseInfo.getHeaders().remove(CONTENT_LENGTH);
                responseInfo.getHeaders().set(TRANSFER_ENCODING, CHUNKED);
            }
        }
        // Add keep alive header as per
        //      http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01.html#Connection
        responseInfo.getHeaders().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
    }
    // Synchronize the ResponseInfo headers with the actualResponseObject
    //      (copy from responseInfo into actualResponseObject)
    actualResponseObject.headers().add(responseInfo.getHeaders());
    // Add cookies (if any)
    if (responseInfo.getCookies() != null) {
        for (Cookie cookie : responseInfo.getCookies()) {
            actualResponseObject.headers().add(HttpHeaders.Names.SET_COOKIE, ServerCookieEncoder.LAX.encode(cookie.name(), cookie.value()));
        }
    }
}
Also used : Cookie(io.netty.handler.codec.http.cookie.Cookie) LastHttpContent(io.netty.handler.codec.http.LastHttpContent)

Example 8 with LastHttpContent

use of io.netty.handler.codec.http.LastHttpContent in project jersey by jersey.

the class JerseyServerHandler method channelRead.

@Override
public void channelRead(final ChannelHandlerContext ctx, Object msg) {
    if (msg instanceof HttpRequest) {
        final HttpRequest req = (HttpRequest) msg;
        if (HttpUtil.is100ContinueExpected(req)) {
            ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE));
        }
        // clearing the content - possible leftover from previous request processing.
        isList.clear();
        final ContainerRequest requestContext = createContainerRequest(ctx, req);
        requestContext.setWriter(new NettyResponseWriter(ctx, req, container));
        // must be like this, since there is a blocking read from Jersey
        container.getExecutorService().execute(new Runnable() {

            @Override
            public void run() {
                container.getApplicationHandler().handle(requestContext);
            }
        });
    }
    if (msg instanceof HttpContent) {
        HttpContent httpContent = (HttpContent) msg;
        ByteBuf content = httpContent.content();
        if (content.isReadable()) {
            isList.add(new ByteBufInputStream(content));
        }
        if (msg instanceof LastHttpContent) {
            isList.add(NettyInputStream.END_OF_INPUT);
        }
    }
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) ContainerRequest(org.glassfish.jersey.server.ContainerRequest) ByteBufInputStream(io.netty.buffer.ByteBufInputStream) ByteBuf(io.netty.buffer.ByteBuf) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent)

Example 9 with LastHttpContent

use of io.netty.handler.codec.http.LastHttpContent in project netty by netty.

the class Http2ServerDowngrader method decode.

@Override
protected void decode(ChannelHandlerContext ctx, Http2StreamFrame frame, List<Object> out) throws Exception {
    if (frame instanceof Http2HeadersFrame) {
        // not really the id
        int id = 0;
        Http2HeadersFrame headersFrame = (Http2HeadersFrame) frame;
        Http2Headers headers = headersFrame.headers();
        if (headersFrame.isEndStream()) {
            if (headers.method() == null) {
                LastHttpContent last = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders);
                HttpConversionUtil.addHttp2ToHttpHeaders(id, headers, last.trailingHeaders(), HttpVersion.HTTP_1_1, true, true);
                out.add(last);
            } else {
                FullHttpRequest full = HttpConversionUtil.toFullHttpRequest(id, headers, ctx.alloc(), validateHeaders);
                out.add(full);
            }
        } else {
            HttpRequest req = HttpConversionUtil.toHttpRequest(id, headersFrame.headers(), validateHeaders);
            if (!HttpUtil.isContentLengthSet(req)) {
                req.headers().add(HttpHeaderNames.TRANSFER_ENCODING, HttpHeaderValues.CHUNKED);
            }
            out.add(req);
        }
    } else if (frame instanceof Http2DataFrame) {
        Http2DataFrame dataFrame = (Http2DataFrame) frame;
        if (dataFrame.isEndStream()) {
            out.add(new DefaultLastHttpContent(dataFrame.content(), validateHeaders));
        } else {
            out.add(new DefaultHttpContent(dataFrame.content()));
        }
    }
    ReferenceCountUtil.retain(frame);
}
Also used : HttpRequest(io.netty.handler.codec.http.HttpRequest) FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) FullHttpRequest(io.netty.handler.codec.http.FullHttpRequest) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent) DefaultHttpContent(io.netty.handler.codec.http.DefaultHttpContent) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) DefaultLastHttpContent(io.netty.handler.codec.http.DefaultLastHttpContent)

Example 10 with LastHttpContent

use of io.netty.handler.codec.http.LastHttpContent in project rest.li by linkedin.

the class RAPResponseDecoder method channelRead0.

@Override
protected void channelRead0(final ChannelHandlerContext ctx, HttpObject msg) throws Exception {
    if (msg instanceof HttpResponse) {
        HttpResponse m = (HttpResponse) msg;
        _shouldCloseConnection = !HttpUtil.isKeepAlive(m);
        if (HttpUtil.is100ContinueExpected(m)) {
            ctx.writeAndFlush(CONTINUE).addListener(new ChannelFutureListener() {

                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    if (!future.isSuccess()) {
                        ctx.fireExceptionCaught(future.cause());
                    }
                }
            });
        }
        if (!m.decoderResult().isSuccess()) {
            ctx.fireExceptionCaught(m.decoderResult().cause());
            return;
        }
        // remove chunked encoding.
        if (HttpUtil.isTransferEncodingChunked(m)) {
            HttpUtil.setTransferEncodingChunked(m, false);
        }
        Timeout<None> timeout = ctx.channel().attr(TIMEOUT_ATTR_KEY).getAndRemove();
        if (timeout == null) {
            LOG.debug("dropped a response after channel inactive or exception had happened.");
            return;
        }
        final TimeoutBufferedWriter writer = new TimeoutBufferedWriter(ctx, _maxContentLength, BUFFER_HIGH_WATER_MARK, BUFFER_LOW_WATER_MARK, timeout);
        EntityStream entityStream = EntityStreams.newEntityStream(writer);
        _chunkedMessageWriter = writer;
        StreamResponseBuilder builder = new StreamResponseBuilder();
        builder.setStatus(m.status().code());
        for (Map.Entry<String, String> e : m.headers()) {
            String key = e.getKey();
            String value = e.getValue();
            if (key.equalsIgnoreCase(HttpConstants.RESPONSE_COOKIE_HEADER_NAME)) {
                builder.addCookie(value);
            } else {
                builder.unsafeAddHeaderValue(key, value);
            }
        }
        ctx.fireChannelRead(builder.build(entityStream));
    } else if (msg instanceof HttpContent) {
        HttpContent chunk = (HttpContent) msg;
        TimeoutBufferedWriter currentWriter = _chunkedMessageWriter;
        // Sanity check
        if (currentWriter == null) {
            throw new IllegalStateException("received " + HttpContent.class.getSimpleName() + " without " + HttpResponse.class.getSimpleName());
        }
        if (!chunk.decoderResult().isSuccess()) {
            this.exceptionCaught(ctx, chunk.decoderResult().cause());
        }
        currentWriter.processHttpChunk(chunk);
        if (chunk instanceof LastHttpContent) {
            _chunkedMessageWriter = null;
        }
    } else {
        // something must be wrong, but let's proceed so that
        // handler after us has a chance to process it.
        ctx.fireChannelRead(msg);
    }
}
Also used : ChannelFuture(io.netty.channel.ChannelFuture) StreamResponseBuilder(com.linkedin.r2.message.stream.StreamResponseBuilder) FullHttpResponse(io.netty.handler.codec.http.FullHttpResponse) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) HttpResponse(io.netty.handler.codec.http.HttpResponse) ByteString(com.linkedin.data.ByteString) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) ChannelFutureListener(io.netty.channel.ChannelFutureListener) TimeoutException(java.util.concurrent.TimeoutException) ClosedChannelException(java.nio.channels.ClosedChannelException) RemoteInvocationException(com.linkedin.r2.RemoteInvocationException) TooLongFrameException(io.netty.handler.codec.TooLongFrameException) IOException(java.io.IOException) EntityStream(com.linkedin.r2.message.stream.entitystream.EntityStream) None(com.linkedin.common.util.None) Map(java.util.Map) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) HttpContent(io.netty.handler.codec.http.HttpContent)

Aggregations

LastHttpContent (io.netty.handler.codec.http.LastHttpContent)122 DefaultLastHttpContent (io.netty.handler.codec.http.DefaultLastHttpContent)56 HttpContent (io.netty.handler.codec.http.HttpContent)52 ByteBuf (io.netty.buffer.ByteBuf)40 EmbeddedChannel (io.netty.channel.embedded.EmbeddedChannel)38 HttpResponse (io.netty.handler.codec.http.HttpResponse)38 HttpRequest (io.netty.handler.codec.http.HttpRequest)31 Test (org.junit.Test)27 DefaultHttpContent (io.netty.handler.codec.http.DefaultHttpContent)21 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)19 Test (org.junit.jupiter.api.Test)19 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)17 DefaultFullHttpResponse (io.netty.handler.codec.http.DefaultFullHttpResponse)13 HttpObject (io.netty.handler.codec.http.HttpObject)10 HttpProcessingState (com.nike.riposte.server.http.HttpProcessingState)9 ChannelFuture (io.netty.channel.ChannelFuture)9 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)9 DefaultHttpHeaders (io.netty.handler.codec.http.DefaultHttpHeaders)9 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)9 IOException (java.io.IOException)9