Skip to content

Commit b5b115e

Browse files
committed
Fix SSE with indenting serializer in WebMvc.fn
This commit ensures that HTTP headers like "text/event-stream" are correctly forwarded to the converter used in SseServerResponse for proper pretty print handling. Close gh-30277
1 parent 310344c commit b5b115e

File tree

2 files changed

+38
-4
lines changed

2 files changed

+38
-4
lines changed

spring-webmvc/src/main/java/org/springframework/web/servlet/function/SseServerResponse.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
* <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events</a>.
5050
*
5151
* @author Arjen Poutsma
52+
* @author Sebastien Deleuze
5253
* @since 5.3.2
5354
*/
5455
final class SseServerResponse extends AbstractServerResponse {
@@ -91,7 +92,7 @@ protected ModelAndView writeToInternal(HttpServletRequest request, HttpServletRe
9192
}
9293

9394
DefaultAsyncServerResponse.writeAsync(request, response, result);
94-
this.sseConsumer.accept(new DefaultSseBuilder(response, context, result));
95+
this.sseConsumer.accept(new DefaultSseBuilder(response, context, result, this.headers()));
9596
return null;
9697
}
9798

@@ -114,15 +115,19 @@ private static final class DefaultSseBuilder implements SseBuilder {
114115

115116
private final List<HttpMessageConverter<?>> messageConverters;
116117

118+
private final HttpHeaders httpHeaders;
119+
117120
private final StringBuilder builder = new StringBuilder();
118121

119122
private boolean sendFailed;
120123

121124

122-
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult) {
125+
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult,
126+
HttpHeaders httpHeaders) {
123127
this.outputMessage = new ServletServerHttpResponse(response);
124128
this.deferredResult = deferredResult;
125129
this.messageConverters = context.messageConverters();
130+
this.httpHeaders = httpHeaders;
126131
}
127132

128133
@Override
@@ -207,7 +212,7 @@ private void writeObject(Object data) throws IOException {
207212
for (HttpMessageConverter<?> converter : this.messageConverters) {
208213
if (converter.canWrite(dataClass, MediaType.APPLICATION_JSON)) {
209214
HttpMessageConverter<Object> objectConverter = (HttpMessageConverter<Object>) converter;
210-
ServerHttpResponse response = new MutableHeadersServerHttpResponse(this.outputMessage);
215+
ServerHttpResponse response = new MutableHeadersServerHttpResponse(this.outputMessage, this.httpHeaders);
211216
objectConverter.write(data, MediaType.APPLICATION_JSON, response);
212217
this.outputMessage.getBody().write(NL_NL);
213218
this.outputMessage.flush();
@@ -277,9 +282,10 @@ private static final class MutableHeadersServerHttpResponse extends DelegatingSe
277282

278283
private final HttpHeaders mutableHeaders = new HttpHeaders();
279284

280-
public MutableHeadersServerHttpResponse(ServerHttpResponse delegate) {
285+
public MutableHeadersServerHttpResponse(ServerHttpResponse delegate, HttpHeaders headers) {
281286
super(delegate);
282287
this.mutableHeaders.putAll(delegate.getHeaders());
288+
this.mutableHeaders.putAll(headers);
283289
}
284290

285291
@Override

spring-webmvc/src/test/java/org/springframework/web/servlet/function/SseServerResponseTests.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333

3434
/**
3535
* @author Arjen Poutsma
36+
* @author Sebastien Deleuze
3637
*/
3738
class SseServerResponseTests {
3839

@@ -89,6 +90,33 @@ void sendObject() throws Exception {
8990
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
9091
}
9192

93+
@Test
94+
void sendObjectWithPrettyPrint() throws Exception {
95+
Person person = new Person("John Doe", 42);
96+
ServerResponse response = ServerResponse.sse(sse -> {
97+
try {
98+
sse.send(person);
99+
}
100+
catch (IOException ex) {
101+
throw new UncheckedIOException(ex);
102+
}
103+
});
104+
105+
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
106+
converter.setPrettyPrint(true);
107+
ServerResponse.Context context = () -> Collections.singletonList(converter);
108+
109+
ModelAndView mav = response.writeTo(this.mockRequest, this.mockResponse, context);
110+
assertThat(mav).isNull();
111+
112+
String expected = "data:{\n" +
113+
"data: \"name\" : \"John Doe\",\n" +
114+
"data: \"age\" : 42\n" +
115+
"data:}\n" +
116+
"\n";
117+
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
118+
}
119+
92120
@Test
93121
void builder() throws Exception {
94122
ServerResponse response = ServerResponse.sse(sse -> {

0 commit comments

Comments
 (0)