diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java index 902a7d2f7d8..55276ce5eff 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandler.java @@ -80,7 +80,8 @@ class ReactiveTypeHandler { @SuppressWarnings("deprecation") private static final List JSON_STREAMING_MEDIA_TYPES = - Arrays.asList(MediaType.APPLICATION_NDJSON, MediaType.APPLICATION_STREAM_JSON); + Arrays.asList(MediaType.APPLICATION_NDJSON, MediaType.APPLICATION_STREAM_JSON, + MediaType.valueOf("application/*+x-ndjson")); private static final boolean isContextPropagationPresent = ClassUtils.isPresent( "io.micrometer.context.ContextSnapshot", ReactiveTypeHandler.class.getClassLoader()); @@ -165,7 +166,7 @@ class ReactiveTypeHandler { for (MediaType streamingType : JSON_STREAMING_MEDIA_TYPES) { if (streamingType.includes(type)) { logExecutorWarning(returnType); - ResponseBodyEmitter emitter = getEmitter(streamingType); + ResponseBodyEmitter emitter = getEmitter(type); new JsonEmitterSubscriber(emitter, this.taskExecutor).connect(adapter, returnValue); return emitter; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandlerTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandlerTests.java index d7952e28a09..28bccb9aa9d 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandlerTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/ReactiveTypeHandlerTests.java @@ -255,6 +255,32 @@ public class ReactiveTypeHandlerTests { assertThat(emitterHandler.getValues()).isEqualTo(Arrays.asList(bar1, "\n", bar2, "\n")); } + @Test + public void writeStreamJsonWithVendorSubtype() throws Exception { + this.servletRequest.addHeader("Accept", "application/vnd.myapp.v1+x-ndjson"); + + Sinks.Many sink = Sinks.many().unicast().onBackpressureBuffer(); + ResponseBodyEmitter emitter = handleValue(sink.asFlux(), Flux.class, forClass(Bar.class)); + + assertThat(emitter).as("emitter").isNotNull(); + + EmitterHandler emitterHandler = new EmitterHandler(); + emitter.initialize(emitterHandler); + + ServletServerHttpResponse message = new ServletServerHttpResponse(this.servletResponse); + emitter.extendResponse(message); + + Bar bar1 = new Bar("foo"); + Bar bar2 = new Bar("bar"); + + sink.tryEmitNext(bar1); + sink.tryEmitNext(bar2); + sink.tryEmitComplete(); + + assertThat(message.getHeaders().getContentType().toString()).isEqualTo("application/vnd.myapp.v1+x-ndjson"); + assertThat(emitterHandler.getValues()).isEqualTo(Arrays.asList(bar1, "\n", bar2, "\n")); + } + @Test public void writeText() throws Exception {