Skip to content

Commit 8ac39a5

Browse files
committed
ServletServerHttpResponse reflects Content-Type override
Closes gh-25490
1 parent d82cb15 commit 8ac39a5

File tree

2 files changed

+33
-16
lines changed

2 files changed

+33
-16
lines changed

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

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.OutputStream;
2121
import java.util.ArrayList;
2222
import java.util.Collection;
23+
import java.util.Collections;
2324
import java.util.List;
2425

2526
import javax.servlet.http.HttpServletResponse;
@@ -152,20 +153,28 @@ public boolean containsKey(Object key) {
152153
@Override
153154
@Nullable
154155
public String getFirst(String headerName) {
155-
String value = servletResponse.getHeader(headerName);
156-
if (value != null) {
157-
return value;
156+
if (headerName.equalsIgnoreCase(CONTENT_TYPE)) {
157+
// Content-Type is written as an override so check super first
158+
String value = super.getFirst(headerName);
159+
return (value != null ? value : servletResponse.getHeader(headerName));
158160
}
159161
else {
160-
return super.getFirst(headerName);
162+
String value = servletResponse.getHeader(headerName);
163+
return (value != null ? value : super.getFirst(headerName));
161164
}
162165
}
163166

164167
@Override
165168
public List<String> get(Object key) {
166169
Assert.isInstanceOf(String.class, key, "Key must be a String-based header name");
167170

168-
Collection<String> values1 = servletResponse.getHeaders((String) key);
171+
String headerName = (String) key;
172+
if (headerName.equalsIgnoreCase(CONTENT_TYPE)) {
173+
// Content-Type is written as an override so don't merge
174+
return Collections.singletonList(getFirst(headerName));
175+
}
176+
177+
Collection<String> values1 = servletResponse.getHeaders(headerName);
169178
if (headersWritten) {
170179
return new ArrayList<>(values1);
171180
}

spring-web/src/test/java/org/springframework/http/server/ServletServerHttpResponseTests.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2020 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.
@@ -17,7 +17,6 @@
1717
package org.springframework.http.server;
1818

1919
import java.nio.charset.StandardCharsets;
20-
import java.util.Collections;
2120
import java.util.List;
2221

2322
import org.junit.jupiter.api.BeforeEach;
@@ -44,20 +43,20 @@ public class ServletServerHttpResponseTests {
4443

4544

4645
@BeforeEach
47-
public void create() throws Exception {
46+
void create() {
4847
mockResponse = new MockHttpServletResponse();
4948
response = new ServletServerHttpResponse(mockResponse);
5049
}
5150

5251

5352
@Test
54-
public void setStatusCode() throws Exception {
53+
void setStatusCode() {
5554
response.setStatusCode(HttpStatus.NOT_FOUND);
5655
assertThat(mockResponse.getStatus()).as("Invalid status code").isEqualTo(404);
5756
}
5857

5958
@Test
60-
public void getHeaders() throws Exception {
59+
void getHeaders() {
6160
HttpHeaders headers = response.getHeaders();
6261
String headerName = "MyHeader";
6362
String headerValue1 = "value1";
@@ -77,23 +76,32 @@ public void getHeaders() throws Exception {
7776
}
7877

7978
@Test
80-
public void preExistingHeadersFromHttpServletResponse() {
79+
void preExistingHeadersFromHttpServletResponse() {
8180
String headerName = "Access-Control-Allow-Origin";
8281
String headerValue = "localhost:8080";
8382

8483
this.mockResponse.addHeader(headerName, headerValue);
84+
this.mockResponse.setContentType("text/csv");
8585
this.response = new ServletServerHttpResponse(this.mockResponse);
8686

8787
assertThat(this.response.getHeaders().getFirst(headerName)).isEqualTo(headerValue);
88-
assertThat(this.response.getHeaders().get(headerName)).isEqualTo(Collections.singletonList(headerValue));
89-
assertThat(this.response.getHeaders().containsKey(headerName)).isTrue();
90-
assertThat(this.response.getHeaders().getFirst(headerName)).isEqualTo(headerValue);
88+
assertThat(this.response.getHeaders().get(headerName)).containsExactly(headerValue);
89+
assertThat(this.response.getHeaders()).containsKey(headerName);
9190
assertThat(this.response.getHeaders().getAccessControlAllowOrigin()).isEqualTo(headerValue);
9291
}
9392

93+
@Test // gh-25490
94+
void preExistingContentTypeIsOverriddenImmediately() {
95+
this.mockResponse.setContentType("text/csv");
96+
this.response = new ServletServerHttpResponse(this.mockResponse);
97+
this.response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
98+
99+
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON);
100+
}
101+
94102
@Test
95-
public void getBody() throws Exception {
96-
byte[] content = "Hello World".getBytes("UTF-8");
103+
void getBody() throws Exception {
104+
byte[] content = "Hello World".getBytes(StandardCharsets.UTF_8);
97105
FileCopyUtils.copy(content, response.getBody());
98106

99107
assertThat(mockResponse.getContentAsByteArray()).as("Invalid content written").isEqualTo(content);

0 commit comments

Comments
 (0)