Search in sources :

Example 1 with StreamSinkConduit

use of org.xnio.conduits.StreamSinkConduit in project undertow by undertow-io.

the class HttpClientConnection method initiateRequest.

private void initiateRequest(HttpClientExchange httpClientExchange) {
    this.requestCount++;
    currentRequest = httpClientExchange;
    pendingResponse = new HttpResponseBuilder();
    ClientRequest request = httpClientExchange.getRequest();
    String connectionString = request.getRequestHeaders().getFirst(Headers.CONNECTION);
    if (connectionString != null) {
        if (Headers.CLOSE.equalToString(connectionString)) {
            state |= CLOSE_REQ;
        } else if (Headers.UPGRADE.equalToString(connectionString)) {
            state |= UPGRADE_REQUESTED;
        }
    } else if (request.getProtocol() != Protocols.HTTP_1_1) {
        state |= CLOSE_REQ;
    }
    if (request.getRequestHeaders().contains(Headers.UPGRADE)) {
        state |= UPGRADE_REQUESTED;
    }
    if (request.getMethod().equals(Methods.CONNECT)) {
        // we treat CONNECT like upgrade requests
        state |= UPGRADE_REQUESTED;
    }
    // setup the client request conduits
    final ConduitStreamSourceChannel sourceChannel = connection.getSourceChannel();
    sourceChannel.setReadListener(clientReadListener);
    sourceChannel.resumeReads();
    ConduitStreamSinkChannel sinkChannel = connection.getSinkChannel();
    StreamSinkConduit conduit = originalSinkConduit;
    HttpRequestConduit httpRequestConduit = new HttpRequestConduit(conduit, bufferPool, request);
    httpClientExchange.setRequestConduit(httpRequestConduit);
    conduit = httpRequestConduit;
    String fixedLengthString = request.getRequestHeaders().getFirst(Headers.CONTENT_LENGTH);
    String transferEncodingString = request.getRequestHeaders().getLast(Headers.TRANSFER_ENCODING);
    boolean hasContent = true;
    if (fixedLengthString != null) {
        try {
            long length = Long.parseLong(fixedLengthString);
            conduit = new ClientFixedLengthStreamSinkConduit(conduit, length, false, false, currentRequest);
            hasContent = length != 0;
        } catch (NumberFormatException e) {
            handleError(e);
            return;
        }
    } else if (transferEncodingString != null) {
        if (!transferEncodingString.toLowerCase(Locale.ENGLISH).contains(Headers.CHUNKED.toString())) {
            handleError(UndertowClientMessages.MESSAGES.unknownTransferEncoding(transferEncodingString));
            return;
        }
        conduit = new ChunkedStreamSinkConduit(conduit, httpClientExchange.getConnection().getBufferPool(), false, false, httpClientExchange.getRequest().getRequestHeaders(), requestFinishListener, httpClientExchange);
    } else {
        conduit = new ClientFixedLengthStreamSinkConduit(conduit, 0, false, false, currentRequest);
        hasContent = false;
    }
    sinkChannel.setConduit(conduit);
    httpClientExchange.invokeReadReadyCallback();
    if (!hasContent) {
        // otherwise it is up to the user
        try {
            sinkChannel.shutdownWrites();
            if (!sinkChannel.flush()) {
                sinkChannel.setWriteListener(ChannelListeners.flushingChannelListener(null, new ChannelExceptionHandler<ConduitStreamSinkChannel>() {

                    @Override
                    public void handleException(ConduitStreamSinkChannel channel, IOException exception) {
                        handleError(exception);
                    }
                }));
                sinkChannel.resumeWrites();
            }
        } catch (Throwable t) {
            handleError(t);
        }
    }
}
Also used : ChunkedStreamSinkConduit(io.undertow.conduits.ChunkedStreamSinkConduit) HttpString(io.undertow.util.HttpString) IOException(java.io.IOException) StreamSinkConduit(org.xnio.conduits.StreamSinkConduit) WriteTimeoutStreamSinkConduit(io.undertow.conduits.WriteTimeoutStreamSinkConduit) BytesSentStreamSinkConduit(io.undertow.conduits.BytesSentStreamSinkConduit) ChunkedStreamSinkConduit(io.undertow.conduits.ChunkedStreamSinkConduit) ChannelExceptionHandler(org.xnio.ChannelExceptionHandler) ConduitStreamSourceChannel(org.xnio.conduits.ConduitStreamSourceChannel) ClientRequest(io.undertow.client.ClientRequest) ConduitStreamSinkChannel(org.xnio.conduits.ConduitStreamSinkChannel)

