Skip to content

Commit 3f8a10c

Browse files
NadChelpoutsma
authored andcommitted
Remove Content-Type when body is empty
Closes gh-32622 See gh-32620
1 parent adc7f73 commit 3f8a10c

File tree

2 files changed

+53
-18
lines changed

2 files changed

+53
-18
lines changed

spring-web/src/main/java/org/springframework/http/codec/EncoderHttpMessageWriter.java

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,20 +16,15 @@
1616

1717
package org.springframework.http.codec;
1818

19-
import java.util.List;
20-
import java.util.Map;
21-
2219
import org.apache.commons.logging.Log;
2320
import org.reactivestreams.Publisher;
24-
import reactor.core.publisher.Flux;
25-
import reactor.core.publisher.Mono;
26-
2721
import org.springframework.core.ResolvableType;
2822
import org.springframework.core.codec.AbstractEncoder;
2923
import org.springframework.core.codec.Encoder;
3024
import org.springframework.core.codec.Hints;
3125
import org.springframework.core.io.buffer.DataBuffer;
3226
import org.springframework.core.io.buffer.DataBufferUtils;
27+
import org.springframework.http.HttpHeaders;
3328
import org.springframework.http.HttpLogging;
3429
import org.springframework.http.MediaType;
3530
import org.springframework.http.ReactiveHttpOutputMessage;
@@ -38,6 +33,11 @@
3833
import org.springframework.lang.Nullable;
3934
import org.springframework.util.Assert;
4035
import org.springframework.util.StringUtils;
36+
import reactor.core.publisher.Flux;
37+
import reactor.core.publisher.Mono;
38+
39+
import java.util.List;
40+
import java.util.Map;
4141

4242
/**
4343
* {@code HttpMessageWriter} that wraps and delegates to an {@link Encoder}.
@@ -127,6 +127,7 @@ public Mono<Void> write(Publisher<? extends T> inputStream, ResolvableType eleme
127127
return body
128128
.singleOrEmpty()
129129
.switchIfEmpty(Mono.defer(() -> {
130+
message.getHeaders().remove(HttpHeaders.CONTENT_TYPE);
130131
message.getHeaders().setContentLength(0);
131132
return message.setComplete().then(Mono.empty());
132133
}))

spring-web/src/test/java/org/springframework/http/codec/EncoderHttpMessageWriterTests.java

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,31 +16,36 @@
1616

1717
package org.springframework.http.codec;
1818

19-
import java.lang.reflect.InvocationTargetException;
20-
import java.lang.reflect.Method;
21-
import java.nio.charset.StandardCharsets;
22-
import java.util.Arrays;
23-
import java.util.Collections;
24-
import java.util.List;
25-
import java.util.Map;
26-
2719
import org.junit.jupiter.api.Test;
2820
import org.mockito.ArgumentCaptor;
2921
import org.mockito.Mock;
3022
import org.mockito.junit.jupiter.MockitoSettings;
3123
import org.mockito.quality.Strictness;
32-
import reactor.core.publisher.Flux;
33-
import reactor.core.publisher.Mono;
34-
import reactor.test.StepVerifier;
35-
24+
import org.springframework.core.ResolvableType;
3625
import org.springframework.core.codec.CharSequenceEncoder;
26+
import org.springframework.core.codec.Encoder;
3727
import org.springframework.core.io.buffer.DataBuffer;
3828
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
29+
import org.springframework.http.HttpHeaders;
30+
import org.springframework.http.HttpMethod;
3931
import org.springframework.http.MediaType;
32+
import org.springframework.http.ReactiveHttpOutputMessage;
4033
import org.springframework.util.MimeType;
4134
import org.springframework.util.MimeTypeUtils;
4235
import org.springframework.util.ReflectionUtils;
36+
import org.springframework.web.testfixture.http.client.reactive.MockClientHttpRequest;
4337
import org.springframework.web.testfixture.http.server.reactive.MockServerHttpResponse;
38+
import reactor.core.publisher.Flux;
39+
import reactor.core.publisher.Mono;
40+
import reactor.test.StepVerifier;
41+
42+
import java.lang.reflect.InvocationTargetException;
43+
import java.lang.reflect.Method;
44+
import java.nio.charset.StandardCharsets;
45+
import java.util.Arrays;
46+
import java.util.Collections;
47+
import java.util.List;
48+
import java.util.Map;
4449

4550
import static java.nio.charset.StandardCharsets.ISO_8859_1;
4651
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -199,6 +204,35 @@ void isStreamingMediaType() throws InvocationTargetException, IllegalAccessExcep
199204
assertThat((Boolean) method.invoke(writer, TEXT_HTML)).isFalse();
200205
}
201206

207+
@Test
208+
public void ifBodyPublisherEmpty_noContentTypeHeader() {
209+
Encoder<CharSequence> encoder = CharSequenceEncoder.textPlainOnly();
210+
EncoderHttpMessageWriter<CharSequence> writer = new EncoderHttpMessageWriter<>(encoder);
211+
ReactiveHttpOutputMessage outputMessage = new MockClientHttpRequest(HttpMethod.POST, "/");
212+
Mono<Void> writerMono = writer.write(Mono.empty(), ResolvableType.forClass(String.class),
213+
null, outputMessage, NO_HINTS);
214+
215+
StepVerifier.create(writerMono)
216+
.verifyComplete();
217+
assertThat(outputMessage.getHeaders()).doesNotContainKey(HttpHeaders.CONTENT_TYPE);
218+
}
219+
220+
@Test
221+
public void ifBodyPublisherEmpty_contentLengthZero() {
222+
Encoder<CharSequence> encoder = CharSequenceEncoder.textPlainOnly();
223+
EncoderHttpMessageWriter<CharSequence> writer = new EncoderHttpMessageWriter<>(encoder);
224+
ReactiveHttpOutputMessage outputMessage = new MockClientHttpRequest(HttpMethod.POST, "/");
225+
Mono<Void> writerMono = writer.write(Mono.empty(), ResolvableType.forClass(String.class),
226+
null, outputMessage, NO_HINTS);
227+
228+
StepVerifier.create(writerMono)
229+
.verifyComplete();
230+
List<String> contentLengthValues = outputMessage.getHeaders().get(HttpHeaders.CONTENT_LENGTH);
231+
assertThat(contentLengthValues).hasSize(1);
232+
int contentLength = Integer.parseInt(contentLengthValues.get(0));
233+
assertThat(contentLength).isEqualTo(0);
234+
}
235+
202236
private void configureEncoder(MimeType... mimeTypes) {
203237
configureEncoder(Flux.empty(), mimeTypes);
204238
}

0 commit comments

Comments
 (0)