diff --git a/reactor-netty-http/src/main/java/reactor/netty/http/HttpOperations.java b/reactor-netty-http/src/main/java/reactor/netty/http/HttpOperations.java index 9ff84eb1a7..087dabe4b9 100644 --- a/reactor-netty-http/src/main/java/reactor/netty/http/HttpOperations.java +++ b/reactor-netty-http/src/main/java/reactor/netty/http/HttpOperations.java @@ -118,19 +118,7 @@ public NettyOutbound send(Publisher source) { return new PostHeadersNettyOutbound(((Mono) source) .flatMap(b -> { if (markSentHeaderAndBody(b)) { - HttpMessage msg; - if (HttpUtil.getContentLength(outboundHttpMessage(), -1) == 0 || - isContentAlwaysEmpty()) { - if (log.isDebugEnabled()) { - log.debug(format(channel(), "Dropped HTTP content, since response has " + - "1. [Content-Length: 0] or 2. there must be no content: {}"), b); - } - b.release(); - msg = newFullBodyMessage(Unpooled.EMPTY_BUFFER); - } - else { - msg = newFullBodyMessage(b); - } + HttpMessage msg = prepareHttpMessage(b); try { afterMarkSentHeaders(); @@ -161,18 +149,7 @@ public NettyOutbound sendObject(Object message) { ByteBuf b = (ByteBuf) message; return new PostHeadersNettyOutbound(FutureMono.deferFuture(() -> { if (markSentHeaderAndBody(b)) { - HttpMessage msg; - if (HttpUtil.getContentLength(outboundHttpMessage(), -1) == 0) { - if (log.isDebugEnabled()) { - log.debug(format(channel(), "Dropped HTTP content, " + - "since response has Content-Length: 0 {}"), b); - } - b.release(); - msg = newFullBodyMessage(Unpooled.EMPTY_BUFFER); - } - else { - msg = newFullBodyMessage(b); - } + HttpMessage msg = prepareHttpMessage(b); try { afterMarkSentHeaders(); @@ -437,6 +414,24 @@ else if (!SCHEME_PATTERN.matcher(tempUri).matches()) { */ protected abstract HttpMessage outboundHttpMessage(); + HttpMessage prepareHttpMessage(ByteBuf buffer) { + HttpMessage msg; + if (HttpUtil.getContentLength(outboundHttpMessage(), -1) == 0 || + isContentAlwaysEmpty()) { + if (log.isDebugEnabled()) { + log.debug(format(channel(), "Dropped HTTP content, since response has " + + "1. [Content-Length: 0] or 2. there must be no content: {}"), buffer); + } + buffer.release(); + msg = newFullBodyMessage(Unpooled.EMPTY_BUFFER); + } + else { + msg = newFullBodyMessage(buffer); + } + + return msg; + } + @SuppressWarnings("rawtypes") final static AtomicIntegerFieldUpdater HTTP_STATE = AtomicIntegerFieldUpdater.newUpdater(HttpOperations.class, diff --git a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java index 7259373c56..ddcad19758 100644 --- a/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java +++ b/reactor-netty-http/src/main/java/reactor/netty/http/server/HttpServerOperations.java @@ -680,8 +680,12 @@ protected void beforeMarkSentHeaders() { @Override protected boolean isContentAlwaysEmpty() { int code = status().code(); - return HttpResponseStatus.NOT_MODIFIED.code() == code || - HttpResponseStatus.NO_CONTENT.code() == code || + if (HttpResponseStatus.NOT_MODIFIED.code() == code) { + responseHeaders.remove(HttpHeaderNames.TRANSFER_ENCODING) + .remove(HttpHeaderNames.CONTENT_LENGTH); + return true; + } + return HttpResponseStatus.NO_CONTENT.code() == code || HttpResponseStatus.RESET_CONTENT.code() == code; } diff --git a/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java b/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java index 61a16ad1b6..5e2f6fca9c 100644 --- a/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java +++ b/reactor-netty-http/src/test/java/reactor/netty/http/HttpResponseStatusCodesHandlingTests.java @@ -15,6 +15,7 @@ */ package reactor.netty.http; +import io.netty.buffer.Unpooled; import io.netty.handler.codec.http.HttpHeaderNames; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; @@ -33,6 +34,7 @@ import reactor.netty.http.server.HttpServer; import reactor.test.StepVerifier; +import java.nio.charset.Charset; import java.time.Duration; import java.util.Arrays; import java.util.stream.Stream; @@ -102,9 +104,17 @@ void noContentStatusCodes(HttpProtocol[] serverProtocols, HttpProtocol[] clientP .get("/304-3", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) .sendString(Mono.just("/304-3"))) .get("/304-4", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) - .sendString(Flux.just("/", "304-4"))) + .header(HttpHeaderNames.CONTENT_LENGTH, "6") + .sendString(Mono.just("/304-4"))) .get("/304-5", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) - .send())) + .sendString(Flux.just("/", "304-5"))) + .get("/304-6", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) + .send()) + .get("/304-7", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) + .sendObject(Unpooled.wrappedBuffer("/304-7".getBytes(Charset.defaultCharset())))) + .get("/304-8", (req, res) -> res.status(HttpResponseStatus.NOT_MODIFIED) + .header(HttpHeaderNames.CONTENT_LENGTH, "6") + .sendObject(Unpooled.wrappedBuffer("/304-8".getBytes(Charset.defaultCharset()))))) .bindNow(); HttpClient client = createClient(disposableServer::address).protocol(clientProtocols); @@ -130,6 +140,9 @@ void noContentStatusCodes(HttpProtocol[] serverProtocols, HttpProtocol[] clientP checkResponse("/304-3", client); checkResponse("/304-4", client); checkResponse("/304-5", client); + checkResponse("/304-6", client); + checkResponse("/304-7", client); + checkResponse("/304-8", client); } static void checkResponse(String url, HttpClient client) {