HTTP handlers set Locale in ExecutionInput

See gh-3
This commit is contained in:
Rossen Stoyanchev
2021-10-29 11:37:51 +00:00
parent f4a7c80cac
commit 2c8638dd6a
21 changed files with 341 additions and 45 deletions

View File

@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
@@ -113,6 +114,12 @@ class DefaultGraphQlTester implements GraphQlTester {
return this;
}
@Override
public DefaultRequestSpec locale(Locale locale) {
setLocale(locale);
return this;
}
@Override
public ResponseSpec execute() {
return this.requestStrategy.execute(createRequestInput());

View File

@@ -17,11 +17,13 @@
package org.springframework.graphql.test.tester;
import java.net.URI;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Function;
import reactor.core.publisher.Flux;
import org.springframework.graphql.RequestInput;
import org.springframework.graphql.web.WebInput;
import org.springframework.http.HttpHeaders;
import org.springframework.lang.Nullable;
@@ -122,6 +124,12 @@ class DefaultWebGraphQlTester implements WebGraphQlTester {
return this;
}
@Override
public WebRequestSpec locale(Locale locale) {
setLocale(locale);
return this;
}
@Override
public WebRequestSpec httpHeader(String headerName, String... headerValues) {
for (String headerValue : headerValues) {
@@ -152,7 +160,8 @@ class DefaultWebGraphQlTester implements WebGraphQlTester {
}
private WebInput createWebInput() {
return new WebInput(DEFAULT_URL, this.headers, createRequestInput().toMap(), null);
RequestInput input = createRequestInput();
return new WebInput(DEFAULT_URL, this.headers, input.toMap(), input.getLocale(), null);
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.graphql.test.tester;
import java.time.Duration;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.Predicate;
@@ -174,6 +175,13 @@ public interface GraphQlTester {
*/
T variable(String name, Object value);
/**
* Set the locale to associate with the request.
* @param locale the locale to use
* @return this request spec
*/
T locale(Locale locale);
}
/**

View File

@@ -16,6 +16,7 @@
package org.springframework.graphql.test.tester;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
import org.springframework.graphql.RequestInput;
@@ -38,6 +39,9 @@ class GraphQlTesterRequestSpecSupport {
private final Map<String, Object> variables = new LinkedHashMap<>();
@Nullable
private Locale locale;
protected GraphQlTesterRequestSpecSupport(String query) {
Assert.notNull(query, "`query` is required");
@@ -53,12 +57,16 @@ class GraphQlTesterRequestSpecSupport {
this.variables.put(name, value);
}
protected void setLocale(Locale locale) {
this.locale = locale;
}
protected void verify(GraphQlTester.ResponseSpec responseSpec) {
responseSpec.path("$.errors").valueIsEmpty();
}
protected RequestInput createRequestInput() {
return new RequestInput(this.query, this.operationName, this.variables);
return new RequestInput(this.query, this.operationName, this.variables, this.locale);
}
}

View File

@@ -17,6 +17,8 @@ package org.springframework.graphql.test.tester;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collections;
import java.util.Locale;
import java.util.function.Predicate;
import com.jayway.jsonpath.Configuration;
@@ -82,7 +84,13 @@ final class WebTestClientRequestStrategy extends RequestStrategySupport implemen
FluxExchangeResult<TestExecutionResult> exchangeResult = this.client.post()
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.TEXT_EVENT_STREAM)
.headers(headers -> headers.putAll(webInput.getHeaders()))
.headers(headers -> {
Locale locale = webInput.getLocale();
if (locale != null) {
headers.setAcceptLanguageAsLocales(Collections.singletonList(locale));
}
headers.putAll(webInput.getHeaders());
})
.bodyValue(webInput.toMap())
.exchange()
.expectStatus()

View File

@@ -227,7 +227,7 @@ public class WebGraphQlTesterTests {
String content = request.getBody().readUtf8();
Map<String, Object> map = new ObjectMapper().readValue(content, new TypeReference<Map<String, Object>>() {});
WebInput webInput = new WebInput(request.getRequestUrl().uri(), headers, map, null);
WebInput webInput = new WebInput(request.getRequestUrl().uri(), headers, map, null, null);
consumer.accept(webInput);
}

View File

@@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.function.BiFunction;
@@ -47,18 +48,23 @@ public class RequestInput {
private final Map<String, Object> variables;
@Nullable
private final Locale locale;
private final List<BiFunction<ExecutionInput, ExecutionInput.Builder, ExecutionInput>> executionInputConfigurers = new ArrayList<>();
public RequestInput(String query, @Nullable String operationName, @Nullable Map<String, Object> vars) {
public RequestInput(
String query, @Nullable String operationName, @Nullable Map<String, Object> vars,
@Nullable Locale locale) {
Assert.notNull(query, "'query' is required");
this.query = query;
this.operationName = operationName;
this.variables = ((vars != null) ? vars : Collections.emptyMap());
this.locale = locale;
}
public RequestInput(Map<String, Object> body) {
this(getKey("query", body), getKey("operationName", body), getKey("variables", body));
}
@SuppressWarnings("unchecked")
private static <T> T getKey(String key, Map<String, Object> body) {
@@ -66,8 +72,8 @@ public class RequestInput {
}
/**
* Return the query name extracted from the request body. This is guaranteed to be a
* non-empty string.
* Return the query name extracted from the request. This is guaranteed to
* be a non-empty string.
* @return the query name
*/
public String getQuery() {
@@ -75,8 +81,8 @@ public class RequestInput {
}
/**
* Return the operation name extracted from the request body or {@code null} if not
* provided.
* Return the operation name extracted from the request or {@code null} if
* not provided.
* @return the operation name or {@code null}
*/
@Nullable
@@ -85,14 +91,23 @@ public class RequestInput {
}
/**
* Return the variables that can be referenced via $syntax extracted from the request
* body or a {@code null} if not provided.
* Return the variables that can be referenced via $syntax extracted from
* the request body or a {@code null} if not provided.
* @return the request variables or {@code null}
*/
public Map<String, Object> getVariables() {
return this.variables;
}
/**
* Return the locale associated with the request, if available.
* @return the locale of {@code null}
*/
@Nullable
public Locale getLocale() {
return this.locale;
}
/**
* Provide a consumer to configure the {@link ExecutionInput} used for input to
* {@link graphql.GraphQL#executeAsync(ExecutionInput)}. The builder is initially
@@ -113,8 +128,12 @@ public class RequestInput {
* @return the execution input
*/
public ExecutionInput toExecutionInput() {
ExecutionInput executionInput = ExecutionInput.newExecutionInput().query(this.query)
.operationName(this.operationName).variables(this.variables).build();
ExecutionInput executionInput = ExecutionInput.newExecutionInput()
.query(this.query)
.operationName(this.operationName)
.variables(this.variables)
.locale(this.locale)
.build();
for (BiFunction<ExecutionInput, ExecutionInput.Builder, ExecutionInput> configurer : this.executionInputConfigurers) {
ExecutionInput current = executionInput;
@@ -142,9 +161,10 @@ public class RequestInput {
@Override
public String toString() {
return "Query='" + getQuery() + "'"
+ ((getOperationName() != null) ? ", Operation='" + getOperationName() + "'" : "")
+ (!CollectionUtils.isEmpty(getVariables()) ? ", Variables=" + getVariables() : "");
return "Query='" + getQuery() + "'" +
((getOperationName() != null) ? ", Operation='" + getOperationName() + "'" : "") +
(!CollectionUtils.isEmpty(getVariables()) ? ", Variables=" + getVariables() : "") +
(getLocale() != null ? ", Locale=" + getLocale() : "");
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.graphql.web;
import java.net.URI;
import java.util.Locale;
import java.util.Map;
import org.springframework.graphql.RequestInput;
@@ -50,12 +51,16 @@ public class WebInput extends RequestInput {
* @param uri the url for the HTTP request, or WebSocket handshake
* @param headers the HTTP request headers
* @param body the content of the request deserialized from JSON
* @param locale the locale associated with the request, if any
* @param id an identifier for the GraphQL request, e.g. a subscription id for
* correlating request and response messages, or it could be an id associated with the
* underlying request/connection id, if available
*/
public WebInput(URI uri, HttpHeaders headers, Map<String, Object> body, @Nullable String id) {
super(validateQuery(body));
public WebInput(
URI uri, HttpHeaders headers, Map<String, Object> body,
@Nullable Locale locale, @Nullable String id) {
super(getKey("query", body), getKey("operationName", body), getKey("variables", body), locale);
Assert.notNull(uri, "URI is required'");
Assert.notNull(headers, "HttpHeaders is required'");
this.uri = UriComponentsBuilder.fromUri(uri).build(true);
@@ -63,14 +68,15 @@ public class WebInput extends RequestInput {
this.id = (id != null) ? id : ObjectUtils.identityToString(this);
}
private static Map<String, Object> validateQuery(Map<String, Object> body) {
String query = (String) body.get("query");
if (!StringUtils.hasText(query)) {
@SuppressWarnings("unchecked")
private static <T> T getKey(String key, Map<String, Object> body) {
if (key.equals("query") && !StringUtils.hasText((String) body.get(key))) {
throw new ServerWebInputException("Query is required");
}
return body;
return (T) body.get(key);
}
/**
* Return the URI of the HTTP request including {@link UriComponents#getQueryParams()
* URL query parameters}.

View File

@@ -61,8 +61,10 @@ public class GraphQlHttpHandler {
public Mono<ServerResponse> handleRequest(ServerRequest request) {
return request.bodyToMono(MAP_PARAMETERIZED_TYPE_REF)
.flatMap((body) -> {
String id = request.exchange().getRequest().getId();
WebInput input = new WebInput(request.uri(), request.headers().asHttpHeaders(), body, id);
WebInput input = new WebInput(
request.uri(), request.headers().asHttpHeaders(), body,
request.exchange().getLocaleContext().getLocale(),
request.exchange().getRequest().getId());
if (logger.isDebugEnabled()) {
logger.debug("Executing: " + input);
}

View File

@@ -161,7 +161,8 @@ public class GraphQlWebSocketHandler implements WebSocketHandler {
if (id == null) {
return GraphQlStatus.close(session, GraphQlStatus.INVALID_MESSAGE_STATUS);
}
WebInput input = new WebInput(handshakeInfo.getUri(), handshakeInfo.getHeaders(), getPayload(map), id);
WebInput input = new WebInput(
handshakeInfo.getUri(), handshakeInfo.getHeaders(), getPayload(map), null, id);
if (logger.isDebugEnabled()) {
logger.debug("Executing: " + input);
}

View File

@@ -25,6 +25,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import reactor.core.publisher.Mono;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.graphql.web.WebGraphQlHandler;
import org.springframework.graphql.web.WebInput;
@@ -68,10 +69,15 @@ public class GraphQlHttpHandler {
* {@link HttpMediaTypeNotSupportedException}.
*/
public ServerResponse handleRequest(ServerRequest request) throws ServletException {
WebInput input = new WebInput(request.uri(), request.headers().asHttpHeaders(), readBody(request), null);
WebInput input = new WebInput(
request.uri(), request.headers().asHttpHeaders(), readBody(request),
LocaleContextHolder.getLocale(), null);
if (logger.isDebugEnabled()) {
logger.debug("Executing: " + input);
}
Mono<ServerResponse> responseMono = this.graphQlHandler.handleRequest(input).map((output) -> {
if (logger.isDebugEnabled()) {
logger.debug("Execution complete");
@@ -82,6 +88,7 @@ public class GraphQlHttpHandler {
}
return builder.body(output.toSpecification());
});
return ServerResponse.async(responseMono);
}

View File

@@ -156,7 +156,7 @@ public class GraphQlWebSocketHandler extends TextWebSocketHandler implements Sub
URI uri = session.getUri();
Assert.notNull(uri, "Expected handshake url");
HttpHeaders headers = session.getHandshakeHeaders();
WebInput input = new WebInput(uri, headers, getPayload(map), id);
WebInput input = new WebInput(uri, headers, getPayload(map), null, id);
if (logger.isDebugEnabled()) {
logger.debug("Executing: " + input);
}

View File

@@ -118,7 +118,7 @@ public class BatchMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService(controllerClass, CourseConfig.class)
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
List<Map<String, Object>> actualCourses = GraphQlTestUtils.checkErrorsAndGetData(result, "courses");
@@ -150,7 +150,7 @@ public class BatchMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService(controllerClass, CourseConfig.class)
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
List<Map<String, Object>> actualCourses = GraphQlTestUtils.checkErrorsAndGetData(result, "courses");

View File

@@ -74,7 +74,7 @@ public class SchemaMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService()
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
Map<String, Object> book = GraphQlTestUtils.checkErrorsAndGetData(result, "bookById");
@@ -96,7 +96,7 @@ public class SchemaMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService()
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
List<Map<String, Object>> bookList = GraphQlTestUtils.checkErrorsAndGetData(result, "booksByCriteria");
@@ -117,7 +117,7 @@ public class SchemaMappingInvocationTests {
"}";
AtomicReference<GraphQLContext> contextRef = new AtomicReference<>();
RequestInput requestInput = new RequestInput(query, null, null);
RequestInput requestInput = new RequestInput(query, null, null, null);
requestInput.configureExecutionInput((executionInput, builder) -> {
contextRef.set(executionInput.getGraphQLContext());
return executionInput;
@@ -147,7 +147,7 @@ public class SchemaMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService()
.execute(new RequestInput(operation, null, null))
.execute(new RequestInput(operation, null, null, null))
.block();
Map<String, Object> author = GraphQlTestUtils.checkErrorsAndGetData(result, "addAuthor");
@@ -166,7 +166,7 @@ public class SchemaMappingInvocationTests {
"}";
ExecutionResult result = initGraphQlService()
.execute(new RequestInput(operation, null, null))
.execute(new RequestInput(operation, null, null, null))
.block();
Publisher<ExecutionResult> publisher = GraphQlTestUtils.checkErrorsAndGetData(result);

View File

@@ -298,8 +298,9 @@ class QuerydslDataFetcherTests {
}
private WebInput input(String query) {
return new WebInput(URI.create("http://abc.org"), new HttpHeaders(),
Collections.singletonMap("query", query), "1");
return new WebInput(
URI.create("http://abc.org"), new HttpHeaders(), Collections.singletonMap("query", query),
null, "1");
}
interface BookProjection {

View File

@@ -72,7 +72,7 @@ public class BatchLoadingTests {
" }" +
"}";
RequestInput input = new RequestInput(query, null, null);
RequestInput input = new RequestInput(query, null, null, null);
ExecutionResult result = service.execute(input).block();
assertThat(result.getErrors()).isEmpty();

View File

@@ -84,7 +84,7 @@ public class ClassNameTypeResolverTests {
"}";
ExecutionResult result = new ExecutionGraphQlService(graphQlSource)
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
List<Map<String, Object>> actualAnimals = GraphQlTestUtils.checkErrorsAndGetData(result, "animals");
@@ -134,7 +134,7 @@ public class ClassNameTypeResolverTests {
"}";
ExecutionResult result = new ExecutionGraphQlService(graphQlSource)
.execute(new RequestInput(query, null, null))
.execute(new RequestInput(query, null, null, null))
.block();
List<Map<String, Object>> actualSightings = GraphQlTestUtils.checkErrorsAndGetData(result, "sightings");

View File

@@ -48,7 +48,8 @@ import static org.assertj.core.api.Assertions.assertThat;
public class WebGraphQlHandlerTests {
private static final WebInput webInput = new WebInput(
URI.create("http://abc.org"), new HttpHeaders(), Collections.singletonMap("query", "{ greeting }"), "1");
URI.create("http://abc.org"), new HttpHeaders(), Collections.singletonMap("query", "{ greeting }"),
null, "1");
@Test
void reactorContextPropagation() {

View File

@@ -37,8 +37,9 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class WebInterceptorTests {
private static final WebInput webInput = new WebInput(URI.create("http://abc.org"), new HttpHeaders(),
Collections.singletonMap("query", "{ notUsed }"), "1");
private static final WebInput webInput = new WebInput(
URI.create("http://abc.org"), new HttpHeaders(), Collections.singletonMap("query", "{ notUsed }"),
null, "1");
@Test
void interceptorOrder() {

View File

@@ -0,0 +1,110 @@
/*
* Copyright 2002-2021 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.web.webflux;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import graphql.GraphQL;
import graphql.schema.DataFetcher;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.GraphQlTestUtils;
import org.springframework.graphql.TestGraphQlSource;
import org.springframework.graphql.execution.ExecutionGraphQlService;
import org.springframework.graphql.web.WebGraphQlHandler;
import org.springframework.http.codec.EncoderHttpMessageWriter;
import org.springframework.http.codec.HttpMessageWriter;
import org.springframework.http.codec.json.Jackson2JsonEncoder;
import org.springframework.mock.http.server.reactive.MockServerHttpRequest;
import org.springframework.mock.http.server.reactive.MockServerHttpResponse;
import org.springframework.mock.web.reactive.function.server.MockServerRequest;
import org.springframework.mock.web.server.MockServerWebExchange;
import org.springframework.web.reactive.function.server.ServerResponse;
import org.springframework.web.reactive.result.view.ViewResolver;
import org.springframework.web.server.ServerWebExchange;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GraphQlHttpHandler}.
* @author Rossen Stoyanchev
*/
public class GraphQlHttpHandlerTests {
@Test
void locale() {
GraphQlHttpHandler handler = createHttpHandler(
"type Query { greeting: String }", "Query", "greeting",
(env) -> "Hello in " + env.getLocale());
MockServerHttpRequest httpRequest =
MockServerHttpRequest.post("/").acceptLanguageAsLocales(Locale.FRENCH).build();
MockServerHttpResponse httpResponse = handleRequest(
httpRequest, handler, Collections.singletonMap("query", "{greeting}"));
assertThat(httpResponse.getBodyAsString().block())
.isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}");
}
private GraphQlHttpHandler createHttpHandler(
String schemaContent, String type, String field, DataFetcher<Object> dataFetcher) {
GraphQL graphQl = GraphQlTestUtils.initGraphQl(schemaContent, type, field, dataFetcher);
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
return new GraphQlHttpHandler(WebGraphQlHandler.builder(service).build());
}
private MockServerHttpResponse handleRequest(
MockServerHttpRequest httpRequest, GraphQlHttpHandler handler, Map<String, String> body) {
MockServerWebExchange exchange = MockServerWebExchange.from(httpRequest);
MockServerRequest serverRequest = MockServerRequest.builder()
.exchange(exchange)
.uri(((ServerWebExchange) exchange).getRequest().getURI())
.method(((ServerWebExchange) exchange).getRequest().getMethod())
.headers(((ServerWebExchange) exchange).getRequest().getHeaders())
.body(Mono.just((Object) body));
handler.handleRequest(serverRequest)
.flatMap(response -> response.writeTo(exchange, new DefaultContext()))
.block();
return exchange.getResponse();
}
private static class DefaultContext implements ServerResponse.Context {
@Override
public List<HttpMessageWriter<?>> messageWriters() {
return Collections.singletonList(new EncoderHttpMessageWriter<>(new Jackson2JsonEncoder()));
}
@Override
public List<ViewResolver> viewResolvers() {
return Collections.emptyList();
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2002-2021 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.web.webmvc;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import javax.servlet.ServletException;
import graphql.GraphQL;
import graphql.schema.DataFetcher;
import org.junit.jupiter.api.Test;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.graphql.GraphQlService;
import org.springframework.graphql.GraphQlTestUtils;
import org.springframework.graphql.TestGraphQlSource;
import org.springframework.graphql.execution.ExecutionGraphQlService;
import org.springframework.graphql.web.WebGraphQlHandler;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.function.AsyncServerResponse;
import org.springframework.web.servlet.function.ServerRequest;
import org.springframework.web.servlet.function.ServerResponse;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link GraphQlHttpHandler}.
* @author Rossen Stoyanchev
*/
public class GraphQlHttpHandlerTests {
private static final List<HttpMessageConverter<?>> MESSAGE_READERS =
Collections.singletonList(new MappingJackson2HttpMessageConverter());
@Test
void locale() throws Exception {
GraphQlHttpHandler handler = createHttpHandler(
"type Query { greeting: String }", "Query", "greeting", (env) -> "Hello in " + env.getLocale());
MockHttpServletRequest servletRequest = new MockHttpServletRequest("POST", "/");
servletRequest.setContentType("application/json");
servletRequest.setContent("{\"query\":\"{ greeting }\"}".getBytes(StandardCharsets.UTF_8));
servletRequest.setAsyncSupported(true);
LocaleContextHolder.setLocale(Locale.FRENCH);
try {
MockHttpServletResponse servletResponse = handleRequest(servletRequest, handler);
assertThat(servletResponse.getContentAsString())
.isEqualTo("{\"data\":{\"greeting\":\"Hello in fr\"}}");
}
finally {
LocaleContextHolder.resetLocaleContext();
}
}
private GraphQlHttpHandler createHttpHandler(
String schemaContent, String type, String field, DataFetcher<Object> dataFetcher) {
GraphQL graphQl = GraphQlTestUtils.initGraphQl(schemaContent, type, field, dataFetcher);
GraphQlService service = new ExecutionGraphQlService(new TestGraphQlSource(graphQl));
return new GraphQlHttpHandler(WebGraphQlHandler.builder(service).build());
}
private MockHttpServletResponse handleRequest(
MockHttpServletRequest servletRequest, GraphQlHttpHandler handler) throws ServletException, IOException {
ServerRequest request = ServerRequest.create(servletRequest, MESSAGE_READERS);
ServerResponse response = ((AsyncServerResponse) handler.handleRequest(request)).block();
MockHttpServletResponse servletResponse = new MockHttpServletResponse();
response.writeTo(servletRequest, servletResponse, new DefaultContext());
return servletResponse;
}
private static class DefaultContext implements ServerResponse.Context {
@Override
public List<HttpMessageConverter<?>> messageConverters() {
return MESSAGE_READERS;
}
}
}