Skip to content

Commit dfaee2d

Browse files
committed
fix(#298): convert exception to graphql error
1 parent 9de944b commit dfaee2d

File tree

2 files changed

+40
-14
lines changed

2 files changed

+40
-14
lines changed

graphql-java-servlet/src/main/java/graphql/kickstart/servlet/HttpRequestInvokerImpl.java

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package graphql.kickstart.servlet;
22

3-
import static graphql.kickstart.servlet.HttpRequestHandler.STATUS_BAD_REQUEST;
4-
3+
import graphql.ExecutionResult;
54
import graphql.ExecutionResultImpl;
5+
import graphql.GraphQLException;
66
import graphql.kickstart.execution.GraphQLInvoker;
77
import graphql.kickstart.execution.GraphQLQueryResult;
88
import graphql.kickstart.execution.error.GenericGraphQLError;
@@ -15,6 +15,7 @@
1515
import java.io.UncheckedIOException;
1616
import java.util.Optional;
1717
import java.util.concurrent.CompletableFuture;
18+
import java.util.concurrent.CompletionException;
1819
import java.util.concurrent.atomic.AtomicReference;
1920
import javax.servlet.AsyncContext;
2021
import javax.servlet.http.HttpServletRequest;
@@ -82,7 +83,8 @@ private CompletableFuture<Void> invokeAndHandle(
8283
return invoke(invocationInput, request, response)
8384
.thenAccept(it -> writeResultResponse(invocationInput, it, request, response))
8485
.thenAccept(it -> listenerHandler.onSuccess())
85-
.exceptionally(t -> writeBadRequestError(t, response, listenerHandler))
86+
.exceptionally(
87+
t -> writeErrorResponse(invocationInput, request, response, listenerHandler, t))
8688
.thenAccept(it -> listenerHandler.onFinally());
8789
}
8890

@@ -99,18 +101,18 @@ private void writeResultResponse(
99101
}
100102
}
101103

102-
protected QueryResponseWriter createWriter(
103-
GraphQLInvocationInput invocationInput, GraphQLQueryResult queryResult) {
104-
return queryResponseWriterFactory.createWriter(invocationInput, queryResult, configuration);
105-
}
106-
107-
private Void writeBadRequestError(
108-
Throwable t, HttpServletResponse response, ListenerHandler listenerHandler) {
104+
private Void writeErrorResponse(
105+
GraphQLInvocationInput invocationInput,
106+
HttpServletRequest request,
107+
HttpServletResponse response,
108+
ListenerHandler listenerHandler,
109+
Throwable t) {
109110
if (!response.isCommitted()) {
110-
response.setStatus(STATUS_BAD_REQUEST);
111-
log.info(
112-
"Bad request: path was not \"/schema.json\" or no query variable named \"query\" given",
113-
t);
111+
writeResultResponse(
112+
invocationInput,
113+
GraphQLQueryResult.create(toErrorResult(t)),
114+
request,
115+
response);
114116
listenerHandler.onError(t);
115117
} else {
116118
log.warn(
@@ -119,6 +121,19 @@ private Void writeBadRequestError(
119121
return null;
120122
}
121123

124+
private ExecutionResult toErrorResult(Throwable t) {
125+
String message =
126+
t instanceof CompletionException && t.getCause() != null
127+
? t.getCause().getMessage()
128+
: t.getMessage();
129+
return new ExecutionResultImpl(new GenericGraphQLError(message));
130+
}
131+
132+
protected QueryResponseWriter createWriter(
133+
GraphQLInvocationInput invocationInput, GraphQLQueryResult queryResult) {
134+
return queryResponseWriterFactory.createWriter(invocationInput, queryResult, configuration);
135+
}
136+
122137
private CompletableFuture<GraphQLQueryResult> invoke(
123138
GraphQLInvocationInput invocationInput,
124139
HttpServletRequest request,

graphql-java-servlet/src/test/groovy/graphql/kickstart/servlet/cache/CachingHttpRequestInvokerTest.groovy

+11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
package graphql.kickstart.servlet.cache
22

3+
import graphql.ExecutionResult
34
import graphql.kickstart.execution.GraphQLInvoker
5+
import graphql.kickstart.execution.GraphQLObjectMapper
46
import graphql.kickstart.execution.GraphQLQueryResult
57
import graphql.kickstart.execution.input.GraphQLSingleInvocationInput
68
import graphql.kickstart.servlet.GraphQLConfiguration
79
import graphql.kickstart.servlet.HttpRequestInvoker
810
import spock.lang.Specification
911

12+
import javax.servlet.ServletOutputStream
1013
import javax.servlet.http.HttpServletRequest
1114
import javax.servlet.http.HttpServletResponse
1215
import java.util.concurrent.CompletableFuture
@@ -22,6 +25,8 @@ class CachingHttpRequestInvokerTest extends Specification {
2225
def httpRequestInvokerMock
2326
def graphqlInvoker
2427
def configuration
28+
def graphqlObjectMapper
29+
def outputStreamMock
2530

2631
def setup() {
2732
cacheReaderMock = Mock(CacheReader)
@@ -32,11 +37,17 @@ class CachingHttpRequestInvokerTest extends Specification {
3237
configuration = Mock(GraphQLConfiguration)
3338
httpRequestInvokerMock = Mock(HttpRequestInvoker)
3439
graphqlInvoker = Mock(GraphQLInvoker)
40+
graphqlObjectMapper = Mock(GraphQLObjectMapper)
41+
outputStreamMock = Mock(ServletOutputStream)
3542
cachingInvoker = new CachingHttpRequestInvoker(configuration, httpRequestInvokerMock, cacheReaderMock)
3643

3744
configuration.getResponseCacheManager() >> responseCacheManagerMock
3845
configuration.getGraphQLInvoker() >> graphqlInvoker
46+
configuration.getObjectMapper() >> graphqlObjectMapper
47+
graphqlObjectMapper.serializeResultAsBytes(_ as ExecutionResult) >> new byte[0]
3948
graphqlInvoker.queryAsync(invocationInputMock) >> CompletableFuture.completedFuture(Mock(GraphQLQueryResult))
49+
50+
responseMock.getOutputStream() >> outputStreamMock
4051
}
4152

4253
def "should execute regular invoker if cache not exists"() {

0 commit comments

Comments
 (0)