Search in sources :

Example 16 with FullHttpMessage

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

the class InboundHttp2ToHttpAdapterTest method serverResponseHeaderInformational.

@Test
public void serverResponseHeaderInformational() throws Exception {
    boostrapEnv(1, 2, 1, 2, 1);
    final FullHttpMessage request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.PUT, "/info/test", true);
    HttpHeaders httpHeaders = request.headers();
    httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
    httpHeaders.set(HttpHeaderNames.EXPECT, HttpHeaderValues.CONTINUE);
    httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
    httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
    final Http2Headers http2Headers = new DefaultHttp2Headers().method(new AsciiString("PUT")).path(new AsciiString("/info/test")).set(new AsciiString(HttpHeaderNames.EXPECT.toString()), new AsciiString(HttpHeaderValues.CONTINUE.toString()));
    final FullHttpMessage response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE);
    final String text = "a big payload";
    final ByteBuf payload = Unpooled.copiedBuffer(text.getBytes());
    final FullHttpMessage request2 = request.replace(payload);
    final FullHttpMessage response2 = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
    try {
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                clientHandler.encoder().writeHeaders(ctxClient(), 3, http2Headers, 0, false, newPromiseClient());
                clientChannel.flush();
            }
        });
        awaitRequests();
        httpHeaders = response.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
        final Http2Headers http2HeadersResponse = new DefaultHttp2Headers().status(new AsciiString("100"));
        runInChannel(serverConnectedChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse, 0, false, newPromiseServer());
                serverConnectedChannel.flush();
            }
        });
        awaitResponses();
        httpHeaders = request2.headers();
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, text.length());
        httpHeaders.remove(HttpHeaderNames.EXPECT);
        runInChannel(clientChannel, new Http2Runnable() {

            @Override
            public void run() {
                clientHandler.encoder().writeData(ctxClient(), 3, payload.retainedDuplicate(), 0, true, newPromiseClient());
                clientChannel.flush();
            }
        });
        awaitRequests2();
        httpHeaders = response2.headers();
        httpHeaders.setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_ID.text(), 3);
        httpHeaders.setInt(HttpHeaderNames.CONTENT_LENGTH, 0);
        httpHeaders.setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), (short) 16);
        final Http2Headers http2HeadersResponse2 = new DefaultHttp2Headers().status(new AsciiString("200"));
        runInChannel(serverConnectedChannel, new Http2Runnable() {

            @Override
            public void run() throws Http2Exception {
                serverHandler.encoder().writeHeaders(ctxServer(), 3, http2HeadersResponse2, 0, true, newPromiseServer());
                serverConnectedChannel.flush();
            }
        });
        awaitResponses2();
        ArgumentCaptor<FullHttpMessage> requestCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(serverListener, times(2)).messageReceived(requestCaptor.capture());
        capturedRequests = requestCaptor.getAllValues();
        assertEquals(2, capturedRequests.size());
        assertEquals(request, capturedRequests.get(0));
        assertEquals(request2, capturedRequests.get(1));
        ArgumentCaptor<FullHttpMessage> responseCaptor = ArgumentCaptor.forClass(FullHttpMessage.class);
        verify(clientListener, times(2)).messageReceived(responseCaptor.capture());
        capturedResponses = responseCaptor.getAllValues();
        assertEquals(2, capturedResponses.size());
        assertEquals(response, capturedResponses.get(0));
        assertEquals(response2, capturedResponses.get(1));
    } finally {
        request.release();
        request2.release();
        response.release();
        response2.release();
    }
}
Also used : HttpHeaders(io.netty.handler.codec.http.HttpHeaders) DefaultFullHttpResponse(io.netty.handler.codec.http.DefaultFullHttpResponse) Http2CodecUtil.getEmbeddedHttp2Exception(io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception) DefaultFullHttpRequest(io.netty.handler.codec.http.DefaultFullHttpRequest) Http2Runnable(io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable) FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage) AsciiString(io.netty.util.AsciiString) AsciiString(io.netty.util.AsciiString) ByteBuf(io.netty.buffer.ByteBuf) Test(org.junit.Test)

Example 17 with FullHttpMessage

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

the class HttpToHttp2ConnectionHandler method write.

