Search in sources :

Example 1 with Http2HeadersStreamSinkChannel

use of io.undertow.protocols.http2.Http2HeadersStreamSinkChannel in project undertow by undertow-io.

the class Http2ClientConnection method sendRequest.

@Override
public void sendRequest(ClientRequest request, ClientCallback<ClientExchange> clientCallback) {
    request.getRequestHeaders().put(METHOD, request.getMethod().toString());
    boolean connectRequest = request.getMethod().equals(Methods.CONNECT);
    if (!connectRequest) {
        request.getRequestHeaders().put(PATH, request.getPath());
        request.getRequestHeaders().put(SCHEME, secure ? "https" : "http");
    }
    final String host = request.getRequestHeaders().getFirst(Headers.HOST);
    if (host != null) {
        request.getRequestHeaders().put(AUTHORITY, host);
    } else {
        request.getRequestHeaders().put(AUTHORITY, defaultHost);
    }
    request.getRequestHeaders().remove(Headers.HOST);
    boolean hasContent = true;
    String fixedLengthString = request.getRequestHeaders().getFirst(CONTENT_LENGTH);
    String transferEncodingString = request.getRequestHeaders().getLast(TRANSFER_ENCODING);
    if (fixedLengthString != null) {
        try {
            long length = Long.parseLong(fixedLengthString);
            hasContent = length != 0;
        } catch (NumberFormatException e) {
            handleError(new IOException(e));
            return;
        }
    } else if (transferEncodingString == null && !connectRequest) {
        hasContent = false;
    }
    request.getRequestHeaders().remove(Headers.CONNECTION);
    request.getRequestHeaders().remove(Headers.KEEP_ALIVE);
    request.getRequestHeaders().remove(Headers.TRANSFER_ENCODING);
    //setup the X-Forwarded-* headers
    String peer = request.getAttachment(ProxiedRequestAttachments.REMOTE_HOST);
    if (peer != null) {
        request.getRequestHeaders().put(Headers.X_FORWARDED_FOR, peer);
    }
    Boolean proto = request.getAttachment(ProxiedRequestAttachments.IS_SSL);
    if (proto == null || !proto) {
        request.getRequestHeaders().put(Headers.X_FORWARDED_PROTO, "http");
    } else {
        request.getRequestHeaders().put(Headers.X_FORWARDED_PROTO, "https");
    }
    String hn = request.getAttachment(ProxiedRequestAttachments.SERVER_NAME);
    if (hn != null) {
        request.getRequestHeaders().put(Headers.X_FORWARDED_HOST, NetworkUtils.formatPossibleIpv6Address(hn));
    }
    Integer port = request.getAttachment(ProxiedRequestAttachments.SERVER_PORT);
    if (port != null) {
        request.getRequestHeaders().put(Headers.X_FORWARDED_PORT, port);
    }
    Http2HeadersStreamSinkChannel sinkChannel;
    try {
        sinkChannel = http2Channel.createStream(request.getRequestHeaders());
    } catch (IOException e) {
        clientCallback.failed(e);
        return;
    }
    Http2ClientExchange exchange = new Http2ClientExchange(this, sinkChannel, request);
    currentExchanges.put(sinkChannel.getStreamId(), exchange);
    if (clientCallback != null) {
        clientCallback.completed(exchange);
    }
    if (!hasContent) {
        //otherwise it is up to the user
        try {
            sinkChannel.shutdownWrites();
            if (!sinkChannel.flush()) {
                sinkChannel.getWriteSetter().set(ChannelListeners.flushingChannelListener(null, new ChannelExceptionHandler<StreamSinkChannel>() {

                    @Override
                    public void handleException(StreamSinkChannel channel, IOException exception) {
                        handleError(exception);
                    }
                }));
                sinkChannel.resumeWrites();
            }
        } catch (IOException e) {
            handleError(e);
        }
    } else if (!sinkChannel.isWriteResumed()) {
        try {
            //TODO: this needs some more thought
            if (!sinkChannel.flush()) {
                sinkChannel.getWriteSetter().set(new ChannelListener<StreamSinkChannel>() {

                    @Override
                    public void handleEvent(StreamSinkChannel channel) {
                        try {
                            if (channel.flush()) {
                                channel.suspendWrites();
                            }
                        } catch (IOException e) {
                            handleError(e);
                        }
                    }
                });
                sinkChannel.resumeWrites();
            }
        } catch (IOException e) {
            handleError(e);
        }
    }
}
Also used : Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) ChannelListener(org.xnio.ChannelListener) ChannelExceptionHandler(org.xnio.ChannelExceptionHandler) Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) StreamSinkChannel(org.xnio.channels.StreamSinkChannel) HttpString(io.undertow.util.HttpString) IOException(java.io.IOException)

