Skip to content

Commit 1c71567

Browse files
committed
Support "application/graphql+json" media type in GraphQL HTTP mapping
As seen in spring-projects/spring-graphql#108, the GraphQL HTTP spec now requires the "application/graphql+json" media type and accepts "application/json" for backwards compatibility. This commit updates the `RouterFunction` definition for the GraphQL HTTP endpoints so that both types are accepted. Closes gh-30407
1 parent d476d8e commit 1c71567

File tree

7 files changed

+17
-16
lines changed

7 files changed

+17
-16
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfiguration.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@
8181
@EnableConfigurationProperties(GraphQlCorsProperties.class)
8282
public class GraphQlWebFluxAutoConfiguration {
8383

84-
private static final RequestPredicate ACCEPT_JSON_CONTENT = accept(MediaType.APPLICATION_JSON)
85-
.and(contentType(MediaType.APPLICATION_JSON));
84+
private static final RequestPredicate SUPPORTS_MEDIATYPES = accept(MediaType.APPLICATION_GRAPHQL,
85+
MediaType.APPLICATION_JSON).and(contentType(MediaType.APPLICATION_GRAPHQL, MediaType.APPLICATION_JSON));
8686

8787
private static final Log logger = LogFactory.getLog(GraphQlWebFluxAutoConfiguration.class);
8888

@@ -107,7 +107,7 @@ public RouterFunction<ServerResponse> graphQlEndpoint(GraphQlHttpHandler httpHan
107107
logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path));
108108
RouterFunctions.Builder builder = RouterFunctions.route();
109109
builder = builder.GET(path, this::onlyAllowPost);
110-
builder = builder.POST(path, ACCEPT_JSON_CONTENT, httpHandler::handleRequest);
110+
builder = builder.POST(path, SUPPORTS_MEDIATYPES, httpHandler::handleRequest);
111111
if (properties.getGraphiql().isEnabled()) {
112112
GraphiQlHandler graphQlHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());
113113
builder = builder.GET(properties.getGraphiql().getPath(), graphQlHandler::handleRequest);

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfiguration.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ public class GraphQlWebMvcAutoConfiguration {
8787

8888
private static final Log logger = LogFactory.getLog(GraphQlWebMvcAutoConfiguration.class);
8989

90-
private static MediaType[] SUPPORTED_MEDIA_TYPES = new MediaType[] { MediaType.valueOf("application/graphql+json"),
90+
private static MediaType[] SUPPORTED_MEDIA_TYPES = new MediaType[] { MediaType.APPLICATION_GRAPHQL,
9191
MediaType.APPLICATION_JSON };
9292

9393
@Bean
@@ -113,8 +113,8 @@ public RouterFunction<ServerResponse> graphQlRouterFunction(GraphQlHttpHandler h
113113
logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path));
114114
RouterFunctions.Builder builder = RouterFunctions.route();
115115
builder = builder.GET(path, this::onlyAllowPost);
116-
builder = builder.POST(path, RequestPredicates.contentType(MediaType.APPLICATION_JSON)
117-
.and(RequestPredicates.accept(MediaType.APPLICATION_JSON)), httpHandler::handleRequest);
116+
builder = builder.POST(path, RequestPredicates.contentType(SUPPORTED_MEDIA_TYPES)
117+
.and(RequestPredicates.accept(SUPPORTED_MEDIA_TYPES)), httpHandler::handleRequest);
118118
if (properties.getGraphiql().isEnabled()) {
119119
GraphiQlHandler graphiQLHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());
120120
builder = builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::handleRequest);

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/reactive/GraphQlWebFluxAutoConfigurationTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ void simpleQueryShouldWork() {
7575
testWithWebClient((client) -> {
7676
String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }";
7777
client.post().uri("/graphql").bodyValue("{ \"query\": \"" + query + "\"}").exchange().expectStatus().isOk()
78-
.expectBody().jsonPath("data.bookById.name").isEqualTo("GraphQL for beginners");
78+
.expectHeader().contentType("application/graphql+json").expectBody().jsonPath("data.bookById.name")
79+
.isEqualTo("GraphQL for beginners");
7980
});
8081
}
8182

@@ -150,8 +151,8 @@ private void testWithWebClient(Consumer<WebTestClient> consumer) {
150151
this.contextRunner.run((context) -> {
151152
WebTestClient client = WebTestClient.bindToApplicationContext(context).configureClient()
152153
.defaultHeaders((headers) -> {
153-
headers.setContentType(MediaType.APPLICATION_JSON);
154-
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_JSON));
154+
headers.setContentType(MediaType.APPLICATION_GRAPHQL);
155+
headers.setAccept(Collections.singletonList(MediaType.APPLICATION_GRAPHQL));
155156
}).baseUrl(BASE_URL).build();
156157
consumer.accept(client);
157158
});

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/graphql/servlet/GraphQlWebMvcAutoConfigurationTests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ void simpleQueryShouldWork() {
8181
String query = "{ bookById(id: \\\"book-1\\\"){ id name pageCount author } }";
8282
MvcResult result = mockMvc.perform(post("/graphql").content("{\"query\": \"" + query + "\"}")).andReturn();
8383
mockMvc.perform(asyncDispatch(result)).andExpect(status().isOk())
84-
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
84+
.andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_GRAPHQL))
8585
.andExpect(jsonPath("data.bookById.name").value("GraphQL for beginners"));
8686
});
8787
}
@@ -155,9 +155,9 @@ void shouldConfigureWebSocketBeans() {
155155

156156
private void testWith(MockMvcConsumer mockMvcConsumer) {
157157
this.contextRunner.run((context) -> {
158-
MediaType mediaType = MediaType.APPLICATION_JSON;
159-
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context)
160-
.defaultRequest(post("/graphql").contentType(mediaType).accept(mediaType)).build();
158+
MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(context).defaultRequest(
159+
post("/graphql").contentType(MediaType.APPLICATION_GRAPHQL).accept(MediaType.APPLICATION_GRAPHQL))
160+
.build();
161161
mockMvcConsumer.accept(mockMvc);
162162
});
163163
}

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerIntegrationTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static class TestHandler implements HttpHandler {
7979
@Override
8080
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
8181
response.setStatusCode(HttpStatus.OK);
82-
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
82+
response.getHeaders().setContentType(MediaType.APPLICATION_GRAPHQL);
8383
return response.writeWith(Mono.just(factory.wrap("{\"data\":{}}".getBytes())));
8484
}
8585

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomBasePathTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static class TestHandler implements HttpHandler {
7979
@Override
8080
public Mono<Void> handle(ServerHttpRequest request, ServerHttpResponse response) {
8181
response.setStatusCode(HttpStatus.OK);
82-
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
82+
response.getHeaders().setContentType(MediaType.APPLICATION_GRAPHQL);
8383
return response.writeWith(Mono.just(factory.wrap("{\"data\":{}}".getBytes())));
8484
}
8585

spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/graphql/tester/HttpGraphQlTesterContextCustomizerWithCustomContextPathTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ DispatcherServlet dispatcherServlet() {
7070
@RestController
7171
static class TestController {
7272

73-
@PostMapping(path = "/graphql", produces = MediaType.APPLICATION_JSON_VALUE)
73+
@PostMapping(path = "/graphql", produces = MediaType.APPLICATION_GRAPHQL_VALUE)
7474
String graphql() {
7575
return "{}";
7676
}

0 commit comments

Comments
 (0)