//setup the client request conduits
final ConduitStreamSourceChannel sourceChannel = connection.getSourceChannel();
sourceChannel.setReadListener(clientReadListener);
sourceChannel.resumeReads();
ConduitStreamSinkChannel sinkChannel = connection.getSinkChannel();
StreamSinkConduit conduit = originalSinkConduit;
conduit = new HttpRequestConduit(conduit, bufferPool, request);
String fixedLengthString = request.getRequestHeaders().getFirst(CONTENT_LENGTH);
String transferEncodingString = request.getRequestHeaders().getLast(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(new IOException(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(httpClientExchange);
if (!hasContent) {
//if there is no content we flush the response channel.
//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);
}
}));
}
} catch (IOException e) {
handleError(e);
}
} else if (!sinkChannel.isWriteResumed()) {
try {
//TODO: this needs some more thought
if (!sinkChannel.flush()) {
sinkChannel.setWriteListener(new ChannelListener<ConduitStreamSinkChannel>() {
@Override
public void handleEvent(ConduitStreamSinkChannel channel) {
try {
if (channel.flush()) {
channel.suspendWrites();
}
} catch (IOException e) {
handleError(e);
}
}
});
sinkChannel.resumeWrites();
}
} catch (IOException e) {
handleError(e);
}
}