Example 2 with Http2HeadersStreamSinkChannel

use of io.undertow.protocols.http2.Http2HeadersStreamSinkChannel in project undertow by undertow-io.

the class Http2ServerConnection method sendOutOfBandResponse.

@Override
public HttpServerExchange sendOutOfBandResponse(HttpServerExchange exchange) {
    if (exchange == null || !HttpContinue.requiresContinueResponse(exchange)) {
        throw UndertowMessages.MESSAGES.outOfBandResponseOnlyAllowedFor100Continue();
    }
    final HttpServerExchange newExchange = new HttpServerExchange(this);
    for (HttpString header : exchange.getRequestHeaders().getHeaderNames()) {
        newExchange.getRequestHeaders().putAll(header, exchange.getRequestHeaders().get(header));
    }
    newExchange.setProtocol(exchange.getProtocol());
    newExchange.setRequestMethod(exchange.getRequestMethod());
    exchange.setRequestURI(exchange.getRequestURI(), exchange.isHostIncludedInRequestURI());
    exchange.setRequestPath(exchange.getRequestPath());
    exchange.setRelativePath(exchange.getRelativePath());
    newExchange.setPersistent(true);
    Connectors.terminateRequest(newExchange);
    newExchange.addResponseWrapper(new ConduitWrapper<StreamSinkConduit>() {

        @Override
        public StreamSinkConduit wrap(ConduitFactory<StreamSinkConduit> factory, HttpServerExchange exchange) {
            HeaderMap headers = newExchange.getResponseHeaders();
            DateUtils.addDateHeaderIfRequired(exchange);
            headers.add(STATUS, exchange.getStatusCode());
            Connectors.flattenCookies(exchange);
            Http2HeadersStreamSinkChannel sink = new Http2HeadersStreamSinkChannel(channel, requestChannel.getStreamId(), headers);
            StreamSinkChannelWrappingConduit ret = new StreamSinkChannelWrappingConduit(sink);
            ret.setWriteReadyHandler(new WriteReadyHandler.ChannelListenerHandler(Connectors.getConduitSinkChannel(exchange)));
            return ret;
        }
    });
    continueSent = true;
    return newExchange;
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) HeaderMap(io.undertow.util.HeaderMap) StreamSinkConduit(org.xnio.conduits.StreamSinkConduit) StreamSinkChannelWrappingConduit(org.xnio.conduits.StreamSinkChannelWrappingConduit) HttpString(io.undertow.util.HttpString)

Example 3 with Http2HeadersStreamSinkChannel

use of io.undertow.protocols.http2.Http2HeadersStreamSinkChannel in project undertow by undertow-io.

the class Http2ReceiveListener method handleInitialRequest.

/**
     * Handles the initial request when the exchange was started by a HTTP ugprade.
     *
     *
     * @param initial The initial upgrade request that started the HTTP2 connection
     */
void handleInitialRequest(HttpServerExchange initial, Http2Channel channel) {
    //we have a request
    Http2HeadersStreamSinkChannel sink = channel.createInitialUpgradeResponseStream();
    final Http2ServerConnection connection = new Http2ServerConnection(channel, sink, undertowOptions, bufferSize, rootHandler);
    HeaderMap requestHeaders = new HeaderMap();
    for (HeaderValues hv : initial.getRequestHeaders()) {
        requestHeaders.putAll(hv.getHeaderName(), hv);
    }
    final HttpServerExchange exchange = new HttpServerExchange(connection, requestHeaders, sink.getHeaders(), maxEntitySize);
    connection.setExchange(exchange);
    exchange.setRequestScheme(initial.getRequestScheme());
    exchange.setProtocol(initial.getProtocol());
    exchange.setRequestMethod(initial.getRequestMethod());
    exchange.setQueryString(initial.getQueryString());
    String uri = exchange.getQueryString().isEmpty() ? initial.getRequestURI() : initial.getRequestURI() + '?' + exchange.getQueryString();
    try {
        Connectors.setExchangeRequestPath(exchange, uri, encoding, decode, allowEncodingSlash, decodeBuffer, maxParameters);
    } catch (ParameterLimitException e) {
        exchange.setStatusCode(StatusCodes.BAD_REQUEST);
        exchange.endExchange();
        return;
    }
    SSLSession session = channel.getSslSession();
    if (session != null) {
        connection.setSslSessionInfo(new Http2SslSessionInfo(channel));
    }
    Connectors.terminateRequest(exchange);
    sink.setCompletionListener(new ChannelListener<Http2DataStreamSinkChannel>() {

        @Override
        public void handleEvent(Http2DataStreamSinkChannel channel) {
            Connectors.terminateResponse(exchange);
        }
    });
    Connectors.executeRootHandler(rootHandler, exchange);
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) ParameterLimitException(io.undertow.util.ParameterLimitException) HeaderMap(io.undertow.util.HeaderMap) HeaderValues(io.undertow.util.HeaderValues) SSLSession(javax.net.ssl.SSLSession) HttpString(io.undertow.util.HttpString) Http2DataStreamSinkChannel(io.undertow.protocols.http2.Http2DataStreamSinkChannel)