Example 2 with StreamSinkConduit

use of org.xnio.conduits.StreamSinkConduit in project undertow by undertow-io.

the class StoredResponseHandler method handleRequest.

@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
    exchange.addResponseWrapper(new ConduitWrapper<StreamSinkConduit>() {

        @Override
        public StreamSinkConduit wrap(ConduitFactory<StreamSinkConduit> factory, HttpServerExchange exchange) {
            return new StoredResponseStreamSinkConduit(factory.create(), exchange);
        }
    });
    next.handleRequest(exchange);
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) StoredResponseStreamSinkConduit(io.undertow.conduits.StoredResponseStreamSinkConduit) StoredResponseStreamSinkConduit(io.undertow.conduits.StoredResponseStreamSinkConduit) StreamSinkConduit(org.xnio.conduits.StreamSinkConduit)

Example 3 with StreamSinkConduit

use of org.xnio.conduits.StreamSinkConduit in project undertow by undertow-io.

the class ContentEncodedResourceManager method getResource.

/**
 * Gets a pre-encoded resource.
 * <p>
 * TODO: blocking / non-blocking semantics
 *
 * @param resource
 * @param exchange
 * @return
 * @throws IOException
 */
public ContentEncodedResource getResource(final Resource resource, final HttpServerExchange exchange) throws IOException {
    final String path = resource.getPath();
    Path file = resource.getFilePath();
    if (file == null) {
        return null;
    }
    if (minResourceSize > 0 && resource.getContentLength() < minResourceSize || maxResourceSize > 0 && resource.getContentLength() > maxResourceSize || !(encodingAllowed == null || encodingAllowed.resolve(exchange))) {
        return null;
    }
    AllowedContentEncodings encodings = contentEncodingRepository.getContentEncodings(exchange);
    if (encodings == null || encodings.isNoEncodingsAllowed()) {
        return null;
    }
    EncodingMapping encoding = encodings.getEncoding();
    if (encoding == null || encoding.getName().equals(ContentEncodingRepository.IDENTITY)) {
        return null;
    }
    String newPath = path + ".undertow.encoding." + encoding.getName();
    Resource preCompressed = encoded.getResource(newPath);
    if (preCompressed != null) {
        return new ContentEncodedResource(preCompressed, encoding.getName());
    }
    final LockKey key = new LockKey(path, encoding.getName());
    if (fileLocks.putIfAbsent(key, this) != null) {
        // we don't do anything fancy here, just return and serve non-compressed content
        return null;
    }
    FileChannel targetFileChannel = null;
    FileChannel sourceFileChannel = null;
    try {
        // double check, the compressing thread could have finished just before we acquired the lock
        preCompressed = encoded.getResource(newPath);
        if (preCompressed != null) {
            return new ContentEncodedResource(preCompressed, encoding.getName());
        }
        final Path finalTarget = encodedResourcesRoot.resolve(newPath);
        final Path tempTarget = encodedResourcesRoot.resolve(newPath);
        // horrible hack to work around XNIO issue
        OutputStream tmp = Files.newOutputStream(tempTarget);
        try {
            tmp.close();
        } finally {
            IoUtils.safeClose(tmp);
        }
        targetFileChannel = FileChannel.open(tempTarget, StandardOpenOption.READ, StandardOpenOption.WRITE);
        sourceFileChannel = FileChannel.open(file, StandardOpenOption.READ);
        StreamSinkConduit conduit = encoding.getEncoding().getResponseWrapper().wrap(new ImmediateConduitFactory<StreamSinkConduit>(new FileConduitTarget(targetFileChannel, exchange)), exchange);
        final ConduitStreamSinkChannel targetChannel = new ConduitStreamSinkChannel(null, conduit);
        long transferred = sourceFileChannel.transferTo(0, resource.getContentLength(), targetChannel);
        targetChannel.shutdownWrites();
        org.xnio.channels.Channels.flushBlocking(targetChannel);
        if (transferred != resource.getContentLength()) {
            UndertowLogger.REQUEST_LOGGER.failedToWritePreCachedFile();
        }
        Files.move(tempTarget, finalTarget);
        encoded.invalidate(newPath);
        final Resource encodedResource = encoded.getResource(newPath);
        return new ContentEncodedResource(encodedResource, encoding.getName());
    } finally {
        IoUtils.safeClose(targetFileChannel);
        IoUtils.safeClose(sourceFileChannel);
        fileLocks.remove(key);
    }
}
Also used : Path(java.nio.file.Path) FileChannel(java.nio.channels.FileChannel) OutputStream(java.io.OutputStream) Resource(io.undertow.server.handlers.resource.Resource) StreamSinkConduit(org.xnio.conduits.StreamSinkConduit) ConduitStreamSinkChannel(org.xnio.conduits.ConduitStreamSinkChannel)

