use of org.xnio.conduits.ConduitStreamSourceChannel in project indy by Commonjava.
the class ProxyAcceptHandler method handleEvent.
@Override
public void handleEvent(AcceptingChannel<StreamConnection> channel) {
long start = System.nanoTime();
RequestContextHelper.setContext(RequestContextHelper.ACCESS_CHANNEL, AccessChannel.GENERIC_PROXY.toString());
setContext(PACKAGE_TYPE, PKG_TYPE_GENERIC_HTTP);
final Logger logger = LoggerFactory.getLogger(getClass());
StreamConnection accepted;
try {
accepted = channel.accept();
} catch (IOException e) {
logger.error("Failed to accept httprox connection: " + e.getMessage(), e);
accepted = null;
}
// to remove the return in the catch clause, which is bad form...
if (accepted == null) {
return;
}
RequestContextHelper.setContext(REQUEST_PHASE, REQUEST_PHASE_START);
LoggerFactory.getLogger(PROXY_METRIC_LOGGER).info("START HTTProx request (from: {})", accepted.getPeerAddress());
RequestContextHelper.clearContext(REQUEST_PHASE);
logger.debug("accepted {}", accepted.getPeerAddress());
final ConduitStreamSourceChannel source = accepted.getSourceChannel();
final ConduitStreamSinkChannel sink = accepted.getSinkChannel();
final ProxyRepositoryCreator creator = createRepoCreator();
final ProxyResponseWriter writer = new ProxyResponseWriter(config, storeManager, contentController, proxyAuthenticator, cacheProvider, mdcManager, creator, accepted, metricsConfig, metricsManager, sliMetricSet, cacheProducer, start, proxyExecutor.getExecutor());
logger.debug("Setting writer: {}", writer);
sink.getWriteSetter().set(writer);
final ProxyRequestReader reader = new ProxyRequestReader(writer, sink, traceManager == null ? Optional.empty() : Optional.of(traceManager));
writer.setProxyRequestReader(reader);
logger.debug("Setting reader: {}", reader);
source.getReadSetter().set(reader);
source.resumeReads();
}
use of org.xnio.conduits.ConduitStreamSourceChannel in project undertow by undertow-io.
the class HttpServerExchange method getRequestChannel.
/**
* Get the inbound request. If there is no request body, calling this method
* may cause the next request to immediately be processed. The {@link StreamSourceChannel#close()} or {@link StreamSourceChannel#shutdownReads()}
* method must be called at some point after the request is processed to prevent resource leakage and to allow
* the next request to proceed. Any unread content will be discarded.
*
* @return the channel for the inbound request, or {@code null} if another party already acquired the channel
*/
public StreamSourceChannel getRequestChannel() {
if (requestChannel != null) {
if (anyAreSet(state, FLAG_REQUEST_RESET)) {
state &= ~FLAG_REQUEST_RESET;
return requestChannel;
}
return null;
}
if (anyAreSet(state, FLAG_REQUEST_TERMINATED)) {
return requestChannel = new ReadDispatchChannel(new ConduitStreamSourceChannel(Configurable.EMPTY, new EmptyStreamSourceConduit(getIoThread())));
}
final ConduitWrapper<StreamSourceConduit>[] wrappers = this.requestWrappers;
final ConduitStreamSourceChannel sourceChannel = connection.getSourceChannel();
if (wrappers != null) {
this.requestWrappers = null;
final WrapperConduitFactory<StreamSourceConduit> factory = new WrapperConduitFactory<>(wrappers, requestWrapperCount, sourceChannel.getConduit(), this);
sourceChannel.setConduit(factory.create());
}
return requestChannel = new ReadDispatchChannel(sourceChannel);
}
use of org.xnio.conduits.ConduitStreamSourceChannel in project undertow by undertow-io.
the class HttpReadListener method handleHttp2PriorKnowledge.
private void handleHttp2PriorKnowledge(final StreamConnection connection, final HttpServerConnection serverConnection, PooledByteBuffer readData) throws IOException {
final ConduitStreamSourceChannel request = connection.getSourceChannel();
byte[] data = new byte[PRI_EXPECTED.length];
final ByteBuffer buffer = ByteBuffer.wrap(data);
if (readData.getBuffer().hasRemaining()) {
while (readData.getBuffer().hasRemaining() && buffer.hasRemaining()) {
buffer.put(readData.getBuffer().get());
}
}
final PooledByteBuffer extraData;
if (readData.getBuffer().hasRemaining()) {
extraData = readData;
} else {
readData.close();
extraData = null;
}
if (!doHttp2PriRead(connection, buffer, serverConnection, extraData)) {
request.getReadSetter().set(new ChannelListener<StreamSourceChannel>() {
@Override
public void handleEvent(StreamSourceChannel channel) {
try {
doHttp2PriRead(connection, buffer, serverConnection, extraData);
} catch (IOException e) {
UndertowLogger.REQUEST_IO_LOGGER.ioException(e);
IoUtils.safeClose(connection);
} catch (Throwable t) {
UndertowLogger.REQUEST_IO_LOGGER.handleUnexpectedFailure(t);
IoUtils.safeClose(connection);
}
}
});
request.resumeReads();
}
}
use of org.xnio.conduits.ConduitStreamSourceChannel in project undertow by undertow-io.
the class HttpTransferEncoding method setupRequest.
public static void setupRequest(final HttpServerExchange exchange) {
final HeaderMap requestHeaders = exchange.getRequestHeaders();
final String connectionHeader = requestHeaders.getFirst(Headers.CONNECTION);
final String transferEncodingHeader = requestHeaders.getLast(Headers.TRANSFER_ENCODING);
final String contentLengthHeader = requestHeaders.getFirst(Headers.CONTENT_LENGTH);
final HttpServerConnection connection = (HttpServerConnection) exchange.getConnection();
// if we are already using the pipelineing buffer add it to the exchange
PipeliningBufferingStreamSinkConduit pipeliningBuffer = connection.getPipelineBuffer();
if (pipeliningBuffer != null) {
pipeliningBuffer.setupPipelineBuffer(exchange);
}
ConduitStreamSourceChannel sourceChannel = connection.getChannel().getSourceChannel();
sourceChannel.setConduit(connection.getReadDataStreamSourceConduit());
boolean persistentConnection = persistentConnection(exchange, connectionHeader);
if (transferEncodingHeader == null && contentLengthHeader == null) {
if (persistentConnection && connection.getExtraBytes() != null && pipeliningBuffer == null && connection.getUndertowOptions().get(UndertowOptions.BUFFER_PIPELINED_DATA, false)) {
pipeliningBuffer = new PipeliningBufferingStreamSinkConduit(connection.getOriginalSinkConduit(), connection.getByteBufferPool());
connection.setPipelineBuffer(pipeliningBuffer);
pipeliningBuffer.setupPipelineBuffer(exchange);
}
// no content - immediately start the next request, returning an empty stream for this one
Connectors.terminateRequest(exchange);
} else {
persistentConnection = handleRequestEncoding(exchange, transferEncodingHeader, contentLengthHeader, connection, pipeliningBuffer, persistentConnection);
}
exchange.setPersistent(persistentConnection);
if (!exchange.isRequestComplete() || connection.getExtraBytes() != null) {
// if there is more data we suspend reads
sourceChannel.setReadListener(null);
sourceChannel.suspendReads();
}
}
use of org.xnio.conduits.ConduitStreamSourceChannel in project undertow by undertow-io.
the class HttpTransferEncoding method handleRequestEncoding.
private static boolean handleRequestEncoding(final HttpServerExchange exchange, String transferEncodingHeader, String contentLengthHeader, HttpServerConnection connection, PipeliningBufferingStreamSinkConduit pipeliningBuffer, boolean persistentConnection) {
HttpString transferEncoding = Headers.IDENTITY;
if (transferEncodingHeader != null) {
transferEncoding = new HttpString(transferEncodingHeader);
}
if (transferEncodingHeader != null && !transferEncoding.equals(Headers.IDENTITY)) {
ConduitStreamSourceChannel sourceChannel = ((HttpServerConnection) exchange.getConnection()).getChannel().getSourceChannel();
sourceChannel.setConduit(new ChunkedStreamSourceConduit(sourceChannel.getConduit(), exchange, chunkedDrainListener(exchange)));
} else if (contentLengthHeader != null) {
final long contentLength;
contentLength = parsePositiveLong(contentLengthHeader);
if (contentLength == 0L) {
log.trace("No content, starting next request");
// no content - immediately start the next request, returning an empty stream for this one
Connectors.terminateRequest(exchange);
} else {
// fixed-length content - add a wrapper for a fixed-length stream
ConduitStreamSourceChannel sourceChannel = ((HttpServerConnection) exchange.getConnection()).getChannel().getSourceChannel();
sourceChannel.setConduit(fixedLengthStreamSourceConduitWrapper(contentLength, sourceChannel.getConduit(), exchange));
}
} else if (transferEncodingHeader != null) {
// identity transfer encoding
log.trace("Connection not persistent (no content length and identity transfer encoding)");
// make it not persistent
persistentConnection = false;
} else if (persistentConnection) {
// performance
if (connection.getExtraBytes() != null && pipeliningBuffer == null && connection.getUndertowOptions().get(UndertowOptions.BUFFER_PIPELINED_DATA, false)) {
pipeliningBuffer = new PipeliningBufferingStreamSinkConduit(connection.getOriginalSinkConduit(), connection.getByteBufferPool());
connection.setPipelineBuffer(pipeliningBuffer);
pipeliningBuffer.setupPipelineBuffer(exchange);
}
// no content - immediately start the next request, returning an empty stream for this one
Connectors.terminateRequest(exchange);
} else {
// assume there is no content
// we still know there is no content
Connectors.terminateRequest(exchange);
}
return persistentConnection;
}
Aggregations