1
1
package graphql .kickstart .servlet ;
2
2
3
+ import com .fasterxml .jackson .core .JsonProcessingException ;
3
4
import graphql .GraphQLException ;
4
5
import graphql .kickstart .execution .GraphQLInvoker ;
5
6
import graphql .kickstart .execution .GraphQLQueryResult ;
9
10
import graphql .kickstart .servlet .input .BatchInputPreProcessResult ;
10
11
import graphql .kickstart .servlet .input .BatchInputPreProcessor ;
11
12
import java .io .IOException ;
13
+ import java .io .UncheckedIOException ;
14
+ import java .util .concurrent .CompletableFuture ;
15
+ import javax .servlet .AsyncContext ;
12
16
import javax .servlet .http .HttpServletRequest ;
13
17
import javax .servlet .http .HttpServletResponse ;
14
18
import lombok .extern .slf4j .Slf4j ;
@@ -36,11 +40,11 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
36
40
GraphQLInvocationInput invocationInput = invocationInputParser
37
41
.getGraphQLInvocationInput (request , response );
38
42
execute (invocationInput , request , response );
39
- } catch (GraphQLException e ) {
43
+ } catch (GraphQLException | JsonProcessingException e ) {
40
44
response .setStatus (STATUS_BAD_REQUEST );
41
45
log .info ("Bad request: cannot handle http request" , e );
42
46
throw e ;
43
- } catch (Throwable t ) {
47
+ } catch (Exception t ) {
44
48
response .setStatus (500 );
45
49
log .error ("Cannot handle http request" , t );
46
50
throw t ;
@@ -49,38 +53,65 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
49
53
50
54
protected void execute (GraphQLInvocationInput invocationInput , HttpServletRequest request ,
51
55
HttpServletResponse response ) throws IOException {
52
- GraphQLQueryResult queryResult = invoke (invocationInput , request , response );
56
+ if (request .isAsyncSupported ()) {
57
+ AsyncContext asyncContext = request .isAsyncStarted ()
58
+ ? request .getAsyncContext ()
59
+ : request .startAsync (request , response );
60
+ asyncContext .setTimeout (configuration .getAsyncTimeout ());
61
+ invoke (invocationInput , request , response )
62
+ .thenAccept (result -> writeResultResponse (invocationInput , result , request , response ))
63
+ .exceptionally (t -> writeErrorResponse (t , response ))
64
+ .thenAccept (aVoid -> asyncContext .complete ());
65
+ } else {
66
+ try {
67
+ GraphQLQueryResult result = invoke (invocationInput , request , response ).join ();
68
+ writeResultResponse (invocationInput , result , request , response );
69
+ } catch (Exception t ) {
70
+ writeErrorResponse (t , response );
71
+ }
72
+ }
73
+ }
53
74
75
+ private void writeResultResponse (GraphQLInvocationInput invocationInput , GraphQLQueryResult queryResult , HttpServletRequest request ,
76
+ HttpServletResponse response ) {
54
77
QueryResponseWriter queryResponseWriter = createWriter (invocationInput , queryResult );
55
- queryResponseWriter .write (request , response );
78
+ try {
79
+ queryResponseWriter .write (request , response );
80
+ } catch (IOException e ) {
81
+ throw new UncheckedIOException (e );
82
+ }
56
83
}
57
84
58
- protected QueryResponseWriter createWriter (GraphQLInvocationInput invocationInput ,
59
- GraphQLQueryResult queryResult ) {
85
+ protected QueryResponseWriter createWriter (GraphQLInvocationInput invocationInput , GraphQLQueryResult queryResult ) {
60
86
return QueryResponseWriter .createWriter (queryResult , configuration .getObjectMapper (),
61
87
configuration .getSubscriptionTimeout ());
62
88
}
63
89
64
- private GraphQLQueryResult invoke (GraphQLInvocationInput invocationInput ,
65
- HttpServletRequest request ,
90
+ private Void writeErrorResponse (Throwable t , HttpServletResponse response ) {
91
+ response .setStatus (STATUS_BAD_REQUEST );
92
+ log .info ("Bad GET request: path was not \" /schema.json\" or no query variable named \" query\" given" , t );
93
+ return null ;
94
+ }
95
+
96
+ private CompletableFuture <GraphQLQueryResult > invoke (GraphQLInvocationInput invocationInput , HttpServletRequest request ,
66
97
HttpServletResponse response ) {
67
98
if (invocationInput instanceof GraphQLSingleInvocationInput ) {
68
- return graphQLInvoker .query (invocationInput );
99
+ return graphQLInvoker .queryAsync (invocationInput );
69
100
}
70
101
return invokeBatched ((GraphQLBatchedInvocationInput ) invocationInput , request , response );
71
102
}
72
103
73
- private GraphQLQueryResult invokeBatched (GraphQLBatchedInvocationInput batchedInvocationInput ,
104
+ private CompletableFuture < GraphQLQueryResult > invokeBatched (GraphQLBatchedInvocationInput batchedInvocationInput ,
74
105
HttpServletRequest request ,
75
106
HttpServletResponse response ) {
76
107
BatchInputPreProcessor preprocessor = configuration .getBatchInputPreProcessor ();
77
108
BatchInputPreProcessResult result = preprocessor
78
109
.preProcessBatch (batchedInvocationInput , request , response );
79
110
if (result .isExecutable ()) {
80
- return graphQLInvoker .query (result .getBatchedInvocationInput ());
111
+ return graphQLInvoker .queryAsync (result .getBatchedInvocationInput ());
81
112
}
82
113
83
- return GraphQLQueryResult .createError (result .getStatusCode (), result .getStatusMessage ());
114
+ return CompletableFuture . completedFuture ( GraphQLQueryResult .createError (result .getStatusCode (), result .getStatusMessage () ));
84
115
}
85
116
86
117
}
0 commit comments