Skip to content

Commit 6372c0f

Browse files
committed
Ensure headers work with ResponseEntity + reactive body
Issue: SPR-17076
1 parent 7500b14 commit 6372c0f

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
@@ -43,17 +43,10 @@
4343
import org.springframework.web.context.request.async.WebAsyncUtils;
4444
import org.springframework.web.method.support.ModelAndViewContainer;
4545

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

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

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

295303
@SuppressWarnings("unused")
296304
private static class TestController {
@@ -313,6 +321,7 @@ private static class TestController {
313321

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

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

318327

0 commit comments

Comments
 (0)