Skip to content

Commit e943f42

Browse files
tinnoubbakerman
authored andcommitted
Subscriptions against a schema without subscription support should result in a GraphQLError
1 parent 68f5975 commit e943f42

File tree

7 files changed

+99
-65
lines changed

7 files changed

+99
-65
lines changed

src/main/java/graphql/ErrorType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ public enum ErrorType {
99
InvalidSyntax,
1010
ValidationError,
1111
DataFetchingException,
12-
MutationNotSupported,
12+
OperationNotSupported,
1313
ExecutionAborted
1414
}

src/main/java/graphql/MutationNotSupportedError.java

Lines changed: 0 additions & 46 deletions
This file was deleted.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package graphql;
2+
3+
import java.util.Collections;
4+
import java.util.List;
5+
6+
import graphql.language.SourceLocation;
7+
8+
/**
9+
* The graphql spec says that subscriptions and mutations are optional but it does not specify how to respond
10+
* when either or both are not supported. This error is returned in this case.
11+
*
12+
* http://facebook.github.io/graphql/#sec-Initial-types
13+
*/
14+
public class OperationNotSupportedError implements GraphQLError {
15+
16+
private List<SourceLocation> sourceLocations;
17+
private String message;
18+
19+
public OperationNotSupportedError(String message, SourceLocation sourceLocation) {
20+
this.message = message;
21+
this.sourceLocations = sourceLocation == null ? null : Collections.singletonList(sourceLocation);
22+
}
23+
24+
@Override
25+
public String getMessage() {
26+
return message;
27+
}
28+
29+
@Override
30+
public List<SourceLocation> getLocations() {
31+
return sourceLocations;
32+
}
33+
34+
@Override
35+
public ErrorType getErrorType() {
36+
return ErrorType.OperationNotSupported;
37+
}
38+
39+
@Override
40+
public String toString() {
41+
return "OperationNotSupportedError{" +
42+
"sourceLocations=" + sourceLocations +
43+
", message='" + message + '\'' +
44+
'}';
45+
}
46+
47+
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
48+
@Override
49+
public boolean equals(Object o) {
50+
return GraphqlErrorHelper.equals(this, o);
51+
}
52+
53+
@Override
54+
public int hashCode() {
55+
return GraphqlErrorHelper.hashCode(this);
56+
}
57+
}

src/main/java/graphql/execution/Execution.java

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,19 @@
11
package graphql.execution;
22

33

4+
import java.util.Collections;
5+
import java.util.List;
6+
import java.util.Map;
7+
import java.util.concurrent.CompletableFuture;
8+
import org.slf4j.Logger;
9+
import org.slf4j.LoggerFactory;
10+
411
import graphql.ExecutionInput;
512
import graphql.ExecutionResult;
613
import graphql.ExecutionResultImpl;
714
import graphql.GraphQLError;
815
import graphql.Internal;
9-
import graphql.MutationNotSupportedError;
16+
import graphql.OperationNotSupportedError;
1017
import graphql.execution.instrumentation.Instrumentation;
1118
import graphql.execution.instrumentation.InstrumentationContext;
1219
import graphql.execution.instrumentation.InstrumentationState;
@@ -20,13 +27,6 @@
2027
import graphql.language.VariableDefinition;
2128
import graphql.schema.GraphQLObjectType;
2229
import graphql.schema.GraphQLSchema;
23-
import org.slf4j.Logger;
24-
import org.slf4j.LoggerFactory;
25-
26-
import java.util.Collections;
27-
import java.util.List;
28-
import java.util.Map;
29-
import java.util.concurrent.CompletableFuture;
3030

