diff --git a/src/main/java/graphql/servlet/GraphQLServlet.java b/src/main/java/graphql/servlet/GraphQLServlet.java index f9a026f2..76a38a42 100644 --- a/src/main/java/graphql/servlet/GraphQLServlet.java +++ b/src/main/java/graphql/servlet/GraphQLServlet.java @@ -1,5 +1,6 @@ package graphql.servlet; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationContext; @@ -479,6 +480,7 @@ private Boolean isArrayStart(String s) { return null; } + @JsonIgnoreProperties(ignoreUnknown = true) protected static class GraphQLRequest { private String query; @JsonDeserialize(using = GraphQLServlet.VariablesDeserializer.class) @@ -510,6 +512,7 @@ public void setOperationName(String operationName) { } } + @JsonIgnoreProperties(ignoreUnknown = true) protected static class GraphQLResponse { private int status; private String response; diff --git a/src/test/groovy/graphql/servlet/GraphQLServletSpec.groovy b/src/test/groovy/graphql/servlet/GraphQLServletSpec.groovy index 9082a948..e82d1ad9 100644 --- a/src/test/groovy/graphql/servlet/GraphQLServletSpec.groovy +++ b/src/test/groovy/graphql/servlet/GraphQLServletSpec.groovy @@ -167,6 +167,20 @@ class GraphQLServletSpec extends Specification { getResponseContent().data.echo == "test" } + def "query over HTTP GET with unknown property 'test' returns data"() { + setup: + request.addParameter('query', 'query { echo(arg:"test") }') + request.addParameter('test', 'test') + + when: + servlet.doGet(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getResponseContent().data.echo == "test" + } + def "batched query over HTTP GET returns data"() { setup: request.addParameter('query', '[{ "query": "query { echo(arg:\\"test\\") }" }, { "query": "query { echo(arg:\\"test\\") }" }]') @@ -237,6 +251,20 @@ class GraphQLServletSpec extends Specification { getBatchedResponseContent()[1].data.echo == "test" } + def "batched query over HTTP GET with unknown property 'test' returns data"() { + setup: + request.addParameter('query', '[{ "query": "query { echo(arg:\\"test\\") }", "test": "test" }, { "query": "query { echo(arg:\\"test\\") }", "test": "test" }]') + + when: + servlet.doGet(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getBatchedResponseContent()[0].data.echo == "test" + getBatchedResponseContent()[1].data.echo == "test" + } + def "mutation over HTTP GET returns errors"() { setup: request.addParameter('query', 'mutation { echo(arg:"test") }') @@ -336,6 +364,22 @@ class GraphQLServletSpec extends Specification { getResponseContent().data.echo == "test" } + def "query over HTTP POST body with unknown property 'test' returns data"() { + setup: + request.setContent(mapper.writeValueAsBytes([ + query: 'query { echo(arg:"test") }', + test: 'test' + ])) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getResponseContent().data.echo == "test" + } + def "query over HTTP POST multipart named 'graphql' returns data"() { setup: request.setContentType("multipart/form-data, boundary=test") @@ -426,6 +470,24 @@ class GraphQLServletSpec extends Specification { getResponseContent().data.echo == "test" } + def "query over HTTP POST multipart named 'query' with unknown property 'test' returns data"() { + setup: + request.setContentType("multipart/form-data, boundary=test") + request.setMethod("POST") + request.setContent(new TestMultipartContentBuilder() + .addPart('query', 'query { echo(arg:"test") }') + .addPart('test', 'test') + .build()) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getResponseContent().data.echo == "test" + } + def "batched query over HTTP POST body returns data"() { setup: request.setContent('[{ "query": "query { echo(arg:\\"test\\") }" }, { "query": "query { echo(arg:\\"test\\") }" }]'.bytes) @@ -484,6 +546,20 @@ class GraphQLServletSpec extends Specification { getBatchedResponseContent()[1].data.echo == "test" } + def "batched query over HTTP POST body with unknown property 'test' returns data"() { + setup: + request.setContent('[{ "query": "query { echo(arg:\\"test\\") }", "test": "test" }, { "query": "query { echo(arg:\\"test\\") }", "test": "test" }]'.bytes) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getBatchedResponseContent()[0].data.echo == "test" + getBatchedResponseContent()[1].data.echo == "test" + } + def "batched query over HTTP POST multipart named 'graphql' returns data"() { setup: request.setContentType("multipart/form-data, boundary=test") @@ -503,6 +579,25 @@ class GraphQLServletSpec extends Specification { getBatchedResponseContent()[1].data.echo == "test" } + def "batched query over HTTP POST multipart named 'graphql' with unknown property 'test' returns data"() { + setup: + request.setContentType("multipart/form-data, boundary=test") + request.setMethod("POST") + + request.setContent(new TestMultipartContentBuilder() + .addPart('graphql', '[{ "query": "query { echo(arg:\\"test\\") }", "test": "test" }, { "query": "query { echo(arg:\\"test\\") }", "test": "test" }]') + .build()) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getBatchedResponseContent()[0].data.echo == "test" + getBatchedResponseContent()[1].data.echo == "test" + } + def "batched query over HTTP POST multipart named 'query' returns data"() { setup: request.setContentType("multipart/form-data, boundary=test") @@ -577,6 +672,24 @@ class GraphQLServletSpec extends Specification { getBatchedResponseContent()[1].data.echo == "test" } + def "batched query over HTTP POST multipart named 'query' with unknown property 'test' returns data"() { + setup: + request.setContentType("multipart/form-data, boundary=test") + request.setMethod("POST") + request.setContent(new TestMultipartContentBuilder() + .addPart('query', '[{ "query": "query { echo(arg:\\"test\\") }", "test": "test" }, { "query": "query { echo(arg:\\"test\\") }", "test": "test" }]') + .build()) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getBatchedResponseContent()[0].data.echo == "test" + getBatchedResponseContent()[1].data.echo == "test" + } + def "mutation over HTTP POST body returns data"() { setup: request.setContent(mapper.writeValueAsBytes([ @@ -606,6 +719,20 @@ class GraphQLServletSpec extends Specification { getBatchedResponseContent()[1].data.echo == "test" } + def "batched mutation over HTTP POST body with unknown property 'test' returns data"() { + setup: + request.setContent('[{ "query": "mutation { echo(arg:\\"test\\") }", "test": "test" }, { "query": "mutation { echo(arg:\\"test\\") }", "test": "test" }]'.bytes) + + when: + servlet.doPost(request, response) + + then: + response.getStatus() == STATUS_OK + response.getContentType() == CONTENT_TYPE_JSON_UTF8 + getBatchedResponseContent()[0].data.echo == "test" + getBatchedResponseContent()[1].data.echo == "test" + } + def "errors before graphql schema execution return internal server error"() { setup: servlet = new SimpleGraphQLServlet(servlet.getSchemaProvider().getSchema()) {