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
This commit is contained in:
parent
310344cf61
commit
b5b115e52c
|
@ -49,6 +49,7 @@ import org.springframework.web.servlet.ModelAndView;
|
|||
* <a href="https://www.w3.org/TR/eventsource/">Server-Sent Events</a>.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @author Sebastien Deleuze
|
||||
* @since 5.3.2
|
||||
*/
|
||||
final class SseServerResponse extends AbstractServerResponse {
|
||||
|
@ -91,7 +92,7 @@ final class SseServerResponse extends AbstractServerResponse {
|
|||
}
|
||||
|
||||
DefaultAsyncServerResponse.writeAsync(request, response, result);
|
||||
this.sseConsumer.accept(new DefaultSseBuilder(response, context, result));
|
||||
this.sseConsumer.accept(new DefaultSseBuilder(response, context, result, this.headers()));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -114,15 +115,19 @@ final class SseServerResponse extends AbstractServerResponse {
|
|||
|
||||
private final List<HttpMessageConverter<?>> messageConverters;
|
||||
|
||||
private final HttpHeaders httpHeaders;
|
||||
|
||||
private final StringBuilder builder = new StringBuilder();
|
||||
|
||||
private boolean sendFailed;
|
||||
|
||||
|
||||
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult) {
|
||||
public DefaultSseBuilder(HttpServletResponse response, Context context, DeferredResult<?> deferredResult,
|
||||
HttpHeaders httpHeaders) {
|
||||
this.outputMessage = new ServletServerHttpResponse(response);
|
||||
this.deferredResult = deferredResult;
|
||||
this.messageConverters = context.messageConverters();
|
||||
this.httpHeaders = httpHeaders;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -207,7 +212,7 @@ final class SseServerResponse extends AbstractServerResponse {
|
|||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||
if (converter.canWrite(dataClass, MediaType.APPLICATION_JSON)) {
|
||||
HttpMessageConverter<Object> objectConverter = (HttpMessageConverter<Object>) converter;
|
||||
ServerHttpResponse response = new MutableHeadersServerHttpResponse(this.outputMessage);
|
||||
ServerHttpResponse response = new MutableHeadersServerHttpResponse(this.outputMessage, this.httpHeaders);
|
||||
objectConverter.write(data, MediaType.APPLICATION_JSON, response);
|
||||
this.outputMessage.getBody().write(NL_NL);
|
||||
this.outputMessage.flush();
|
||||
|
@ -277,9 +282,10 @@ final class SseServerResponse extends AbstractServerResponse {
|
|||
|
||||
private final HttpHeaders mutableHeaders = new HttpHeaders();
|
||||
|
||||
public MutableHeadersServerHttpResponse(ServerHttpResponse delegate) {
|
||||
public MutableHeadersServerHttpResponse(ServerHttpResponse delegate, HttpHeaders headers) {
|
||||
super(delegate);
|
||||
this.mutableHeaders.putAll(delegate.getHeaders());
|
||||
this.mutableHeaders.putAll(headers);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,6 +33,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
* @author Sebastien Deleuze
|
||||
*/
|
||||
class SseServerResponseTests {
|
||||
|
||||
|
@ -89,6 +90,33 @@ class SseServerResponseTests {
|
|||
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void sendObjectWithPrettyPrint() throws Exception {
|
||||
Person person = new Person("John Doe", 42);
|
||||
ServerResponse response = ServerResponse.sse(sse -> {
|
||||
try {
|
||||
sse.send(person);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
});
|
||||
|
||||
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||
converter.setPrettyPrint(true);
|
||||
ServerResponse.Context context = () -> Collections.singletonList(converter);
|
||||
|
||||
ModelAndView mav = response.writeTo(this.mockRequest, this.mockResponse, context);
|
||||
assertThat(mav).isNull();
|
||||
|
||||
String expected = "data:{\n" +
|
||||
"data: \"name\" : \"John Doe\",\n" +
|
||||
"data: \"age\" : 42\n" +
|
||||
"data:}\n" +
|
||||
"\n";
|
||||
assertThat(this.mockResponse.getContentAsString()).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
void builder() throws Exception {
|
||||
ServerResponse response = ServerResponse.sse(sse -> {
|
||||
|
|
Loading…
Reference in New Issue