Skip to content

Commit

Permalink
improve query param handling fixes #58
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy2003 committed Oct 28, 2019
1 parent 0f5d66d commit 0f15bcd
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 37 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.leangen.graphql.spqr.spring.autoconfigure;

import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import io.leangen.graphql.spqr.spring.web.GraphQLController;
Expand Down Expand Up @@ -40,8 +41,8 @@ public GraphQLServletExecutor graphQLExecutor(ServletContextFactory contextFacto
@ConditionalOnProperty(name = "graphql.spqr.http.enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(GraphQLController.class)
@ConditionalOnBean(GraphQLSchema.class)
public DefaultGraphQLController graphQLController(GraphQL graphQL, GraphQLServletExecutor executor) {
return new DefaultGraphQLController(graphQL, executor);
public DefaultGraphQLController graphQLController(GraphQL graphQL, GraphQLServletExecutor executor, ObjectMapper objectMapper) {
return new DefaultGraphQLController(graphQL, executor, objectMapper);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package io.leangen.graphql.spqr.spring.autoconfigure;

import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import graphql.schema.GraphQLSchema;
import io.leangen.graphql.module.Module;
import io.leangen.graphql.spqr.spring.autoconfigure.reactive.FluxAdapter;
import io.leangen.graphql.spqr.spring.autoconfigure.reactive.MonoAdapter;
import io.leangen.graphql.spqr.spring.web.GraphQLController;
import io.leangen.graphql.spqr.spring.web.reactive.GraphQLReactiveExecutor;
import io.leangen.graphql.spqr.spring.web.GuiController;
import io.leangen.graphql.spqr.spring.web.reactive.DefaultGraphQLExecutor;
import io.leangen.graphql.spqr.spring.web.reactive.DefaultGraphQLController;
import io.leangen.graphql.spqr.spring.web.reactive.DefaultGraphQLExecutor;
import io.leangen.graphql.spqr.spring.web.reactive.GraphQLReactiveExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand Down Expand Up @@ -53,8 +54,8 @@ public GraphQLReactiveExecutor graphQLExecutor(ReactiveContextFactory contextFac
@ConditionalOnProperty(name = "graphql.spqr.http.enabled", havingValue = "true", matchIfMissing = true)
@ConditionalOnMissingBean(GraphQLController.class)
@ConditionalOnBean(GraphQLSchema.class)
public DefaultGraphQLController graphQLController(GraphQL graphQL, GraphQLReactiveExecutor executor) {
return new DefaultGraphQLController(graphQL, executor);
public DefaultGraphQLController graphQLController(GraphQL graphQL, GraphQLReactiveExecutor executor, ObjectMapper objectMapper) {
return new DefaultGraphQLController(graphQL, executor, objectMapper);
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
package io.leangen.graphql.spqr.spring.web;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import io.leangen.graphql.spqr.spring.web.dto.GraphQLRequest;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.Map;
import org.springframework.web.bind.annotation.*;

@RestController
public abstract class GraphQLController<R> {

protected final GraphQL graphQL;
protected final GraphQLExecutor<R> executor;
private ObjectMapper objectMapper;

public GraphQLController(GraphQL graphQL, GraphQLExecutor<R> executor) {
public GraphQLController(GraphQL graphQL, GraphQLExecutor<R> executor, ObjectMapper objectMapper) {
this.graphQL = graphQL;
this.executor = executor;
this.objectMapper = objectMapper;
}

@PostMapping(
Expand All @@ -33,11 +31,14 @@ public GraphQLController(GraphQL graphQL, GraphQLExecutor<R> executor) {
)
@ResponseBody
public Object executeJsonPost(@RequestBody GraphQLRequest requestBody,
GraphQLRequest requestParams,
R request) {
String query = requestParams.getQuery() == null ? requestBody.getQuery() : requestParams.getQuery();
String operationName = requestParams.getOperationName() == null ? requestBody.getOperationName() : requestParams.getOperationName();
Map<String, Object> variables = requestParams.getVariables() == null ? requestBody.getVariables() : requestParams.getVariables();
@RequestParam(value = "query", required = false) String requestQuery,
@RequestParam(value = "operationName", required = false) String requestOperationName,
@RequestParam(value = "variables", required = false) String variablesJsonString,
R request) throws IOException {
String query = requestQuery == null ? requestBody.getQuery() : requestQuery;
String operationName = requestOperationName == null ? requestBody.getOperationName() : requestOperationName;
//noinspection unchecked
Map<String, Object> variables = variablesJsonString == null ? requestBody.getVariables() : objectMapper.readValue(variablesJsonString, Map.class);

return executor.execute(graphQL, new GraphQLRequest(query, operationName, variables), request);
}
Expand Down Expand Up @@ -80,7 +81,12 @@ public Object executeFormPost(@RequestParam Map<String, String> queryParams,
headers = "Connection!=Upgrade"
)
@ResponseBody
public Object executeGet(GraphQLRequest graphQLRequest, R request) {
return executor.execute(graphQL, graphQLRequest, request);
public Object executeGet(@RequestParam(value = "query") String requestQuery,
@RequestParam(value = "operationName", required = false) String requestOperationName,
@RequestParam(value = "variables", required = false) String variablesJsonString,
R request) throws IOException {
//noinspection unchecked
Map<String, Object> variables = variablesJsonString == null ? Collections.emptyMap() : objectMapper.readValue(variablesJsonString, Map.class);
return executor.execute(graphQL, new GraphQLRequest(requestQuery, requestOperationName, variables), request);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.leangen.graphql.spqr.spring.web.reactive;

import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import io.leangen.graphql.spqr.spring.web.GraphQLController;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -12,7 +13,7 @@
public class DefaultGraphQLController extends GraphQLController<ServerWebExchange> {

@Autowired
public DefaultGraphQLController(GraphQL graphQL, GraphQLReactiveExecutor executor) {
super(graphQL, executor);
public DefaultGraphQLController(GraphQL graphQL, GraphQLReactiveExecutor executor, ObjectMapper objectMapper) {
super(graphQL, executor, objectMapper);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.leangen.graphql.spqr.spring.web.servlet;

import com.fasterxml.jackson.databind.ObjectMapper;
import graphql.GraphQL;
import io.leangen.graphql.spqr.spring.web.GraphQLController;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -12,7 +13,7 @@
public class DefaultGraphQLController extends GraphQLController<NativeWebRequest> {

@Autowired
public DefaultGraphQLController(GraphQL graphQL, GraphQLServletExecutor executor) {
super(graphQL, executor);
public DefaultGraphQLController(GraphQL graphQL, GraphQLServletExecutor executor, ObjectMapper objectMapper) {
super(graphQL, executor, objectMapper);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package io.leangen.graphql.spqr.spring.test;

import java.lang.reflect.Method;
import java.util.Arrays;

import io.leangen.graphql.ExtensionProvider;
import io.leangen.graphql.GeneratorConfiguration;
import io.leangen.graphql.annotations.GraphQLArgument;
import io.leangen.graphql.annotations.GraphQLQuery;
import io.leangen.graphql.metadata.strategy.query.BeanResolverBuilder;
import io.leangen.graphql.metadata.strategy.query.PublicResolverBuilder;
Expand All @@ -13,9 +17,7 @@
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Arrays;
import org.springframework.web.multipart.MultipartFile;

@Configuration
public class ResolverBuilder_TestConfig {
Expand All @@ -41,11 +43,16 @@ protected boolean isQuery(Method method, ResolverBuilderParams params) {

@Component("annotatedOperationSourceBean")
@GraphQLApi
private static class AnnotatedOperationSourceBean {
public static class AnnotatedOperationSourceBean {
@GraphQLQuery(name = "greetingFromAnnotatedSource_wiredAsComponent")
public String getGreeting(){
return "Hello world !";
}

@GraphQLQuery(name = "echo")
public String echo(@GraphQLArgument(name = "content") String content) {
return content;
}
}

@Bean
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package io.leangen.graphql.spqr.spring.web;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import io.leangen.graphql.spqr.spring.autoconfigure.SpqrAutoConfiguration;
import io.leangen.graphql.spqr.spring.autoconfigure.SpqrMvcAutoConfiguration;
import io.leangen.graphql.spqr.spring.test.ResolverBuilder_TestConfig;
Expand All @@ -14,9 +17,6 @@
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
Expand Down Expand Up @@ -109,14 +109,37 @@ public void defaultControllerTest_POST_applicationJson_INVALID() throws Exceptio
@Test
public void defaultControllerTest_POST_applicationJson_overridingQueryParams() throws Exception {
mockMvc.perform(
post("/"+apiContext)
.param("query","{greetingFromBeanSource_wiredAsComponent_byAnnotation}")
post("/" + apiContext)
.param("query", "{greetingFromBeanSource_wiredAsComponent_byAnnotation}")
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"query\":\"{INVALID_QUERY}\",\"variables\":null,\"operationName\":null}"))
.andExpect(status().isOk())
.andExpect(content().string(containsString("Hello world")));
}

@Test
public void defaultControllerTest_GET_with_variables() throws Exception {
mockMvc.perform(
get("/" + apiContext)
.param("query", "query Echo($contentInput: String){ echo(content: $contentInput)}")
.param("variables", "{\"contentInput\": \"Hello world\"}")
)
.andExpect(status().isOk())
.andExpect(content().json("{\"data\":{\"echo\":\"Hello world\"}}", true));
}

@Test
public void defaultControllerTest_POST_with_variables() throws Exception {
mockMvc.perform(
post("/" + apiContext)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content("{\"query\":\"{INVALID_QUERY}\",\"variables\":{\"contentInput\": \"Hello world2\"},\"operationName\":null}")
.param("query", "query Echo($contentInput: String){ echo(content: $contentInput)}")
.param("variables", "{\"contentInput\": \"Hello world1\"}"))
.andExpect(status().isOk())
.andExpect(content().json("{\"data\":{\"echo\":\"Hello world1\"}}", true));
}

@Test
public void defaultControllerTest_POST_formUrlEncoded_INVALID() throws Exception {
mockMvc.perform(
Expand Down

0 comments on commit 0f15bcd

Please sign in to comment.