Example 4 with Http2HeadersStreamSinkChannel

use of io.undertow.protocols.http2.Http2HeadersStreamSinkChannel in project undertow by undertow-io.

the class Http2ServerConnection method pushResource.

@Override
public boolean pushResource(String path, HttpString method, HeaderMap requestHeaders, final HttpHandler handler) {
    HeaderMap responseHeaders = new HeaderMap();
    try {
        requestHeaders.put(Http2ReceiveListener.METHOD, method.toString());
        requestHeaders.put(Http2ReceiveListener.PATH, path.toString());
        requestHeaders.put(Http2ReceiveListener.AUTHORITY, exchange.getHostAndPort());
        requestHeaders.put(Http2ReceiveListener.SCHEME, exchange.getRequestScheme());
        Http2HeadersStreamSinkChannel sink = channel.sendPushPromise(responseChannel.getStreamId(), requestHeaders, responseHeaders);
        Http2ServerConnection newConnection = new Http2ServerConnection(channel, sink, getUndertowOptions(), getBufferSize(), rootHandler);
        final HttpServerExchange exchange = new HttpServerExchange(newConnection, requestHeaders, responseHeaders, getUndertowOptions().get(UndertowOptions.MAX_ENTITY_SIZE, UndertowOptions.DEFAULT_MAX_ENTITY_SIZE));
        newConnection.setExchange(exchange);
        exchange.setRequestMethod(method);
        exchange.setProtocol(Protocols.HTTP_1_1);
        exchange.setRequestScheme(this.exchange.getRequestScheme());
        try {
            Connectors.setExchangeRequestPath(exchange, path, getUndertowOptions().get(UndertowOptions.URL_CHARSET, StandardCharsets.UTF_8.name()), getUndertowOptions().get(UndertowOptions.DECODE_URL, true), getUndertowOptions().get(UndertowOptions.ALLOW_ENCODED_SLASH, false), new StringBuilder(), getUndertowOptions().get(UndertowOptions.MAX_PARAMETERS, UndertowOptions.DEFAULT_MAX_HEADERS));
        } catch (ParameterLimitException e) {
            UndertowLogger.REQUEST_IO_LOGGER.debug("Too many parameters in HTTP/2 request", e);
            exchange.setStatusCode(StatusCodes.BAD_REQUEST);
            exchange.endExchange();
            return false;
        }
        Connectors.terminateRequest(exchange);
        getIoThread().execute(new Runnable() {

            @Override
            public void run() {
                Connectors.executeRootHandler(handler, exchange);
            }
        });
        return true;
    } catch (IOException e) {
        UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
        return false;
    }
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) Http2HeadersStreamSinkChannel(io.undertow.protocols.http2.Http2HeadersStreamSinkChannel) ParameterLimitException(io.undertow.util.ParameterLimitException) HeaderMap(io.undertow.util.HeaderMap) IOException(java.io.IOException)

Aggregations

Http2HeadersStreamSinkChannel (io.undertow.protocols.http2.Http2HeadersStreamSinkChannel)4 HttpServerExchange (io.undertow.server.HttpServerExchange)3 HeaderMap (io.undertow.util.HeaderMap)3 HttpString (io.undertow.util.HttpString)3 ParameterLimitException (io.undertow.util.ParameterLimitException)2 IOException (java.io.IOException)2 Http2DataStreamSinkChannel (io.undertow.protocols.http2.Http2DataStreamSinkChannel)1 HeaderValues (io.undertow.util.HeaderValues)1 SSLSession (javax.net.ssl.SSLSession)1 ChannelExceptionHandler (org.xnio.ChannelExceptionHandler)1 ChannelListener (org.xnio.ChannelListener)1 StreamSinkChannel (org.xnio.channels.StreamSinkChannel)1 StreamSinkChannelWrappingConduit (org.xnio.conduits.StreamSinkChannelWrappingConduit)1 StreamSinkConduit (org.xnio.conduits.StreamSinkConduit)1