Use optimized request predicates for GraphQL endpoints

Prior to this commit, Spring Boot auto-configurations for GraphQL web
endpoint were implementing their own `RequestPredicate` instances for
HTTP endpoints. Those were composing predicates with the provided DSL.
While this is functionnally right, Spring for GraphQL now provides
predicates in order to:

* host the implementation in spring-graphql directly
* provide optimized predicates for faster matching and lower overhead

This commit switches the auto-configurations to using these new
predicates.

Closes gh-39652
This commit is contained in:
Brian Clozel
2024-03-11 11:03:39 +01:00
parent 72441637ce
commit 65ef899400
2 changed files with 4 additions and 18 deletions

View File

@@ -47,19 +47,18 @@ import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.graphql.server.WebGraphQlHandler;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.webflux.GraphQlHttpHandler;
import org.springframework.graphql.server.webflux.GraphQlRequestPredicates;
import org.springframework.graphql.server.webflux.GraphQlWebSocketHandler;
import org.springframework.graphql.server.webflux.GraphiQlHandler;
import org.springframework.graphql.server.webflux.SchemaHandler;
import org.springframework.http.HttpHeaders;
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.cors.CorsConfiguration;
import org.springframework.web.reactive.HandlerMapping;
import org.springframework.web.reactive.config.CorsRegistry;
import org.springframework.web.reactive.config.WebFluxConfigurer;
import org.springframework.web.reactive.function.server.RequestPredicate;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerRequest;
@@ -67,9 +66,6 @@ import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.handler.SimpleUrlHandlerMapping;
import org.springframework.web.reactive.socket.server.support.WebSocketUpgradeHandlerPredicate;
import static org.springframework.web.reactive.function.server.RequestPredicates.accept;
import static org.springframework.web.reactive.function.server.RequestPredicates.contentType;
/**
* {@link EnableAutoConfiguration Auto-configuration} for enabling Spring GraphQL over
* WebFlux.
@@ -85,11 +81,6 @@ import static org.springframework.web.reactive.function.server.RequestPredicates
@ImportRuntimeHints(GraphQlWebFluxAutoConfiguration.GraphiQlResourceHints.class)
public class GraphQlWebFluxAutoConfiguration {
@SuppressWarnings("removal")
private static final RequestPredicate SUPPORTS_MEDIATYPES = accept(MediaType.APPLICATION_GRAPHQL_RESPONSE,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL)
.and(contentType(MediaType.APPLICATION_JSON));
private static final Log logger = LogFactory.getLog(GraphQlWebFluxAutoConfiguration.class);
@Bean
@@ -112,7 +103,7 @@ public class GraphQlWebFluxAutoConfiguration {
String path = properties.getPath();
logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path));
RouterFunctions.Builder builder = RouterFunctions.route();
builder = builder.POST(path, SUPPORTS_MEDIATYPES, httpHandler::handleRequest);
builder.route(GraphQlRequestPredicates.graphQlHttp(path), httpHandler::handleRequest);
builder = builder.GET(path, this::onlyAllowPost);
if (properties.getGraphiql().isEnabled()) {
GraphiQlHandler graphQlHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());

View File

@@ -49,6 +49,7 @@ import org.springframework.graphql.execution.GraphQlSource;
import org.springframework.graphql.server.WebGraphQlHandler;
import org.springframework.graphql.server.WebGraphQlInterceptor;
import org.springframework.graphql.server.webmvc.GraphQlHttpHandler;
import org.springframework.graphql.server.webmvc.GraphQlRequestPredicates;
import org.springframework.graphql.server.webmvc.GraphQlWebSocketHandler;
import org.springframework.graphql.server.webmvc.GraphiQlHandler;
import org.springframework.graphql.server.webmvc.SchemaHandler;
@@ -62,7 +63,6 @@ import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.function.RequestPredicates;
import org.springframework.web.servlet.function.RouterFunction;
import org.springframework.web.servlet.function.RouterFunctions;
import org.springframework.web.servlet.function.ServerRequest;
@@ -88,10 +88,6 @@ public class GraphQlWebMvcAutoConfiguration {
private static final Log logger = LogFactory.getLog(GraphQlWebMvcAutoConfiguration.class);
@SuppressWarnings("removal")
private static final MediaType[] SUPPORTED_MEDIA_TYPES = new MediaType[] { MediaType.APPLICATION_GRAPHQL_RESPONSE,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_GRAPHQL };
@Bean
@ConditionalOnMissingBean
public GraphQlHttpHandler graphQlHttpHandler(WebGraphQlHandler webGraphQlHandler) {
@@ -112,8 +108,7 @@ public class GraphQlWebMvcAutoConfiguration {
String path = properties.getPath();
logger.info(LogMessage.format("GraphQL endpoint HTTP POST %s", path));
RouterFunctions.Builder builder = RouterFunctions.route();
builder = builder.POST(path, RequestPredicates.contentType(MediaType.APPLICATION_JSON)
.and(RequestPredicates.accept(SUPPORTED_MEDIA_TYPES)), httpHandler::handleRequest);
builder.route(GraphQlRequestPredicates.graphQlHttp(path), httpHandler::handleRequest);
builder = builder.GET(path, this::onlyAllowPost);
if (properties.getGraphiql().isEnabled()) {
GraphiQlHandler graphiQLHandler = new GraphiQlHandler(path, properties.getWebsocket().getPath());