Example 4 with StreamSinkConduit

use of org.xnio.conduits.StreamSinkConduit 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 5 with StreamSinkConduit

use of org.xnio.conduits.StreamSinkConduit in project undertow by undertow-io.

the class HttpServerConnection method sendOutOfBandResponse.

@Override
public HttpServerExchange sendOutOfBandResponse(HttpServerExchange exchange) {
    if (exchange == null || !HttpContinue.requiresContinueResponse(exchange)) {
        throw UndertowMessages.MESSAGES.outOfBandResponseOnlyAllowedFor100Continue();
    }
    final ConduitState state = resetChannel();
    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.getRequestHeaders().put(Headers.CONNECTION, Headers.KEEP_ALIVE.toString());
    newExchange.getRequestHeaders().put(Headers.CONTENT_LENGTH, 0);
    newExchange.setPersistent(true);
    Connectors.terminateRequest(newExchange);
    newExchange.addResponseWrapper(new ConduitWrapper<StreamSinkConduit>() {

        @Override
        public StreamSinkConduit wrap(ConduitFactory<StreamSinkConduit> factory, HttpServerExchange exchange) {
            HttpResponseConduit httpResponseConduit = new HttpResponseConduit(getSinkChannel().getConduit(), getByteBufferPool(), HttpServerConnection.this, exchange);
            exchange.addExchangeCompleteListener(new ExchangeCompletionListener() {

                @Override
                public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) {
                    httpResponseConduit.freeContinueResponse();
                    nextListener.proceed();
                }
            });
            ServerFixedLengthStreamSinkConduit fixed = new ServerFixedLengthStreamSinkConduit(httpResponseConduit, false, false);
            fixed.reset(0, exchange);
            return fixed;
        }
    });
    // we restore the read channel immediately, as this out of band response has no read side
    channel.getSourceChannel().setConduit(source(state));
    newExchange.addExchangeCompleteListener(new ExchangeCompletionListener() {

        @Override
        public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) {
            restoreChannel(state);
        }
    });
    return newExchange;
}
Also used : HttpServerExchange(io.undertow.server.HttpServerExchange) StreamSinkConduit(org.xnio.conduits.StreamSinkConduit) ExchangeCompletionListener(io.undertow.server.ExchangeCompletionListener) HttpString(io.undertow.util.HttpString)

Aggregations

StreamSinkConduit (org.xnio.conduits.StreamSinkConduit)8 HttpServerExchange (io.undertow.server.HttpServerExchange)5 HttpString (io.undertow.util.HttpString)4 HeadStreamSinkConduit (io.undertow.conduits.HeadStreamSinkConduit)3 HeaderMap (io.undertow.util.HeaderMap)3 ChunkedStreamSinkConduit (io.undertow.conduits.ChunkedStreamSinkConduit)2 ConduitStreamSinkChannel (org.xnio.conduits.ConduitStreamSinkChannel)2 ClientRequest (io.undertow.client.ClientRequest)1 BytesSentStreamSinkConduit (io.undertow.conduits.BytesSentStreamSinkConduit)1 FinishableStreamSinkConduit (io.undertow.conduits.FinishableStreamSinkConduit)1 PreChunkedStreamSinkConduit (io.undertow.conduits.PreChunkedStreamSinkConduit)1 RangeStreamSinkConduit (io.undertow.conduits.RangeStreamSinkConduit)1 StoredResponseStreamSinkConduit (io.undertow.conduits.StoredResponseStreamSinkConduit)1 WriteTimeoutStreamSinkConduit (io.undertow.conduits.WriteTimeoutStreamSinkConduit)1 Http2Channel (io.undertow.protocols.http2.Http2Channel)1 Http2DataStreamSinkChannel (io.undertow.protocols.http2.Http2DataStreamSinkChannel)1 Http2HeadersStreamSinkChannel (io.undertow.protocols.http2.Http2HeadersStreamSinkChannel)1 ExchangeCompletionListener (io.undertow.server.ExchangeCompletionListener)1 Resource (io.undertow.server.handlers.resource.Resource)1 ByteRange (io.undertow.util.ByteRange)1