use of org.xnio.ChannelExceptionHandler 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);
}
}
}
use of org.xnio.ChannelExceptionHandler in project undertow by undertow-io.
the class Http2ClientConnection method sendRequest.
@Override
public void sendRequest(ClientRequest request, ClientCallback<ClientExchange> clientCallback) {
if (!http2Channel.isOpen()) {
clientCallback.failed(new ClosedChannelException());
return;
}
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);
Http2HeadersStreamSinkChannel sinkChannel;
try {
sinkChannel = http2Channel.createStream(request.getRequestHeaders());
} catch (Throwable t) {
IOException e = t instanceof IOException ? (IOException) t : new IOException(t);
clientCallback.failed(e);
return;
}
Http2ClientExchange exchange = new Http2ClientExchange(this, sinkChannel, request);
currentExchanges.put(sinkChannel.getStreamId(), exchange);
sinkChannel.setTrailersProducer(new Http2DataStreamSinkChannel.TrailersProducer() {
@Override
public HeaderMap getTrailers() {
HeaderMap attachment = exchange.getAttachment(HttpAttachments.RESPONSE_TRAILERS);
Supplier<HeaderMap> supplier = exchange.getAttachment(HttpAttachments.RESPONSE_TRAILER_SUPPLIER);
if (attachment != null && supplier == null) {
return attachment;
} else if (attachment == null && supplier != null) {
return supplier.get();
} else if (attachment != null) {
HeaderMap supplied = supplier.get();
for (HeaderValues k : supplied) {
attachment.putAll(k.getHeaderName(), k);
}
return attachment;
} else {
return null;
}
}
});
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 (Throwable e) {
handleError(e);
}
}
}
use of org.xnio.ChannelExceptionHandler in project undertow by undertow-io.
the class AsyncSenderImpl method close.
@Override
public void close(final IoCallback callback) {
try {
StreamSinkChannel channel = this.channel;
if (channel == null) {
if (exchange.getResponseContentLength() == -1 && !exchange.getResponseHeaders().contains(Headers.TRANSFER_ENCODING)) {
exchange.setResponseContentLength(0);
}
this.channel = channel = exchange.getResponseChannel();
if (channel == null) {
throw UndertowMessages.MESSAGES.responseChannelAlreadyProvided();
}
}
channel.shutdownWrites();
if (!channel.flush()) {
channel.getWriteSetter().set(ChannelListeners.flushingChannelListener(new ChannelListener<StreamSinkChannel>() {
@Override
public void handleEvent(final StreamSinkChannel channel) {
if (callback != null) {
callback.onComplete(exchange, AsyncSenderImpl.this);
}
}
}, new ChannelExceptionHandler<StreamSinkChannel>() {
@Override
public void handleException(final StreamSinkChannel channel, final IOException exception) {
try {
if (callback != null) {
invokeOnException(callback, exception);
}
} finally {
IoUtils.safeClose(channel);
}
}
}));
channel.resumeWrites();
} else {
if (callback != null) {
callback.onComplete(exchange, this);
}
}
} catch (IOException e) {
if (callback != null) {
invokeOnException(callback, e);
}
}
}
use of org.xnio.ChannelExceptionHandler in project undertow by undertow-io.
the class ServerSentEventHandler method handleRequest.
@Override
public void handleRequest(final HttpServerExchange exchange) throws Exception {
exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, "text/event-stream; charset=UTF-8");
exchange.setPersistent(false);
final StreamSinkChannel sink = exchange.getResponseChannel();
if (!sink.flush()) {
sink.getWriteSetter().set(ChannelListeners.flushingChannelListener(new ChannelListener<StreamSinkChannel>() {
@Override
public void handleEvent(StreamSinkChannel channel) {
handleConnect(channel, exchange);
}
}, new ChannelExceptionHandler<StreamSinkChannel>() {
@Override
public void handleException(StreamSinkChannel channel, IOException exception) {
IoUtils.safeClose(exchange.getConnection());
}
}));
sink.resumeWrites();
} else {
exchange.dispatch(exchange.getIoThread(), new Runnable() {
@Override
public void run() {
handleConnect(sink, exchange);
}
});
}
}
use of org.xnio.ChannelExceptionHandler in project undertow by undertow-io.
the class HttpContinue method internalSendContinueResponse.
private static void internalSendContinueResponse(final HttpServerExchange exchange, final IoCallback callback) {
if (exchange.getAttachment(ALREADY_SENT) != null) {
callback.onComplete(exchange, null);
return;
}
HttpServerExchange newExchange = exchange.getConnection().sendOutOfBandResponse(exchange);
exchange.putAttachment(ALREADY_SENT, true);
newExchange.setStatusCode(StatusCodes.CONTINUE);
newExchange.getResponseHeaders().put(Headers.CONTENT_LENGTH, 0);
final StreamSinkChannel responseChannel = newExchange.getResponseChannel();
try {
responseChannel.shutdownWrites();
if (!responseChannel.flush()) {
responseChannel.getWriteSetter().set(ChannelListeners.flushingChannelListener(new ChannelListener<StreamSinkChannel>() {
@Override
public void handleEvent(StreamSinkChannel channel) {
channel.suspendWrites();
exchange.dispatch(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
callback.onComplete(exchange, null);
}
});
}
}, new ChannelExceptionHandler<Channel>() {
@Override
public void handleException(Channel channel, final IOException e) {
exchange.dispatch(new HttpHandler() {
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
callback.onException(exchange, null, e);
}
});
}
}));
responseChannel.resumeWrites();
exchange.dispatch();
} else {
callback.onComplete(exchange, null);
}
} catch (IOException e) {
callback.onException(exchange, null, e);
}
}
Aggregations