Skip to content

Commit 24a113f

Browse files
committed
Ensure headers work with ResponseEntity + reactive body
Issue: SPR-17076
1 parent e21db26 commit 24a113f

File tree

2 files changed

+26
-12
lines changed

2 files changed

+26
-12
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandler.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,12 @@ public void handleReturnValue(@Nullable Object returnValue, MethodParameter retu
144144
else {
145145
emitter = this.reactiveHandler.handleValue(returnValue, returnType, mavContainer, webRequest);
146146
if (emitter == null) {
147-
// Not streaming..
147+
// Not streaming: write headers without committing response..
148+
outputMessage.getHeaders().forEach((headerName, headerValues) -> {
149+
for (String headerValue : headerValues) {
150+
response.addHeader(headerName, headerValue);
151+
}
152+
});
148153
return;
149154
}
150155
}

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ResponseBodyEmitterReturnValueHandlerTests.java

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42,17 +42,10 @@
4242
import org.springframework.web.context.request.async.WebAsyncUtils;
4343
import org.springframework.web.method.support.ModelAndViewContainer;
4444

45-
import static org.junit.Assert.assertEquals;
46-
import static org.junit.Assert.assertFalse;
47-
import static org.junit.Assert.assertNotNull;
48-
import static org.junit.Assert.assertNull;
49-
import static org.junit.Assert.assertTrue;
50-
import static org.mockito.Mockito.any;
51-
import static org.mockito.Mockito.mock;
52-
import static org.mockito.Mockito.times;
53-
import static org.mockito.Mockito.verify;
54-
import static org.springframework.core.ResolvableType.forClassWithGenerics;
55-
import static org.springframework.web.method.ResolvableMethod.on;
45+
import static org.junit.Assert.*;
46+
import static org.mockito.Mockito.*;
47+
import static org.springframework.core.ResolvableType.*;
48+
import static org.springframework.web.method.ResolvableMethod.*;
5649

5750
/**
5851
* Unit tests for ResponseBodyEmitterReturnValueHandler.
@@ -290,6 +283,21 @@ public void responseEntityFlux() throws Exception {
290283
assertEquals("foobarbaz", this.response.getContentAsString());
291284
}
292285

286+
@Test // SPR-17076
287+
public void responseEntityFluxWithCustomHeader() throws Exception {
288+
289+
EmitterProcessor<SimpleBean> processor = EmitterProcessor.create();
290+
ResponseEntity<Flux<SimpleBean>> entity = ResponseEntity.ok().header("x-foo", "bar").body(processor);
291+
ResolvableType bodyType = forClassWithGenerics(Flux.class, SimpleBean.class);
292+
MethodParameter type = on(TestController.class).resolveReturnType(ResponseEntity.class, bodyType);
293+
this.handler.handleReturnValue(entity, type, this.mavContainer, this.webRequest);
294+
295+
assertTrue(this.request.isAsyncStarted());
296+
assertEquals(200, this.response.getStatus());
297+
assertEquals("bar", this.response.getHeader("x-foo"));
298+
assertFalse(this.response.isCommitted());
299+
}
300+
293301

294302
@SuppressWarnings("unused")
295303
private static class TestController {
@@ -312,6 +320,7 @@ private static class TestController {
312320

313321
private ResponseEntity<Flux<String>> h9() { return null; }
314322

323+
private ResponseEntity<Flux<SimpleBean>> h10() { return null; }
315324
}
316325

317326

0 commit comments

Comments
 (0)