/**
     * Handles conversion of {@link HttpMessage} and {@link HttpContent} to HTTP/2 frames.
     */
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) {
    if (!(msg instanceof HttpMessage || msg instanceof HttpContent)) {
        ctx.write(msg, promise);
        return;
    }
    boolean release = true;
    SimpleChannelPromiseAggregator promiseAggregator = new SimpleChannelPromiseAggregator(promise, ctx.channel(), ctx.executor());
    try {
        Http2ConnectionEncoder encoder = encoder();
        boolean endStream = false;
        if (msg instanceof HttpMessage) {
            final HttpMessage httpMsg = (HttpMessage) msg;
            // Provide the user the opportunity to specify the streamId
            currentStreamId = getStreamId(httpMsg.headers());
            // Convert and write the headers.
            Http2Headers http2Headers = HttpConversionUtil.toHttp2Headers(httpMsg, validateHeaders);
            endStream = msg instanceof FullHttpMessage && !((FullHttpMessage) msg).content().isReadable();
            writeHeaders(ctx, encoder, currentStreamId, httpMsg.headers(), http2Headers, endStream, promiseAggregator);
        }
        if (!endStream && msg instanceof HttpContent) {
            boolean isLastContent = false;
            HttpHeaders trailers = EmptyHttpHeaders.INSTANCE;
            Http2Headers http2Trailers = EmptyHttp2Headers.INSTANCE;
            if (msg instanceof LastHttpContent) {
                isLastContent = true;
                // Convert any trailing headers.
                final LastHttpContent lastContent = (LastHttpContent) msg;
                trailers = lastContent.trailingHeaders();
                http2Trailers = HttpConversionUtil.toHttp2Headers(trailers, validateHeaders);
            }
            // Write the data
            final ByteBuf content = ((HttpContent) msg).content();
            endStream = isLastContent && trailers.isEmpty();
            release = false;
            encoder.writeData(ctx, currentStreamId, content, 0, endStream, promiseAggregator.newPromise());
            if (!trailers.isEmpty()) {
                // Write trailing headers.
                writeHeaders(ctx, encoder, currentStreamId, trailers, http2Trailers, true, promiseAggregator);
            }
        }
    } catch (Throwable t) {
        onError(ctx, t);
        promiseAggregator.setFailure(t);
    } finally {
        if (release) {
            ReferenceCountUtil.release(msg);
        }
        promiseAggregator.doneAllocatingPromises();
    }
}
Also used : EmptyHttpHeaders(io.netty.handler.codec.http.EmptyHttpHeaders) HttpHeaders(io.netty.handler.codec.http.HttpHeaders) FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage) SimpleChannelPromiseAggregator(io.netty.handler.codec.http2.Http2CodecUtil.SimpleChannelPromiseAggregator) FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage) HttpMessage(io.netty.handler.codec.http.HttpMessage) LastHttpContent(io.netty.handler.codec.http.LastHttpContent) ByteBuf(io.netty.buffer.ByteBuf) HttpContent(io.netty.handler.codec.http.HttpContent) LastHttpContent(io.netty.handler.codec.http.LastHttpContent)

Example 18 with FullHttpMessage

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

the class InboundHttp2ToHttpAdapter method onHeadersRead.

@Override
public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Headers headers, int streamDependency, short weight, boolean exclusive, int padding, boolean endOfStream) throws Http2Exception {
    Http2Stream stream = connection.stream(streamId);
    FullHttpMessage msg = processHeadersBegin(ctx, stream, headers, endOfStream, true, true);
    if (msg != null) {
        // See https://github.com/netty/netty/issues/5866
        if (streamDependency != Http2CodecUtil.CONNECTION_STREAM_ID) {
            msg.headers().setInt(HttpConversionUtil.ExtensionHeaderNames.STREAM_DEPENDENCY_ID.text(), streamDependency);
        }
        msg.headers().setShort(HttpConversionUtil.ExtensionHeaderNames.STREAM_WEIGHT.text(), weight);
        processHeadersEnd(ctx, stream, msg, endOfStream);
    }
}
Also used : FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage)

Example 19 with FullHttpMessage

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

the class InboundHttp2ToHttpAdapter method processHeadersBegin.