3131
import static graphql.Assert.assertShouldNeverHappen;
3232
import static graphql.execution.ExecutionContextBuilder.newExecutionContextBuilder;
@@ -114,7 +114,14 @@ private CompletableFuture<ExecutionResult> executeOperation(ExecutionContext exe
114114
// for the record earlier code has asserted that we have a query type in the schema since the spec says this is
115115
// ALWAYS required
116116
if (operation == MUTATION && operationRootType == null) {
117-
CompletableFuture<ExecutionResult> resultCompletableFuture = completedFuture(new ExecutionResultImpl(Collections.singletonList(new MutationNotSupportedError())));
117+
OperationNotSupportedError mutationNotSupportedError = new OperationNotSupportedError("Schema is not configured for mutations.", operationDefinition.getSourceLocation());
118+
CompletableFuture<ExecutionResult> resultCompletableFuture = completedFuture(
119+
new ExecutionResultImpl(Collections.singletonList(mutationNotSupportedError)));
120+
executionDispatchCtx.onEnd(resultCompletableFuture, null);
121+
return resultCompletableFuture;
122+
} else if (operation == SUBSCRIPTION && operationRootType == null) {
123+
OperationNotSupportedError subscriptionNotSupportedError = new OperationNotSupportedError("Schema is not configured for subscriptions.", operationDefinition.getSourceLocation());
124+
CompletableFuture<ExecutionResult> resultCompletableFuture = completedFuture(new ExecutionResultImpl(Collections.singletonList(subscriptionNotSupportedError)));
118125
executionDispatchCtx.onEnd(resultCompletableFuture, null);
119126
return resultCompletableFuture;
120127
}

src/test/groovy/example/http/ExecutionResultJSONTesting.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package example.http;
22

3+
import javax.servlet.http.HttpServletResponse;
4+
import java.io.IOException;
5+
import java.util.ArrayList;
6+
import java.util.List;
37
import com.fasterxml.jackson.databind.ObjectMapper;
48
import com.google.gson.Gson;
59
import com.google.gson.GsonBuilder;
10+
611
import graphql.ExceptionWhileDataFetching;
712
import graphql.ExecutionResult;
813
import graphql.ExecutionResultImpl;
914
import graphql.GraphQLError;
1015
import graphql.InvalidSyntaxError;
11-
import graphql.MutationNotSupportedError;
16+
import graphql.OperationNotSupportedError;
1217
import graphql.SerializationError;
1318
import graphql.execution.ExecutionPath;
1419
import graphql.execution.ExecutionTypeInfo;
@@ -20,11 +25,6 @@
2025
import graphql.validation.ValidationError;
2126
import graphql.validation.ValidationErrorType;
2227

23-
import javax.servlet.http.HttpServletResponse;
24-
import java.io.IOException;
25-
import java.util.ArrayList;
26-
import java.util.List;
27-
2828
import static java.util.Arrays.stream;
2929
import static java.util.stream.Collectors.toList;
3030

@@ -71,7 +71,7 @@ private ExecutionResult createER() {
7171
List<GraphQLError> errors = new ArrayList<>();
7272

7373
errors.add(new ValidationError(ValidationErrorType.UnknownType, mkLocations(), "Test ValidationError"));
74-
errors.add(new MutationNotSupportedError());
74+
errors.add(new OperationNotSupportedError("Mutations are not supported.", null));
7575
errors.add(new InvalidSyntaxError(mkLocations(), "Not good syntax m'kay"));
7676
errors.add(new NonNullableFieldWasNullError(new NonNullableFieldWasNullException(mkTypeInfo(), mkPath())));
7777
errors.add(new SerializationError(mkPath(), new CoercingSerializeException("Bad coercing")));

src/test/groovy/graphql/GraphQLErrorTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class GraphQLErrorTest extends Specification {
3030
message : "Validation error of type UnknownType: Test ValidationError",
3131
]
3232

33-
new MutationNotSupportedError() |
33+
new OperationNotSupportedError("Mutations are not supported on this schema", null) |
3434
[
3535
message: "Mutations are not supported on this schema",
3636
]

src/test/groovy/graphql/GraphQLTest.groovy

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,25 @@ class GraphQLTest extends Specification {
266266

267267
then:
268268
result.errors.size() == 1
269-
result.errors[0].class == MutationNotSupportedError
269+
result.errors[0].class == OperationNotSupportedError
270270
}
271271

272+
def "a subscription query against a schema that doesn't support subscriptions should result in a GraphQL error"() {
273+
given:
274+
275+
GraphQLSchema schema = newSchema().query(
276+
newObject()
277+
.name("Query")
278+
)
279+
.build()
280+
281+
when:
282+
def result = new GraphQL(schema).execute("subscription { doesNotExist }")
283+
284+
then:
285+
result.errors.size() == 1
286+
result.errors[0].class == OperationNotSupportedError
287+
}
272288

273289
def "query with int literal too large"() {
274290
given:

0 commit comments

Comments
 (0)