From 7140e6cbae84f0ca150eb857b4dd251ea63a8165 Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Fri, 22 Mar 2024 13:37:28 +0000 Subject: [PATCH] Avoid AssertException for persisted query Closes gh-930 --- .../modules/ROOT/pages/request-execution.adoc | 3 +- .../support/SerializableGraphQlRequest.java | 5 +++ .../webmvc/GraphQlHttpHandlerTests.java | 44 ++++++++++++++++++- .../springframework/graphql/GraphQlSetup.java | 8 +++- 4 files changed, 56 insertions(+), 4 deletions(-) diff --git a/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc b/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc index 42643ffc..7373ae66 100644 --- a/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc +++ b/spring-graphql-docs/modules/ROOT/pages/request-execution.adoc @@ -308,7 +308,8 @@ In Spring GraphQL you can register a `PreparsedDocumentProvider` through GraphQlSource.Builder builder = ... // Create provider -PreparsedDocumentProvider provider = ... +PreparsedDocumentProvider provider = + new ApolloPersistedQuerySupport(new InMemoryPersistedQueryCache(Collections.emptyMap())); builder.schemaResources(..) .configureRuntimeWiring(..) diff --git a/spring-graphql/src/main/java/org/springframework/graphql/server/support/SerializableGraphQlRequest.java b/spring-graphql/src/main/java/org/springframework/graphql/server/support/SerializableGraphQlRequest.java index 7f71ea9d..d73fb3bc 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/server/support/SerializableGraphQlRequest.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/support/SerializableGraphQlRequest.java @@ -17,6 +17,8 @@ package org.springframework.graphql.server.support; import java.util.Map; +import graphql.execution.preparsed.persisted.PersistedQuerySupport; + import org.springframework.graphql.GraphQlRequest; import org.springframework.lang.Nullable; import org.springframework.web.server.ServerWebInputException; @@ -85,6 +87,9 @@ public class SerializableGraphQlRequest implements GraphQlRequest { @Override public String getDocument() { if (this.query == null) { + if (this.extensions != null && this.extensions.get("persistedQuery") != null) { + return PersistedQuerySupport.PERSISTED_QUERY_MARKER; + } throw new ServerWebInputException("No 'query'"); } return this.query; 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 77221827..e98c4964 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 @@ -22,10 +22,11 @@ import java.util.List; import java.util.Locale; import java.util.UUID; -import jakarta.servlet.ServletException; - import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; +import graphql.execution.preparsed.persisted.ApolloPersistedQuerySupport; +import graphql.execution.preparsed.persisted.InMemoryPersistedQueryCache; +import jakarta.servlet.ServletException; import org.junit.jupiter.api.Test; import org.springframework.context.i18n.LocaleContextHolder; @@ -109,6 +110,45 @@ public class GraphQlHttpHandlerTests { assertThatNoException().isThrownBy(() -> UUID.fromString(id)); } + @Test + void persistedQuery() throws Exception { + + ApolloPersistedQuerySupport documentProvider = + new ApolloPersistedQuerySupport(new InMemoryPersistedQueryCache(Collections.emptyMap())); + + GraphQlHttpHandler handler = GraphQlSetup.schemaContent("type Query { greeting: String }") + .configureGraphQl(builder -> builder.preparsedDocumentProvider(documentProvider)) + .toHttpHandler(); + + String document = """ + { + "query" : "{__typename}", + "extensions": { + "persistedQuery": { + "version":1, + "sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38" + } + } + }"""; + + MockHttpServletResponse servletResponse = handleRequest(createServletRequest(document, "*/*"), handler); + assertThat(servletResponse.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}"); + + document = """ + { + "extensions":{ + "persistedQuery":{ + "version":1, + "sha256Hash":"ecf4edb46db40b5132295c0291d62fb65d6759a9eedfa4d5d612dd5ec54a6b38" + } + } + }"""; + + servletResponse = handleRequest(createServletRequest(document, "*/*"), handler); + assertThat(servletResponse.getContentAsString()).isEqualTo("{\"data\":{\"__typename\":\"Query\"}}"); + } + + private MockHttpServletRequest createServletRequest(String query, String accept) { MockHttpServletRequest servletRequest = new MockHttpServletRequest("POST", "/"); servletRequest.setContentType(MediaType.APPLICATION_JSON_VALUE); diff --git a/spring-graphql/src/testFixtures/java/org/springframework/graphql/GraphQlSetup.java b/spring-graphql/src/testFixtures/java/org/springframework/graphql/GraphQlSetup.java index d10cb3cc..e6761c26 100644 --- a/spring-graphql/src/testFixtures/java/org/springframework/graphql/GraphQlSetup.java +++ b/spring-graphql/src/testFixtures/java/org/springframework/graphql/GraphQlSetup.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2023 the original author or authors. + * Copyright 2002-2024 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.function.Consumer; import graphql.GraphQL; import graphql.execution.instrumentation.Instrumentation; @@ -137,6 +138,11 @@ public class GraphQlSetup implements GraphQlServiceSetup { return this; } + public GraphQlSetup configureGraphQl(Consumer configurer) { + this.graphQlSourceBuilder.configureGraphQl(configurer); + return this; + } + public GraphQL toGraphQl() { return this.graphQlSourceBuilder.build().graphQl(); }