/**
     * Provides translation between HTTP/2 and HTTP header objects while ensuring the stream
     * is in a valid state for additional headers.
     *
     * @param ctx The context for which this message has been received.
     * Used to send informational header if detected.
     * @param stream The stream the {@code headers} apply to
     * @param headers The headers to process
     * @param endOfStream {@code true} if the {@code stream} has received the end of stream flag
     * @param allowAppend
     * <ul>
     * <li>{@code true} if headers will be appended if the stream already exists.</li>
     * <li>if {@code false} and the stream already exists this method returns {@code null}.</li>
     * </ul>
     * @param appendToTrailer
     * <ul>
     * <li>{@code true} if a message {@code stream} already exists then the headers
     * should be added to the trailing headers.</li>
     * <li>{@code false} then appends will be done to the initial headers.</li>
     * </ul>
     * @return The object used to track the stream corresponding to {@code stream}. {@code null} if
     *         {@code allowAppend} is {@code false} and the stream already exists.
     * @throws Http2Exception If the stream id is not in the correct state to process the headers request
     */
protected FullHttpMessage processHeadersBegin(ChannelHandlerContext ctx, Http2Stream stream, Http2Headers headers, boolean endOfStream, boolean allowAppend, boolean appendToTrailer) throws Http2Exception {
    FullHttpMessage msg = getMessage(stream);
    boolean release = true;
    if (msg == null) {
        msg = newMessage(stream, headers, validateHttpHeaders, ctx.alloc());
    } else if (allowAppend) {
        release = false;
        HttpConversionUtil.addHttp2ToHttpHeaders(stream.id(), headers, msg, appendToTrailer);
    } else {
        release = false;
        msg = null;
    }
    if (sendDetector.mustSendImmediately(msg)) {
        // Copy the message (if necessary) before sending. The content is not expected to be copied (or used) in
        // this operation but just in case it is used do the copy before sending and the resource may be released
        final FullHttpMessage copy = endOfStream ? null : sendDetector.copyIfNeeded(msg);
        fireChannelRead(ctx, msg, release, stream);
        return copy;
    }
    return msg;
}
Also used : FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage)

Example 20 with FullHttpMessage

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

the class InboundHttp2ToHttpAdapter method onRstStreamRead.

@Override
public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long errorCode) throws Http2Exception {
    Http2Stream stream = connection.stream(streamId);
    FullHttpMessage msg = getMessage(stream);
    if (msg != null) {
        onRstStreamRead(stream, msg);
    }
    ctx.fireExceptionCaught(Http2Exception.streamError(streamId, Http2Error.valueOf(errorCode), "HTTP/2 to HTTP layer caught stream reset"));
}
Also used : FullHttpMessage(io.netty.handler.codec.http.FullHttpMessage)

Aggregations

FullHttpMessage (io.netty.handler.codec.http.FullHttpMessage)20 DefaultFullHttpRequest (io.netty.handler.codec.http.DefaultFullHttpRequest)12 HttpHeaders (io.netty.handler.codec.http.HttpHeaders)12 ByteBuf (io.netty.buffer.ByteBuf)11 Http2CodecUtil.getEmbeddedHttp2Exception (io.netty.handler.codec.http2.Http2CodecUtil.getEmbeddedHttp2Exception)11 Http2Runnable (io.netty.handler.codec.http2.Http2TestUtil.Http2Runnable)11 AsciiString (io.netty.util.AsciiString)11 Test (org.junit.Test)11 FullHttpRequest (io.netty.handler.codec.http.FullHttpRequest)10 DefaultFullHttpResponse (io.netty.handler.codec.http.DefaultFullHttpResponse)3 TooLongFrameException (io.netty.handler.codec.TooLongFrameException)1 EmptyHttpHeaders (io.netty.handler.codec.http.EmptyHttpHeaders)1 FullHttpResponse (io.netty.handler.codec.http.FullHttpResponse)1 HttpContent (io.netty.handler.codec.http.HttpContent)1 HttpMessage (io.netty.handler.codec.http.HttpMessage)1 LastHttpContent (io.netty.handler.codec.http.LastHttpContent)1 SimpleChannelPromiseAggregator (io.netty.handler.codec.http2.Http2CodecUtil.SimpleChannelPromiseAggregator)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1