下面列出了怎么用 io.netty.handler.codec.http.HttpHeaders 的API类实例代码及写法,或者点击链接到github查看源代码。
@Test
public void should_return_bad_request_when_chunked_request_exceeds_endpoint_overridden_configured_max_request_size() throws Exception {
NettyHttpClientRequestBuilder request = request()
.withMethod(HttpMethod.POST)
.withUri(BasicEndpointWithRequestSizeValidationOverride.MATCHING_PATH)
.withPaylod(generatePayloadOfSizeInBytes(BasicEndpointWithRequestSizeValidationOverride.MAX_REQUEST_SIZE + 1))
.withHeader(HttpHeaders.Names.TRANSFER_ENCODING, CHUNKED);
// when
NettyHttpClientResponse serverResponse = request.execute(serverConfig.endpointsPort(),
incompleteCallTimeoutMillis);
// then
assertThat(serverResponse.statusCode).isEqualTo(HttpResponseStatus.BAD_REQUEST.code());
assertBadRequestErrorMessageAndMetadata(serverResponse.payload);
}
/**
* Creates a {@link NettyRequest} with the given parameters.
* @param httpMethod the {@link HttpMethod} desired.
* @param uri the URI desired.
* @param headers {@link HttpHeaders} that need to be a part of the request.
* @param channel the {@link Channel} that the request arrived over.
* @return {@link NettyRequest} encapsulating a {@link HttpRequest} with the given parameters.
* @throws RestServiceException if the {@code httpMethod} is not recognized by {@link NettyRequest}.
*/
private NettyRequest createNettyRequest(HttpMethod httpMethod, String uri, HttpHeaders headers, Channel channel)
throws RestServiceException {
MetricRegistry metricRegistry = new MetricRegistry();
RestRequestMetricsTracker.setDefaults(metricRegistry);
HttpRequest httpRequest = new DefaultHttpRequest(HttpVersion.HTTP_1_1, httpMethod, uri, false);
if (headers != null) {
httpRequest.headers().set(headers);
}
NettyRequest nettyRequest =
new NettyRequest(httpRequest, channel, new NettyMetrics(metricRegistry), BLACKLISTED_QUERY_PARAM_SET);
assertEquals("Auto-read is in an invalid state",
(!httpMethod.equals(HttpMethod.POST) && !httpMethod.equals(HttpMethod.PUT))
|| NettyRequest.bufferWatermark <= 0, channel.config().isAutoRead());
return nettyRequest;
}
/**
* Method to easily create a request.
* @param httpMethod the {@link HttpMethod} desired.
* @param uri string representation of the desired URI.
* @param headers any associated headers as a {@link HttpHeaders} object. Can be null.
* @param content the content that accompanies the request. Can be null.
* @return A {@link FullHttpRequest} object that defines the request required by the input.
*/
private FullHttpRequest buildRequest(HttpMethod httpMethod, String uri, HttpHeaders headers, ByteBuffer content) {
ByteBuf contentBuf;
if (content != null) {
contentBuf = Unpooled.wrappedBuffer(content);
} else {
contentBuf = Unpooled.buffer(0);
}
FullHttpRequest httpRequest = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, httpMethod, uri, contentBuf);
if (headers != null) {
httpRequest.headers().set(headers);
}
if (HttpMethod.POST.equals(httpMethod) && !HttpUtil.isContentLengthSet(httpRequest)) {
HttpUtil.setTransferEncodingChunked(httpRequest, true);
}
return httpRequest;
}
/**
* Add basic authentication headers to a {@link HttpRequest}.
*
* The given information is Base64 encoded and the authorization header is set appropriately. Since this needs
* to be done for every request, it is refactored out.
*
* @param ctx the handler context.
* @param request the request where the header should be added.
* @param user the username for auth.
* @param password the password for auth.
*/
public static void addHttpBasicAuth(final ChannelHandlerContext ctx, final HttpRequest request, final String user,
final String password) {
// if both user and password are null or empty, don't add http basic auth
// this is usually the case when certificate auth is used.
if ((user == null || user.isEmpty()) && (password == null || password.isEmpty())) {
return;
}
final String pw = password == null ? "" : password;
ByteBuf raw = ctx.alloc().buffer(user.length() + pw.length() + 1);
raw.writeBytes((user + ":" + pw).getBytes(CHARSET));
ByteBuf encoded = Base64.encode(raw, false);
request.headers().add(HttpHeaders.Names.AUTHORIZATION, "Basic " + encoded.toString(CHARSET));
encoded.release();
raw.release();
}
/**
* Verifies either the expected request headers are found or not found (based on the parameter passed) in the
* public access log entry
* @param logEntry the public access log entry
* @param headers expected headers
* @param httpMethod HttpMethod type
* @param expected, true if the headers are expected, false otherwise
*/
private void verifyPublicAccessLogEntryForRequestHeaders(String logEntry, HttpHeaders headers, HttpMethod httpMethod,
boolean expected) {
Iterator<Map.Entry<String, String>> itr = headers.iteratorAsString();
while (itr.hasNext()) {
Map.Entry<String, String> entry = itr.next();
if (!entry.getKey().startsWith(NOT_LOGGED_HEADER_KEY) && !entry.getKey()
.startsWith(EchoMethodHandler.RESPONSE_HEADER_KEY_PREFIX)) {
if (httpMethod == HttpMethod.GET && !entry.getKey().equalsIgnoreCase(HttpHeaderNames.CONTENT_TYPE.toString())) {
String subString = "[" + entry.getKey() + "=" + entry.getValue() + "]";
boolean actual = logEntry.contains(subString);
if (expected) {
Assert.assertTrue("Public Access log entry does not have expected header " + entry.getKey(), actual);
} else {
Assert.assertFalse("Public Access log entry has unexpected header " + entry.getKey(), actual);
}
}
}
}
}
/**
* Retrieves the host and, optionally, the port from the specified request's Host header.
*
* @param httpRequest HTTP request
* @param includePort when true, include the port
* @return the host and, optionally, the port specified in the request's Host header
*/
private static String parseHostHeader(HttpRequest httpRequest, boolean includePort) {
// this header parsing logic is adapted from ClientToProxyConnection#identifyHostAndPort.
List<String> hosts = httpRequest.headers().getAll(HttpHeaders.Names.HOST);
if (!hosts.isEmpty()) {
String hostAndPort = hosts.get(0);
if (includePort) {
return hostAndPort;
} else {
HostAndPort parsedHostAndPort = HostAndPort.fromString(hostAndPort);
return parsedHostAndPort.getHost();
}
} else {
return null;
}
}
@Test
public void testFilenameContainingSemicolon() throws Exception {
final String boundary = "dLV9Wyq26L_-JQxk6ferf-RT153LhOO";
final DefaultFullHttpRequest req = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST,
"http://localhost");
req.headers().add(HttpHeaders.Names.CONTENT_TYPE, "multipart/form-data; boundary=" + boundary);
// Force to use memory-based data.
final DefaultHttpDataFactory inMemoryFactory = new DefaultHttpDataFactory(false);
final String data = "asdf";
final String filename = "tmp;0.txt";
final String body =
"--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\"file\"; filename=\"" + filename + "\"\r\n" +
"Content-Type: image/gif\r\n" +
"\r\n" +
data + "\r\n" +
"--" + boundary + "--\r\n";
req.content().writeBytes(body.getBytes(CharsetUtil.UTF_8.name()));
// Create decoder instance to test.
final HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(inMemoryFactory, req);
assertFalse(decoder.getBodyHttpDatas().isEmpty());
decoder.destroy();
}
@Override
public void sendResponse(FullHttpRequest req, ChannelHandlerContext ctx) throws Exception {
counter.inc();
byte[] content = null;
try(InputStream is = FallbackResponder.class.getClassLoader().getResourceAsStream(resource)) {
content = IOUtils.toByteArray(is);
}
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
HttpHeaders.setContentLength(response, content.length);
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, MediaType.APPLICATION_XML_UTF_8.toString());
response.content().writeBytes(content);
ctx.write(response);
ChannelFuture future = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
future.addListener(ChannelFutureListener.CLOSE);
}
private boolean writeResponse(HttpObject currentObj, ChannelHandlerContext ctx) {
// Decide whether to close the connection or not.
boolean keepAlive = HttpHeaders.isKeepAlive(request);
// Build the response object.
FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1,
currentObj.getDecoderResult().isSuccess() ? OK : BAD_REQUEST, Unpooled.copiedBuffer(
apiResult.toString(), CharsetUtil.UTF_8));
response.headers().set(CONTENT_TYPE, "application/json; charset=UTF-8");
if (keepAlive) {
// Add 'Content-Length' header only for a keep-alive connection.
response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
// Add keep alive header as per:
// -
// http://www.w3.org/Protocols/HTTP/1.1/draft-ietf-http-v11-spec-01.html#Connection
response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
}
// Write the response.
ctx.write(response);
return keepAlive;
}
@Override
public void beforeMethod(final EnhancedInstance objInst,
final Method method,
final Object[] allArguments,
final Class<?>[] argumentsTypes,
final MethodInterceptResult result) throws Throwable {
CarrierItem next = (CarrierItem) objInst.getSkyWalkingDynamicField();
if (next != null) {
HttpHeaders headers = (HttpHeaders) allArguments[0];
while (next.hasNext()) {
next = next.next();
headers.remove(next.getHeadKey());
headers.set(next.getHeadKey(), next.getHeadValue());
}
}
}
private static final FullHttpResponse http_200(String result) {
FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
Unpooled.wrappedBuffer(result.getBytes()));
HttpHeaders httpHeaders = response.headers();
httpHeaders.set(HttpHeaders.Names.CONTENT_TYPE, "text/plain");
httpHeaders.set(HttpHeaders.Names.CONTENT_LENGTH, response.content().readableBytes());
return response;
}
protected void removeTransferEncodingChunked(HttpHeaders headers) {
if (headers.contains(TRANSFER_ENCODING, CHUNKED, true)) {
List<String> transferEncodingsMinusChunked =
headers.getAll(TRANSFER_ENCODING).stream()
.filter(encoding -> !CHUNKED.equalsIgnoreCase(encoding))
.collect(Collectors.toList());
if (transferEncodingsMinusChunked.isEmpty()) {
headers.remove(TRANSFER_ENCODING);
}
else {
headers.set(TRANSFER_ENCODING, transferEncodingsMinusChunked);
}
}
}
@Test
public void contentTypeJsonMixedCaseShouldBeValid() {
HttpHeaders mockHeaders = mock(HttpHeaders.class);
when(mockHeaders.get(HttpHeaders.Names.CONTENT_TYPE)).thenReturn("aPpLiCaTiOn/JSON");
assertTrue("content-type aPpLiCaTiOn/JSON should be valid", mediaTypeChecker.isContentTypeValid(mockHeaders));
}
/**
* <p>
* Handle the web socket handshake for the web socket specification <a href=
* "http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-08">HyBi version 8 to 10</a>. Version 8, 9 and
* 10 share the same wire protocol.
* </p>
*
* <p>
* Browser request to the server:
* </p>
*
* <pre>
* GET /chat HTTP/1.1
* Host: server.example.com
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
* Sec-WebSocket-Origin: http://example.com
* Sec-WebSocket-Protocol: chat, superchat
* Sec-WebSocket-Version: 8
* </pre>
*
* <p>
* Server response:
* </p>
*
* <pre>
* HTTP/1.1 101 Switching Protocols
* Upgrade: websocket
* Connection: Upgrade
* Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
* Sec-WebSocket-Protocol: chat
* </pre>
*/
@Override
protected FullHttpResponse newHandshakeResponse(FullHttpRequest req, HttpHeaders headers) {
FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, HttpResponseStatus.SWITCHING_PROTOCOLS);
if (headers != null) {
res.headers().add(headers);
}
CharSequence key = req.headers().get(HttpHeaderNames.SEC_WEBSOCKET_KEY);
if (key == null) {
throw new WebSocketHandshakeException("not a WebSocket request: missing key");
}
String acceptSeed = key + WEBSOCKET_08_ACCEPT_GUID;
byte[] sha1 = WebSocketUtil.sha1(acceptSeed.getBytes(CharsetUtil.US_ASCII));
String accept = WebSocketUtil.base64(sha1);
if (logger.isDebugEnabled()) {
logger.debug("WebSocket version 08 server handshake key: {}, response: {}", key, accept);
}
res.headers().add(HttpHeaderNames.UPGRADE, HttpHeaderValues.WEBSOCKET);
res.headers().add(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE);
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_ACCEPT, accept);
String subprotocols = req.headers().get(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL);
if (subprotocols != null) {
String selectedSubprotocol = selectSubprotocol(subprotocols);
if (selectedSubprotocol == null) {
if (logger.isDebugEnabled()) {
logger.debug("Requested subprotocol(s) not supported: {}", subprotocols);
}
} else {
res.headers().add(HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL, selectedSubprotocol);
}
}
return res;
}
@VisibleForTesting
void stripXFFHeaders(HttpRequest req)
{
HttpHeaders headers = req.headers();
for (AsciiString headerName : HEADERS_TO_STRIP) {
headers.remove(headerName);
}
}
public static void trySaveRequest(final HttpServerExchange exchange, final byte[] buffer, int length) {
int maxSize = exchange.getUndertowOptions().get(UndertowOptions.MAX_BUFFERED_REQUEST_SIZE, UndertowOptions.DEFAULT_MAX_BUFFERED_REQUEST_SIZE);
if (maxSize > 0) {
if (length > maxSize) {
UndertowLogger.REQUEST_LOGGER.debugf("Request to %s was to large to save", exchange.getRequestURI());
return;//failed to save the request, we just return
}
//TODO: we should really be used pooled buffers
//TODO: we should probably limit the number of saved requests at any given time
HttpHeaders headers = new DefaultHttpHeaders();
for (String entry : exchange.getRequestHeaderNames()) {
if (entry.equals(HttpHeaderNames.CONTENT_LENGTH) ||
entry.equals(HttpHeaderNames.TRANSFER_ENCODING) ||
entry.equals(HttpHeaderNames.CONNECTION)) {
continue;
}
headers.set(entry, exchange.getRequestHeaders(entry));
}
SavedRequest request = new SavedRequest(buffer, length, exchange.getRequestMethod(), exchange.getRelativePath(), headers);
final ServletRequestContext sc = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
HttpSessionImpl session = sc.getCurrentServletContext().getSession(exchange, true);
Session underlyingSession;
if (System.getSecurityManager() == null) {
underlyingSession = session.getSession();
} else {
underlyingSession = AccessController.doPrivileged(new HttpSessionImpl.UnwrapSessionAction(session));
}
underlyingSession.setAttribute(SESSION_KEY, request);
}
}
public static @Nullable HttpHeaders extractTrailingHeadersIfPossible(@Nullable HttpRequest request) {
if (!(request instanceof LastHttpContent)) {
return null;
}
return ((LastHttpContent) request).trailingHeaders();
}
/**
* Chunked encoding is an HTTP 1.1 feature, but sometimes we get a chunked
* response that reports its HTTP version as 1.0. In this case, we change it
* to 1.1.
*
* @param httpResponse
*/
private void fixHttpVersionHeaderIfNecessary(HttpResponse httpResponse) {
String te = httpResponse.headers().get(
HttpHeaders.Names.TRANSFER_ENCODING);
if (StringUtils.isNotBlank(te)
&& te.equalsIgnoreCase(HttpHeaders.Values.CHUNKED)) {
if (httpResponse.getProtocolVersion() != HttpVersion.HTTP_1_1) {
LOG.debug("Fixing HTTP version.");
httpResponse.setProtocolVersion(HttpVersion.HTTP_1_1);
}
}
}
@DataProvider(value = {
"-1",
"0",
"1",
"2",
"4"
}, splitBy = "\\|")
@Test
public void synchronizeAndSetupResponseInfoAndFirstChunk_shouldSetCookieHeadersWhenCookiesPresent(int numberOfCookies) {
// given
actualResponseObject = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
when(requestInfo.isKeepAliveRequested()).thenReturn(false);
Set<Cookie> cookies = createCookies(numberOfCookies);
responseInfo.setCookies(cookies);
// when
responseSender.synchronizeAndSetupResponseInfoAndFirstChunk(responseInfo, actualResponseObject, requestInfo, ctx);
// then
List<String> setCookieHeaderValues = actualResponseObject.headers().getAll(HttpHeaders.Names.SET_COOKIE);
if (numberOfCookies > 0) {
assertThat(setCookieHeaderValues).isNotEmpty();
assertThat(setCookieHeaderValues.size()).isEqualTo(numberOfCookies);
} else {
assertThat(setCookieHeaderValues).isEmpty();
}
if (!setCookieHeaderValues.isEmpty()) {
DefaultCookie[] originalCookies = cookies.toArray(new DefaultCookie[cookies.size()]);
for (int x = 0; x < numberOfCookies; x++) {
assertThat(setCookieHeaderValues.get(x)).startsWith(originalCookies[x].name() + "=" + originalCookies[x].value());
assertThat(setCookieHeaderValues.get(x)).contains("Max-Age=" + originalCookies[x].maxAge());
if (originalCookies[x].isHttpOnly()) {
assertThat(setCookieHeaderValues.get(x)).contains("HTTPOnly");
}
}
}
}
public void add(String name, Path value, String fileName, final HttpHeaders headers) {
Deque<FormValue> values = this.values.get(name);
if (values == null) {
this.values.put(name, values = new ArrayDeque<>(1));
}
values.add(new FormValueImpl(value, fileName, headers));
if (values.size() > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
if (++valueCount > maxValues) {
throw new RuntimeException(UndertowMessages.MESSAGES.tooManyParameters(maxValues));
}
}
private static HttpHeaders generateDefaultResponseHeaders(RequestInfo<?> request) {
String base64EncodedPayload = base64Encode(request.getRawContentBytes());
return new DefaultHttpHeaders()
.set(RECEIVED_PAYLOAD_BYTES_AS_BASE64_RESPONSE_HEADER_KEY, base64EncodedPayload)
.set(RECEIVED_CONTENT_ENCODING_HEADER, String.valueOf(request.getHeaders().get(CONTENT_ENCODING)))
.set(RECEIVED_CONTENT_LENGTH_HEADER, String.valueOf(request.getHeaders().get(CONTENT_LENGTH)))
.set(RECEIVED_TRANSFER_ENCODING_HEADER, String.valueOf(request.getHeaders().get(TRANSFER_ENCODING)));
}
public static HttpRequest httpRequest(HttpMethod method, String url, String body) {
ByteBuf content = Unpooled.copiedBuffer(body.getBytes(Charset.forName("US-ASCII")));
HttpRequest request = new DefaultFullHttpRequest(HTTP_1_1,
method,
url,
content);
HttpHeaders.setContentLength(request, content.writerIndex());
return request;
}
@BeforeClass
public static void setup() {
final BlockingHandler blockingHandler = new BlockingHandler();
DefaultServer.setRootHandler(blockingHandler);
blockingHandler.setRootHandler(new HttpHandler() {
@Override
public void handleRequest(final HttpServerExchange exchange) {
HttpHeaders trailers = new DefaultHttpHeaders();
exchange.putAttachment(HttpAttachments.RESPONSE_TRAILERS, trailers);
trailers.set("foo", "fooVal");
trailers.set("bar", "barVal");
exchange.writeAsync(message);
}
});
}
public HttpRequest adapt(SdkHttpRequest sdkRequest) {
HttpMethod method = toNettyHttpMethod(sdkRequest.method());
HttpHeaders headers = new DefaultHttpHeaders();
String uri = encodedPathAndQueryParams(sdkRequest);
// All requests start out as HTTP/1.1 objects, even if they will
// ultimately be sent over HTTP2. Conversion to H2 is handled at a
// later stage if necessary; see HttpToHttp2OutboundAdapter.
DefaultHttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, method, uri, headers);
addHeadersToRequest(request, sdkRequest);
return request;
}
@Test
public void compressionServerDefaultClientDefaultIsNone() {
HttpServer server = HttpServer.create()
.port(0);
DisposableServer runningServer =
server.handle((in, out) -> out.sendString(Mono.just("reply")))
.wiretap(true)
.bindNow(Duration.ofSeconds(10));
HttpClient client = HttpClient.create()
.remoteAddress(runningServer::address)
.wiretap(true);
Tuple2<String, HttpHeaders> resp =
client.get()
.uri("/test")
.response((res, buf) -> buf.asString()
.zipWith(Mono.just(res.responseHeaders())))
.blockFirst();
assertThat(resp).isNotNull();
assertThat(resp.getT2().get("Content-Encoding")).isNull();
assertThat(resp.getT1()).isEqualTo("reply");
runningServer.dispose();
runningServer.onDispose()
.block();
}
private static HttpClientResponse<ByteBuf> response(
@NotNull final ByteBuf content,
@NotNull final Action1<HttpHeaders> headerTransformer
) {
final DefaultHttpResponse nettyResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
headerTransformer.call(nettyResponse.headers());
final UnicastContentSubject<ByteBuf> subject = UnicastContentSubject.create(1000, TimeUnit.MILLISECONDS);
subject.onNext(content);
return new HttpClientResponse<>(
nettyResponse,
subject
);
}
@Override
public String getHeader(HttpServerRequest request, String name) {
try {
final HttpHeaders headers = request.requestHeaders();
if (headers != null) {
return headers.get(name);
}
} catch (Exception ignored) {
}
return null;
}
/**
* Returns the size of the headers, including the 2 CRLFs at the end of the header block.
*
* @param headers headers to size
* @return length of the headers, in bytes
*/
public static long getHeaderSize(HttpHeaders headers) {
// +2 for ': ', +2 for new line
return headers.entries().stream()
.mapToLong(header -> header.getKey().length() + header.getValue().length() + 4)
.sum();
}
/**
* Replaces an HTTP entity body with the specified binary contents.
* TODO: Currently this method only works for FullHttpMessages, since it must modify the Content-Length header; determine if this may be applied to chunked messages as well
*
* @param message the HTTP message to manipulate
* @param newBinaryContents the new entity body contents
*/
public static void replaceBinaryHttpEntityBody(FullHttpMessage message, byte[] newBinaryContents) {
message.content().resetWriterIndex();
// resize the buffer if needed, since the new message may be longer than the old one
message.content().ensureWritable(newBinaryContents.length, true);
message.content().writeBytes(newBinaryContents);
// update the Content-Length header, since the size may have changed
message.headers().set(HttpHeaders.Names.CONTENT_LENGTH, newBinaryContents.length);
}
/**
* Determine whether or not the client connection should be closed.
*
* @param req
* @param res
* @param httpObject
* @return
*/
private boolean shouldCloseClientConnection(HttpRequest req,
HttpResponse res, HttpObject httpObject) {
if (ProxyUtils.isChunked(res)) {
// If the response is chunked, we want to return false unless it's
// the last chunk. If it is the last chunk, then we want to pass
// through to the same close semantics we'd otherwise use.
if (httpObject != null) {
if (!ProxyUtils.isLastChunk(httpObject)) {
String uri = null;
if (req != null) {
uri = req.getUri();
}
LOG.debug("Not closing client connection on middle chunk for {}", uri);
return false;
} else {
LOG.debug("Handling last chunk. Using normal client connection closing rules.");
}
}
}
if (!HttpHeaders.isKeepAlive(req)) {
LOG.debug("Closing client connection since request is not keep alive: {}", req);
// Here we simply want to close the connection because the
// client itself has requested it be closed in the request.
return true;
}
// ignore the response's keep-alive; we can keep this client connection open as long as the client allows it.
LOG.debug("Not closing client connection for request: {}", req);
return false;
}