diff --git a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlHandlerGraphQlTransport.java b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlHandlerGraphQlTransport.java index 5b9e14dc..06cc9749 100644 --- a/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlHandlerGraphQlTransport.java +++ b/spring-graphql-test/src/main/java/org/springframework/graphql/test/tester/WebGraphQlHandlerGraphQlTransport.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. @@ -79,7 +79,7 @@ final class WebGraphQlHandlerGraphQlTransport extends AbstractDirectGraphQlTrans protected Mono executeInternal(ExecutionGraphQlRequest executionRequest) { WebGraphQlRequest request = new WebGraphQlRequest( - this.url, this.headers, null, Collections.emptyMap(), executionRequest.toMap(), + this.url, this.headers, null, Collections.emptyMap(), executionRequest, idGenerator.generateId().toString(), null); return this.graphQlHandler.handleRequest(request).cast(ExecutionGraphQlResponse.class); diff --git a/spring-graphql/src/main/java/org/springframework/graphql/server/WebGraphQlRequest.java b/spring-graphql/src/main/java/org/springframework/graphql/server/WebGraphQlRequest.java index bbe7b6b2..ffa938ee 100644 --- a/spring-graphql/src/main/java/org/springframework/graphql/server/WebGraphQlRequest.java +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/WebGraphQlRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-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. @@ -22,6 +22,7 @@ import java.util.Locale; import java.util.Map; import org.springframework.graphql.ExecutionGraphQlRequest; +import org.springframework.graphql.GraphQlRequest; import org.springframework.graphql.support.DefaultExecutionGraphQlRequest; import org.springframework.http.HttpCookie; import org.springframework.http.HttpHeaders; @@ -60,15 +61,6 @@ public class WebGraphQlRequest extends DefaultExecutionGraphQlRequest implements private final Map attributes; - /** - * Create an instance. - * @deprecated as of 1.1.3 in favor of the constructor with cookies - */ - @Deprecated - public WebGraphQlRequest(URI uri, HttpHeaders headers, Map body, String id, @Nullable Locale locale) { - this(uri, headers, null, Collections.emptyMap(), body, id, locale); - } - /** * Create an instance. * @param uri the URL for the HTTP request or WebSocket handshake @@ -78,22 +70,27 @@ public class WebGraphQlRequest extends DefaultExecutionGraphQlRequest implements * @param body the deserialized content of the GraphQL request * @param id an identifier for the GraphQL request * @param locale the locale from the HTTP request, if any + * @since 1.2.5 + */ + public WebGraphQlRequest( + URI uri, HttpHeaders headers, @Nullable MultiValueMap cookies, + Map attributes, GraphQlRequest body, String id, @Nullable Locale locale) { + + this(uri, headers, cookies, attributes, body.getDocument(), + body.getOperationName(), body.getVariables(), body.getExtensions(), id, locale); + } + + /** + * Variant of {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, Map, GraphQlRequest, String, Locale)} + * with a Map for the request body. * @since 1.1.3 */ public WebGraphQlRequest( URI uri, HttpHeaders headers, @Nullable MultiValueMap cookies, Map attributes, Map body, String id, @Nullable Locale locale) { - super(getQuery(body), getOperation(body), + this(uri, headers, cookies, attributes, getQuery(body), getOperation(body), getMap(VARIABLES_KEY, body), getMap(EXTENSIONS_KEY, body), id, locale); - - Assert.notNull(uri, "URI is required'"); - Assert.notNull(headers, "HttpHeaders is required'"); - - this.uri = UriComponentsBuilder.fromUri(uri).build(true); - this.headers = headers; - this.cookies = (cookies != null ? CollectionUtils.unmodifiableMultiValueMap(cookies) : EMPTY_COOKIES); - this.attributes = Collections.unmodifiableMap(attributes); } private static String getQuery(Map body) { @@ -123,6 +120,33 @@ public class WebGraphQlRequest extends DefaultExecutionGraphQlRequest implements return (Map) value; } + /** + * Create an instance. + * @deprecated as of 1.1.3 in favor of + * {@link #WebGraphQlRequest(URI, HttpHeaders, MultiValueMap, Map, GraphQlRequest, String, Locale)} + */ + @Deprecated(since = "1.1.3", forRemoval = true) + public WebGraphQlRequest(URI uri, HttpHeaders headers, Map body, String id, @Nullable Locale locale) { + this(uri, headers, null, Collections.emptyMap(), body, id, locale); + } + + private WebGraphQlRequest( + URI uri, HttpHeaders headers, @Nullable MultiValueMap cookies, + Map attributes, String document, @Nullable String operationName, + @Nullable Map variables, @Nullable Map extensions, + String id, @Nullable Locale locale) { + + super(document, operationName, variables, extensions, id, locale); + + Assert.notNull(uri, "URI is required'"); + Assert.notNull(headers, "HttpHeaders is required'"); + + this.uri = UriComponentsBuilder.fromUri(uri).build(true); + this.headers = headers; + this.cookies = (cookies != null ? CollectionUtils.unmodifiableMultiValueMap(cookies) : EMPTY_COOKIES); + this.attributes = Collections.unmodifiableMap(attributes); + } + /** * Return the URL for the HTTP request or WebSocket handshake. 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 new file mode 100644 index 00000000..7f71ea9d --- /dev/null +++ b/spring-graphql/src/main/java/org/springframework/graphql/server/support/SerializableGraphQlRequest.java @@ -0,0 +1,98 @@ +/* + * 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. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.graphql.server.support; + +import java.util.Map; + +import org.springframework.graphql.GraphQlRequest; +import org.springframework.lang.Nullable; +import org.springframework.web.server.ServerWebInputException; + + +/** + * {@link GraphQlRequest} for deserialization from a request. + * + * @author Rossen Stoyanchev + * @since 1.2.5 + */ +public class SerializableGraphQlRequest implements GraphQlRequest { + + @Nullable + private String query; + + @Nullable + private String operationName; + + @Nullable + private Map variables; + + @Nullable + private Map extensions; + + + public void setQuery(String query) { + this.query = query; + } + + @Nullable + public String getQuery() { + return this.query; + } + + public void setOperationName(@Nullable String operationName) { + this.operationName = operationName; + } + + @Nullable + @Override + public String getOperationName() { + return this.operationName; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + @Nullable + @Override + public Map getVariables() { + return this.variables; + } + + public void setExtensions(Map extensions) { + this.extensions = extensions; + } + + @Nullable + @Override + public Map getExtensions() { + return this.extensions; + } + + @Override + public String getDocument() { + if (this.query == null) { + throw new ServerWebInputException("No 'query'"); + } + return this.query; + } + + @Override + public Map toMap() { + throw new UnsupportedOperationException(); + } + +} 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 611efc1a..deda89f9 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 @@ -1,5 +1,5 @@ /* - * Copyright 2020-2023 the original author or authors. + * Copyright 2020-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. @@ -27,6 +27,7 @@ import reactor.core.publisher.Mono; import org.springframework.core.ParameterizedTypeReference; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; +import org.springframework.graphql.server.support.SerializableGraphQlRequest; import org.springframework.http.MediaType; import org.springframework.util.Assert; import org.springframework.web.reactive.function.server.ServerRequest; @@ -71,7 +72,7 @@ public class GraphQlHttpHandler { * @return the HTTP response */ public Mono handleRequest(ServerRequest serverRequest) { - return serverRequest.bodyToMono(MAP_PARAMETERIZED_TYPE_REF) + return serverRequest.bodyToMono(SerializableGraphQlRequest.class) .flatMap(body -> { WebGraphQlRequest graphQlRequest = new WebGraphQlRequest( serverRequest.uri(), serverRequest.headers().asHttpHeaders(), 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 9951fcaf..d87b87a9 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 @@ -30,8 +30,10 @@ import org.apache.commons.logging.LogFactory; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.ParameterizedTypeReference; +import org.springframework.graphql.GraphQlRequest; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; +import org.springframework.graphql.server.support.SerializableGraphQlRequest; import org.springframework.http.HttpCookie; import org.springframework.http.MediaType; import org.springframework.util.AlternativeJdkIdGenerator; @@ -135,9 +137,9 @@ public class GraphQlHttpHandler { return target; } - private static Map readBody(ServerRequest request) throws ServletException { + private static GraphQlRequest readBody(ServerRequest request) throws ServletException { try { - return request.body(MAP_PARAMETERIZED_TYPE_REF); + return request.body(SerializableGraphQlRequest.class); } catch (IOException ex) { throw new ServerWebInputException("I/O error while reading request body", null, ex); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java index f05271b8..b8aa82af 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/QuerydslDataFetcherTests.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. @@ -49,14 +49,13 @@ import org.springframework.graphql.ExecutionGraphQlResponse; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.ResponseHelper; import org.springframework.graphql.data.GraphQlRepository; -import org.springframework.graphql.data.pagination.ConnectionFieldTypeVisitor; import org.springframework.graphql.data.query.QuerydslDataFetcher.Builder; import org.springframework.graphql.data.query.QuerydslDataFetcher.QuerydslBuilderCustomizer; -import org.springframework.graphql.execution.ConnectionTypeDefinitionConfigurer; import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; @@ -378,7 +377,7 @@ class QuerydslDataFetcherTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", Locale.ENGLISH); + new DefaultGraphQlRequest(query), "1", Locale.ENGLISH); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java index 1820978a..0a41f632 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/jpa/QueryByExampleDataFetcherJpaTests.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. @@ -51,6 +51,7 @@ import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.jpa.JpaTransactionManager; @@ -262,7 +263,7 @@ class QueryByExampleDataFetcherJpaTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", null); + new DefaultGraphQlRequest(query), "1", null); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java index 8fcb2242..58dbf134 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherMongoDbTests.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. @@ -45,16 +45,15 @@ import org.springframework.data.repository.query.QueryByExampleExecutor; import org.springframework.graphql.BookSource; import org.springframework.graphql.GraphQlSetup; import org.springframework.graphql.ResponseHelper; -import org.springframework.graphql.data.pagination.ConnectionFieldTypeVisitor; import org.springframework.graphql.data.query.QueryByExampleDataFetcher; import org.springframework.graphql.data.query.ScrollPositionCursorStrategy; import org.springframework.graphql.data.query.ScrollSubrange; import org.springframework.graphql.data.query.WindowConnectionAdapter; -import org.springframework.graphql.execution.ConnectionTypeDefinitionConfigurer; import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -242,7 +241,7 @@ class QueryByExampleDataFetcherMongoDbTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", null); + new DefaultGraphQlRequest(query), "1", null); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java index d5858345..3019acd6 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/mongo/QueryByExampleDataFetcherReactiveMongoDbTests.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. @@ -52,6 +52,7 @@ import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; @@ -213,7 +214,7 @@ class QueryByExampleDataFetcherReactiveMongoDbTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", null); + new DefaultGraphQlRequest(query), "1", null); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherNeo4jTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherNeo4jTests.java index ade94445..9943dd6d 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherNeo4jTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherNeo4jTests.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. @@ -16,11 +16,26 @@ package org.springframework.graphql.data.query.neo4j; +import java.net.URI; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Consumer; +import java.util.stream.Collectors; + import graphql.schema.DataFetcher; import org.junit.jupiter.api.Test; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; +import org.testcontainers.containers.Neo4jContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import reactor.core.publisher.Mono; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -40,23 +55,10 @@ import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.testcontainers.containers.Neo4jContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.utility.DockerImageName; -import reactor.core.publisher.Mono; - -import java.net.URI; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Consumer; -import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.any; @@ -241,7 +243,7 @@ class QueryByExampleDataFetcherNeo4jTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", null); + new DefaultGraphQlRequest(query), "1", null); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherReactiveNeo4jDbTests.java b/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherReactiveNeo4jDbTests.java index 5a9795c3..994162d2 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherReactiveNeo4jDbTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/data/query/neo4j/QueryByExampleDataFetcherReactiveNeo4jDbTests.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. @@ -16,6 +16,13 @@ package org.springframework.graphql.data.query.neo4j; +import java.net.URI; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.stream.Collectors; + import graphql.schema.DataFetcher; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -23,6 +30,13 @@ import org.neo4j.cypherdsl.core.renderer.Dialect; import org.neo4j.driver.AuthTokens; import org.neo4j.driver.Driver; import org.neo4j.driver.GraphDatabase; +import org.testcontainers.containers.Neo4jContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -42,22 +56,10 @@ import org.springframework.graphql.execution.RuntimeWiringConfigurer; import org.springframework.graphql.server.WebGraphQlHandler; import org.springframework.graphql.server.WebGraphQlRequest; import org.springframework.graphql.server.WebGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import org.springframework.lang.Nullable; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; -import org.testcontainers.containers.Neo4jContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; -import org.testcontainers.utility.DockerImageName; -import reactor.core.publisher.Flux; -import reactor.core.publisher.Mono; - -import java.net.URI; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.function.Consumer; -import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; @@ -225,7 +227,7 @@ class QueryByExampleDataFetcherReactiveNeo4jDbTests { private WebGraphQlRequest request(String query) { return new WebGraphQlRequest( URI.create("/"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", query), "1", null); + new DefaultGraphQlRequest(query), "1", null); } diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlHandlerTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlHandlerTests.java index ba2ceaa8..ed57dd1f 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlHandlerTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlHandlerTests.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. @@ -32,6 +32,7 @@ import org.springframework.graphql.TestThreadLocalAccessor; import org.springframework.graphql.execution.DataFetcherExceptionResolver; import org.springframework.graphql.execution.DataFetcherExceptionResolverAdapter; import org.springframework.graphql.execution.ErrorType; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; @@ -43,7 +44,7 @@ public class WebGraphQlHandlerTests { private static final WebGraphQlRequest webInput = new WebGraphQlRequest( URI.create("https://abc.org"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", "{ greeting }"), "1", null); + new DefaultGraphQlRequest("{ greeting }"), "1", null); private final GraphQlSetup graphQlSetup = GraphQlSetup.schemaContent("type Query { greeting: String }"); diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlInterceptorTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlInterceptorTests.java index 19dcf9c8..8909ddbd 100644 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlInterceptorTests.java +++ b/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlInterceptorTests.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. @@ -30,6 +30,7 @@ import reactor.core.scheduler.Schedulers; import org.springframework.graphql.ExecutionGraphQlRequest; import org.springframework.graphql.ExecutionGraphQlResponse; import org.springframework.graphql.support.DefaultExecutionGraphQlResponse; +import org.springframework.graphql.support.DefaultGraphQlRequest; import org.springframework.http.HttpHeaders; import static org.assertj.core.api.Assertions.assertThat; @@ -41,7 +42,7 @@ public class WebGraphQlInterceptorTests { private static final WebGraphQlRequest webRequest = new WebGraphQlRequest( URI.create("http://abc.org"), new HttpHeaders(), null, Collections.emptyMap(), - Collections.singletonMap("query", "{ notUsed }"), "1", null); + new DefaultGraphQlRequest("{ notUsed }"), "1", null); @Test void interceptorOrder() { diff --git a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlRequestTests.java b/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlRequestTests.java deleted file mode 100644 index 095633c0..00000000 --- a/spring-graphql/src/test/java/org/springframework/graphql/server/WebGraphQlRequestTests.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2002-2023 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. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.graphql.server; - -import java.net.URI; -import java.util.Collections; -import java.util.Map; - -import org.junit.jupiter.api.Test; - -import org.springframework.http.HttpHeaders; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.web.server.ServerWebInputException; - -import static org.assertj.core.api.Assertions.assertThatThrownBy; - -/** - * Unit tests for {@link WebGraphQlRequest}. - * - * @author Rossen Stoyanchev - */ -public class WebGraphQlRequestTests { - - @Test // gh-726 - void invalidBody() { - testInvalidBody(Map.of()); - testInvalidBody(Map.of("query", Collections.emptyMap())); - testInvalidBody(Map.of("query", "query { foo }", "operationName", Collections.emptyMap())); - testInvalidBody(Map.of("query", "query { foo }", "variables", "not-a-map")); - testInvalidBody(Map.of("query", "query { foo }", "extensions", "not-a-map")); - } - - private void testInvalidBody(Map body) { - assertThatThrownBy(() -> - new WebGraphQlRequest( - URI.create("/graphql"), new HttpHeaders(), new LinkedMultiValueMap<>(), - Collections.emptyMap(), body, "1", null)) - .isInstanceOf(ServerWebInputException.class); - } - - -} 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 4dd3c52b..8240a206 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2022 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. @@ -18,14 +18,15 @@ package org.springframework.graphql.server.webflux; import java.util.Collections; import java.util.List; import java.util.Locale; -import java.util.Map; import com.jayway.jsonpath.DocumentContext; import com.jayway.jsonpath.JsonPath; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; +import org.springframework.graphql.GraphQlRequest; import org.springframework.graphql.GraphQlSetup; +import org.springframework.graphql.server.support.SerializableGraphQlRequest; import org.springframework.http.MediaType; import org.springframework.http.codec.EncoderHttpMessageWriter; import org.springframework.http.codec.HttpMessageWriter; @@ -55,8 +56,9 @@ public class GraphQlHttpHandlerTests { MockServerHttpRequest httpRequest = MockServerHttpRequest.post("/") .contentType(MediaType.APPLICATION_JSON).accept(MediaType.ALL).build(); + String document = "{greeting}"; MockServerHttpResponse httpResponse = handleRequest( - httpRequest, this.greetingHandler, Collections.singletonMap("query", "{greeting}")); + httpRequest, this.greetingHandler, initRequest(document)); assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); } @@ -67,7 +69,7 @@ public class GraphQlHttpHandlerTests { .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_GRAPHQL_RESPONSE).build(); MockServerHttpResponse httpResponse = handleRequest( - httpRequest, this.greetingHandler, Collections.singletonMap("query", "{greeting}")); + httpRequest, this.greetingHandler, initRequest("{greeting}")); assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_GRAPHQL_RESPONSE); } @@ -78,7 +80,7 @@ public class GraphQlHttpHandlerTests { .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON).build(); MockServerHttpResponse httpResponse = handleRequest( - httpRequest, this.greetingHandler, Collections.singletonMap("query", "{greeting}")); + httpRequest, this.greetingHandler, initRequest("{greeting}")); assertThat(httpResponse.getHeaders().getContentType()).isEqualTo(MediaType.APPLICATION_JSON); } @@ -94,7 +96,7 @@ public class GraphQlHttpHandlerTests { .acceptLanguageAsLocales(Locale.FRENCH).build(); MockServerHttpResponse httpResponse = handleRequest( - httpRequest, handler, Collections.singletonMap("query", "{greeting}")); + httpRequest, handler, initRequest("{greeting}")); assertThat(httpResponse.getBodyAsString().block()) .isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}"); @@ -110,15 +112,21 @@ public class GraphQlHttpHandlerTests { .contentType(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_GRAPHQL_RESPONSE).build(); MockServerHttpResponse httpResponse = handleRequest( - httpRequest, handler, Collections.singletonMap("query", "{showId}")); + httpRequest, handler, initRequest("{showId}")); DocumentContext document = JsonPath.parse(httpResponse.getBodyAsString().block()); String id = document.read("data.showId", String.class); assertThat(id).isEqualTo(httpRequest.getId()); } + private static SerializableGraphQlRequest initRequest(String document) { + SerializableGraphQlRequest request = new SerializableGraphQlRequest(); + request.setQuery(document); + return request; + } + private MockServerHttpResponse handleRequest( - MockServerHttpRequest httpRequest, GraphQlHttpHandler handler, Map body) { + MockServerHttpRequest httpRequest, GraphQlHttpHandler handler, GraphQlRequest body) { MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest); @@ -127,7 +135,7 @@ public class GraphQlHttpHandlerTests { .uri(((ServerWebExchange) exchange).getRequest().getURI()) .method(((ServerWebExchange) exchange).getRequest().getMethod()) .headers(((ServerWebExchange) exchange).getRequest().getHeaders()) - .body(Mono.just((Object) body)); + .body(Mono.just(body)); handler.handleRequest(serverRequest) .flatMap(response -> response.writeTo(exchange, new DefaultContext()))