Return 405 "Allow:POST" for HTTP GET queries
See gh-70
This commit is contained in:
@@ -42,6 +42,8 @@ import org.springframework.graphql.web.WebGraphQlHandler;
|
||||
import org.springframework.graphql.web.WebInterceptor;
|
||||
import org.springframework.graphql.web.webflux.GraphQlHttpHandler;
|
||||
import org.springframework.graphql.web.webflux.GraphQlWebSocketHandler;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.codec.ServerCodecConfigurer;
|
||||
import org.springframework.web.reactive.HandlerMapping;
|
||||
@@ -87,18 +89,27 @@ public class GraphQlWebFluxAutoConfiguration {
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> graphQlEndpoint(GraphQlHttpHandler handler, GraphQlSource graphQlSource,
|
||||
GraphQlProperties properties, ResourceLoader resourceLoader) {
|
||||
|
||||
String graphQLPath = properties.getPath();
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("GraphQL endpoint HTTP POST " + graphQLPath);
|
||||
}
|
||||
// @formatter:off
|
||||
RouterFunctions.Builder builder = RouterFunctions.route()
|
||||
.POST(graphQLPath, accept(MediaType.APPLICATION_JSON).and(contentType(MediaType.APPLICATION_JSON)), handler::handleRequest);
|
||||
.GET(graphQLPath, request ->
|
||||
ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
.headers(headers -> headers.setAllow(Collections.singleton(HttpMethod.POST)))
|
||||
.build())
|
||||
.POST(graphQLPath,
|
||||
accept(MediaType.APPLICATION_JSON).and(contentType(MediaType.APPLICATION_JSON)),
|
||||
handler::handleRequest);
|
||||
|
||||
if (properties.getGraphiql().isEnabled()) {
|
||||
Resource resource = resourceLoader.getResource("classpath:graphiql/index.html");
|
||||
GraphiQlWebFluxHandler graphiQlHandler = new GraphiQlWebFluxHandler(graphQLPath, resource);
|
||||
builder = builder.GET(properties.getGraphiql().getPath(), graphiQlHandler::showGraphiQlPage);
|
||||
}
|
||||
|
||||
if (properties.getSchema().getPrinter().isEnabled()) {
|
||||
SchemaPrinter printer = new SchemaPrinter();
|
||||
builder = builder.GET(graphQLPath + properties.getSchema().getPrinter().getPath(),
|
||||
|
||||
@@ -47,6 +47,8 @@ import org.springframework.graphql.web.WebGraphQlHandler;
|
||||
import org.springframework.graphql.web.WebInterceptor;
|
||||
import org.springframework.graphql.web.webmvc.GraphQlHttpHandler;
|
||||
import org.springframework.graphql.web.webmvc.GraphQlWebSocketHandler;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.converter.HttpMessageConverter;
|
||||
import org.springframework.web.servlet.HandlerMapping;
|
||||
@@ -94,20 +96,30 @@ public class GraphQlWebMvcAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RouterFunction<ServerResponse> graphQlRouterFunction(GraphQlHttpHandler handler, GraphQlSource graphQlSource,
|
||||
GraphQlProperties properties, ResourceLoader resourceLoader) {
|
||||
public RouterFunction<ServerResponse> graphQlRouterFunction(GraphQlHttpHandler handler,
|
||||
GraphQlSource graphQlSource, GraphQlProperties properties, ResourceLoader resourceLoader) {
|
||||
|
||||
String graphQLPath = properties.getPath();
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("GraphQL endpoint HTTP POST " + graphQLPath);
|
||||
}
|
||||
|
||||
// @formatter:off
|
||||
RouterFunctions.Builder builder = RouterFunctions.route()
|
||||
.POST(graphQLPath, contentType(MediaType.APPLICATION_JSON).and(accept(MediaType.APPLICATION_JSON)), handler::handleRequest);
|
||||
.GET(graphQLPath, request ->
|
||||
ServerResponse.status(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
.headers(headers -> headers.setAllow(Collections.singleton(HttpMethod.POST)))
|
||||
.build())
|
||||
.POST(graphQLPath,
|
||||
contentType(MediaType.APPLICATION_JSON).and(accept(MediaType.APPLICATION_JSON)),
|
||||
handler::handleRequest);
|
||||
|
||||
if (properties.getGraphiql().isEnabled()) {
|
||||
Resource resource = resourceLoader.getResource("classpath:graphiql/index.html");
|
||||
GraphiQlWebMvcHandler graphiQLHandler = new GraphiQlWebMvcHandler(graphQLPath, resource);
|
||||
builder = builder.GET(properties.getGraphiql().getPath(), graphiQLHandler::showGraphiQlPage);
|
||||
}
|
||||
|
||||
if (properties.getSchema().getPrinter().isEnabled()) {
|
||||
SchemaPrinter printer = new SchemaPrinter();
|
||||
builder = builder.GET(graphQLPath + properties.getSchema().getPrinter().getPath(),
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.boot.test.context.runner.ReactiveWebApplicationContex
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.graphql.web.WebInterceptor;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.test.web.reactive.server.WebTestClient;
|
||||
|
||||
@@ -63,7 +64,6 @@ class GraphQlWebFluxAutoConfigurationTests {
|
||||
" author" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
client.post().uri("").bodyValue("{ \"query\": \"" + query + "\"}")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
@@ -74,6 +74,25 @@ class GraphQlWebFluxAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryHttpGet() {
|
||||
testWithWebClient((client) -> {
|
||||
String query = "{" +
|
||||
" bookById(id: \\\"book-1\\\"){ " +
|
||||
" id" +
|
||||
" name" +
|
||||
" pageCount" +
|
||||
" author" +
|
||||
" }" +
|
||||
"}";
|
||||
client.get().uri("?query={query}", "{ \"query\": \"" + query + "\"}")
|
||||
.exchange()
|
||||
.expectStatus()
|
||||
.isEqualTo(HttpStatus.METHOD_NOT_ALLOWED)
|
||||
.expectHeader().valueEquals("Allow", "POST");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryMissing() {
|
||||
testWithWebClient((client) ->
|
||||
|
||||
@@ -58,7 +58,7 @@ class GraphQlWebMvcAutoConfigurationTests {
|
||||
"spring.graphql.schema.locations=classpath:books/");
|
||||
|
||||
@Test
|
||||
void endpointHandlesGraphQlQuery() {
|
||||
void query() {
|
||||
testWith((mockMvc) -> {
|
||||
String query = "{" +
|
||||
" bookById(id: \\\"book-1\\\"){ " +
|
||||
@@ -76,6 +76,23 @@ class GraphQlWebMvcAutoConfigurationTests {
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void queryHttpGet() {
|
||||
testWith((mockMvc) -> {
|
||||
String query = "{" +
|
||||
" bookById(id: \\\"book-1\\\"){ " +
|
||||
" id" +
|
||||
" name" +
|
||||
" pageCount" +
|
||||
" author" +
|
||||
" }" +
|
||||
"}";
|
||||
mockMvc.perform(get("/graphql?query={query}", "{\"query\": \"" + query + "\"}"))
|
||||
.andExpect(status().isMethodNotAllowed())
|
||||
.andExpect(header().string("Allow", "POST"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void missingQuery() {
|
||||
testWith((mockMvc) -> mockMvc.perform(post("/graphql").content("{}")).andExpect(status().isBadRequest()));
|
||||
|
||||
Reference in New Issue
Block a user