diff --git a/spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlHttpHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlHttpHandler.java index 26ac915e..ce8ef3d2 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlHttpHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/webflux/GraphQlHttpHandler.java @@ -32,6 +32,7 @@ import org.springframework.graphql.server.support.SerializableGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; import org.springframework.web.reactive.function.server.ServerRequest; import org.springframework.web.reactive.function.server.ServerResponse; import org.springframework.web.server.UnsupportedMediaTypeStatusException; @@ -103,16 +104,19 @@ public class GraphQlHttpHandler { private static Mono applyApplicationGraphQlFallback( UnsupportedMediaTypeStatusException ex, ServerRequest request) { - - // Spec requires application/json but some clients still use application/graphql - return "application/graphql".equals(request.headers().firstHeader(HttpHeaders.CONTENT_TYPE)) ? - ServerRequest.from(request) - .headers((headers) -> headers.setContentType(MediaType.APPLICATION_JSON)) - .body(request.bodyToFlux(DataBuffer.class)) - .build() - .bodyToMono(SerializableGraphQlRequest.class) - .log() : - Mono.error(ex); + String contentTypeHeader = request.headers().firstHeader(HttpHeaders.CONTENT_TYPE); + if (StringUtils.hasText(contentTypeHeader)) { + MediaType contentType = MediaType.parseMediaType(contentTypeHeader); + MediaType applicationGraphQl = MediaType.parseMediaType("application/graphql"); + // Spec requires application/json but some clients still use application/graphql + return applicationGraphQl.includes(contentType) ? ServerRequest.from(request) + .headers((headers) -> headers.setContentType(MediaType.APPLICATION_JSON)) + .body(request.bodyToFlux(DataBuffer.class)) + .build() + .bodyToMono(SerializableGraphQlRequest.class) + .log() : Mono.error(ex); + } + return Mono.error(ex); } private static MediaType selectResponseMediaType(ServerRequest serverRequest) { diff --git a/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandler.java b/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandler.java index c9c459cb..9c757a43 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandler.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandler.java @@ -42,6 +42,7 @@ import org.springframework.util.Assert; import org.springframework.util.IdGenerator; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; +import org.springframework.util.StringUtils; import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.server.ServerWebInputException; import org.springframework.web.servlet.function.ServerRequest; @@ -154,23 +155,28 @@ public class GraphQlHttpHandler { private static SerializableGraphQlRequest applyApplicationGraphQlFallback( ServerRequest request, HttpMediaTypeNotSupportedException ex) throws HttpMediaTypeNotSupportedException { - - // Spec requires application/json but some clients still use application/graphql - if ("application/graphql".equals(request.headers().firstHeader(HttpHeaders.CONTENT_TYPE))) { - try { - request = ServerRequest.from(request) - .headers((headers) -> headers.setContentType(MediaType.APPLICATION_JSON)) - .body(request.body(byte[].class)) - .build(); - return request.body(SerializableGraphQlRequest.class); - } - catch (Throwable ex2) { - // ignore + String contentTypeHeader = request.headers().firstHeader(HttpHeaders.CONTENT_TYPE); + if (StringUtils.hasText(contentTypeHeader)) { + MediaType contentType = MediaType.parseMediaType(contentTypeHeader); + MediaType applicationGraphQl = MediaType.parseMediaType("application/graphql"); + // Spec requires application/json but some clients still use application/graphql + if (applicationGraphQl.includes(contentType)) { + try { + request = ServerRequest.from(request) + .headers((headers) -> headers.setContentType(MediaType.APPLICATION_JSON)) + .body(request.body(byte[].class)) + .build(); + return request.body(SerializableGraphQlRequest.class); + } + catch (Throwable ex2) { + // ignore + } } } throw ex; } + private static MediaType selectResponseMediaType(ServerRequest serverRequest) { for (MediaType accepted : serverRequest.headers().accept()) { if (SUPPORTED_MEDIA_TYPES.contains(accepted)) { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphQlHttpHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphQlHttpHandlerTests.java index 10cc70cc..bc03bc95 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphQlHttpHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/server/webflux/GraphQlHttpHandlerTests.java @@ -91,6 +91,22 @@ public class GraphQlHttpHandlerTests { .verifyComplete(); } + @Test + void shouldSupportApplicationGraphQlWithCharset() throws Exception { + String document = "{greeting}"; + MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/") + .contentType(MediaType.parseMediaType("application/graphql;charset=UTF-8")) + .accept(MediaType.ALL) + .body(initRequestBody(document)); + + MockServerHttpResponse response = handleRequest(httpRequest, this.greetingHandler); + + assertThat(response.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); + StepVerifier.create(response.getBodyAsString()) + .expectNext("{\"data\":{\"greeting\":\"Hello\"}}") + .verifyComplete(); + } + @Test void shouldProduceApplicationGraphQl() throws Exception { MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/") diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandlerTests.java index ecdf04ce..c649b080 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/server/webmvc/GraphQlHttpHandlerTests.java @@ -79,6 +79,15 @@ public class GraphQlHttpHandlerTests { assertThat(response.getContentAsString()).isEqualTo("{\"data\":{\"greeting\":\"Hello\"}}"); } + @Test + void shouldSupportApplicationGraphQlWithCharset() throws Exception { + MockHttpServletRequest request = createServletRequest("{ greeting }", "*/*"); + request.setContentType("application/graphql;charset=UTF-8"); + + MockHttpServletResponse response = handleRequest(request, this.greetingHandler); + assertThat(response.getContentAsString()).isEqualTo("{\"data\":{\"greeting\":\"Hello\"}}"); + } + @Test void shouldProduceApplicationGraphQl() throws Exception { MockHttpServletRequest request = createServletRequest("{ greeting }", MediaType.APPLICATION_GRAPHQL_RESPONSE_VALUE);