Skip to content

Commit b86c11c

Browse files
committed
Respect existing content-length for HTTP HEAD
Closes gh-23484
1 parent 122e2ca commit b86c11c

File tree

2 files changed

+80
-2
lines changed

2 files changed

+80
-2
lines changed

spring-web/src/main/java/org/springframework/http/server/reactive/HttpHeadResponseDecorator.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
2424

2525
import org.springframework.core.io.buffer.DataBuffer;
2626
import org.springframework.core.io.buffer.DataBufferUtils;
27+
import org.springframework.http.HttpHeaders;
2728

2829
/**
2930
* {@link ServerHttpResponse} decorator for HTTP HEAD requests.
@@ -52,7 +53,11 @@ public final Mono<Void> writeWith(Publisher<? extends DataBuffer> body) {
5253
DataBufferUtils.release(buffer);
5354
return next;
5455
})
55-
.doOnNext(count -> getHeaders().setContentLength(count))
56+
.doOnNext(length -> {
57+
if (length > 0 || getHeaders().getFirst(HttpHeaders.CONTENT_LENGTH) == null) {
58+
getHeaders().setContentLength(length);
59+
}
60+
})
5661
.then();
5762
}
5863

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.http.server.reactive;
17+
18+
import java.nio.charset.StandardCharsets;
19+
20+
import io.netty.buffer.PooledByteBufAllocator;
21+
import org.junit.After;
22+
import org.junit.Test;
23+
import reactor.core.publisher.Flux;
24+
25+
import org.springframework.core.io.buffer.DataBuffer;
26+
import org.springframework.core.io.buffer.LeakAwareDataBufferFactory;
27+
import org.springframework.core.io.buffer.NettyDataBufferFactory;
28+
import org.springframework.mock.http.server.reactive.test.MockServerHttpResponse;
29+
30+
import static org.junit.Assert.assertEquals;
31+
32+
/**
33+
* Unit tests for {@link HttpHeadResponseDecorator}.
34+
* @author Rossen Stoyanchev
35+
*/
36+
public class HttpHeadResponseDecoratorTests {
37+
38+
private final LeakAwareDataBufferFactory bufferFactory =
39+
new LeakAwareDataBufferFactory(new NettyDataBufferFactory(PooledByteBufAllocator.DEFAULT));
40+
41+
private final ServerHttpResponse response =
42+
new HttpHeadResponseDecorator(new MockServerHttpResponse(this.bufferFactory));
43+
44+
45+
@After
46+
public void tearDown() {
47+
this.bufferFactory.checkForLeaks();
48+
}
49+
50+
51+
@Test
52+
public void write() {
53+
Flux<DataBuffer> body = Flux.just(toDataBuffer("data1"), toDataBuffer("data2"));
54+
response.writeWith(body).block();
55+
assertEquals(10, response.getHeaders().getContentLength());
56+
}
57+
58+
@Test // gh-23484
59+
public void writeWithGivenContentLength() {
60+
int length = 15;
61+
this.response.getHeaders().setContentLength(length);
62+
this.response.writeWith(Flux.empty()).block();
63+
assertEquals(length, this.response.getHeaders().getContentLength());
64+
}
65+
66+
67+
private DataBuffer toDataBuffer(String s) {
68+
DataBuffer buffer = this.bufferFactory.allocateBuffer();
69+
buffer.write(s.getBytes(StandardCharsets.UTF_8));
70+
return buffer;
71+
}
72+
73+
}

0 commit comments

Comments
 (0)