@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()); newExchange.setRequestPath(exchange.getRequestPath()); newExchange.getRequestHeaders().put(Headers.CONNECTION, Headers.KEEP_ALIVE.toString()); newExchange.getRequestHeaders().put(Headers.CONTENT_LENGTH, 0); newExchange.addExchangeCompleteListener( new ExchangeCompletionListener() { @Override public void exchangeEvent(HttpServerExchange exchange, NextListener nextListener) { restoreChannel(state); } }); return newExchange; }
@Override public void handleRequest(final HttpServerExchange exchange) { final HeaderMap requestHeaders = exchange.getRequestHeaders(); boolean persistentConnection; final boolean hasConnectionHeader = requestHeaders.contains(Headers.CONNECTION); final boolean hasTransferEncoding = requestHeaders.contains(Headers.TRANSFER_ENCODING); final boolean hasContentLength = requestHeaders.contains(Headers.CONTENT_LENGTH); if (exchange.isHttp11()) { persistentConnection = !(hasConnectionHeader && new HttpString(requestHeaders.getFirst(Headers.CONNECTION)).equals(Headers.CLOSE)); } else if (exchange.isHttp10()) { persistentConnection = false; if (hasConnectionHeader) { for (String value : requestHeaders.get(Headers.CONNECTION)) { if (Headers.KEEP_ALIVE.equals(new HttpString(value))) { persistentConnection = true; break; } } } } else { log.trace("Connection not persistent"); persistentConnection = false; } HttpString transferEncoding = Headers.IDENTITY; if (hasTransferEncoding) { transferEncoding = new HttpString(requestHeaders.getLast(Headers.TRANSFER_ENCODING)); } if (hasTransferEncoding && !transferEncoding.equals(Headers.IDENTITY)) { exchange.addRequestWrapper(chunkedStreamSourceChannelWrapper()); } else if (hasContentLength) { final long contentLength; try { contentLength = Long.parseLong(requestHeaders.get(Headers.CONTENT_LENGTH).getFirst()); } catch (NumberFormatException e) { log.trace("Invalid request due to unparsable content length"); // content length is bad; invalid request exchange.setResponseCode(400); exchange.endExchange(); return; } if (contentLength == 0L) { log.trace("No content, starting next request"); // no content - immediately start the next request, returning an empty stream for this one exchange.addRequestWrapper(emptyStreamSourceChannelWrapper()); exchange.terminateRequest(); } else { // fixed-length content - add a wrapper for a fixed-length stream exchange.addRequestWrapper(fixedLengthStreamSourceChannelWrapper(contentLength)); } } else if (hasTransferEncoding) { if (transferEncoding.equals(Headers.IDENTITY)) { log.trace("Connection not persistent (no content length and identity transfer encoding)"); // make it not persistent persistentConnection = false; } } else if (persistentConnection) { // no content - immediately start the next request, returning an empty stream for this one exchange.terminateRequest(); exchange.addRequestWrapper(emptyStreamSourceChannelWrapper()); } exchange.setPersistent(persistentConnection); // now the response wrapper, to add in the appropriate connection control headers exchange.addResponseWrapper(responseWrapper(persistentConnection)); HttpHandlers.executeHandler(next, exchange); }