final HeaderMap responseHeaders = exchange.getResponseHeaders();
// test to see if we're still persistent
String connection = responseHeaders.getFirst(Headers.CONNECTION);
boolean stillPersistent = requestLooksPersistent && exchange.isPersistent() && (connection == null || !HttpString.tryFromString(connection).equals(Headers.CLOSE));
HttpString transferEncoding = Headers.IDENTITY;
final String transferEncodingHeader = responseHeaders.getLast(Headers.TRANSFER_ENCODING);
final String contentLengthHeader = responseHeaders.getFirst(Headers.CONTENT_LENGTH);
if (transferEncodingHeader != null) {
if (exchange.isHttp11()) {
transferEncoding = new HttpString(transferEncodingHeader);
} else {
// RFC 2616 3.6 last paragraph
responseHeaders.remove(Headers.TRANSFER_ENCODING);
}
} else if (exchange.isHttp11() && contentLengthHeader == null) {
//if we have a HTTP 1.1 request with no transfer encoding and no content length
//then we default to chunked, to enable persistent connections to work
responseHeaders.put(Headers.TRANSFER_ENCODING, Headers.CHUNKED.toString());
transferEncoding = Headers.CHUNKED;
}
StreamSinkConduit wrappedConduit;
final int code = exchange.getResponseCode();
if (exchange.getRequestMethod().equals(Methods.HEAD) || (100 <= code && code <= 199) || code == 204 || code == 304) {
final ConduitListener<StreamSinkConduit> finishListener = stillPersistent ? terminateResponseListener(exchange) : null;
if (code == 101 && contentLengthHeader != null) {
// add least for websocket upgrades we can have a content length
final long contentLength;
try {
contentLength = Long.parseLong(contentLengthHeader);
// fixed-length response
wrappedConduit = new FixedLengthStreamSinkConduit(channel, contentLength, true, !stillPersistent, finishListener);
} catch (NumberFormatException e) {
// assume that the response is unbounded, but forbid persistence (this will cause subsequent requests to fail when they write their replies)
stillPersistent = false;
wrappedConduit = new FinishableStreamSinkConduit(channel, terminateResponseListener(exchange));
}
} else {
wrappedConduit = new FixedLengthStreamSinkConduit(channel, 0L, true, !stillPersistent, finishListener);
}
} else if (!transferEncoding.equals(Headers.IDENTITY)) {
final ConduitListener<StreamSinkConduit> finishListener = stillPersistent ? terminateResponseListener(exchange) : null;
wrappedConduit = new ChunkedStreamSinkConduit(channel, true, !stillPersistent, finishListener, exchange);
} else if (contentLengthHeader != null) {
final long contentLength;
try {