11package graphql .kickstart .servlet ;
22
3+ import com .fasterxml .jackson .core .JsonProcessingException ;
34import graphql .GraphQLException ;
45import graphql .kickstart .execution .GraphQLInvoker ;
56import graphql .kickstart .execution .GraphQLQueryResult ;
910import graphql .kickstart .servlet .input .BatchInputPreProcessResult ;
1011import graphql .kickstart .servlet .input .BatchInputPreProcessor ;
1112import java .io .IOException ;
13+ import java .io .UncheckedIOException ;
14+ import java .util .concurrent .CompletableFuture ;
15+ import javax .servlet .AsyncContext ;
1216import javax .servlet .http .HttpServletRequest ;
1317import javax .servlet .http .HttpServletResponse ;
1418import lombok .extern .slf4j .Slf4j ;
@@ -36,11 +40,11 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
3640 GraphQLInvocationInput invocationInput = invocationInputParser
3741 .getGraphQLInvocationInput (request , response );
3842 execute (invocationInput , request , response );
39- } catch (GraphQLException e ) {
43+ } catch (GraphQLException | JsonProcessingException e ) {
4044 response .setStatus (STATUS_BAD_REQUEST );
4145 log .info ("Bad request: cannot handle http request" , e );
4246 throw e ;
43- } catch (Throwable t ) {
47+ } catch (Exception t ) {
4448 response .setStatus (500 );
4549 log .error ("Cannot handle http request" , t );
4650 throw t ;
@@ -49,38 +53,65 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr
4953
5054 protected void execute (GraphQLInvocationInput invocationInput , HttpServletRequest request ,
5155 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+ }
5374
75+ private void writeResultResponse (GraphQLInvocationInput invocationInput , GraphQLQueryResult queryResult , HttpServletRequest request ,
76+ HttpServletResponse response ) {
5477 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+ }
5683 }
5784
58- protected QueryResponseWriter createWriter (GraphQLInvocationInput invocationInput ,
59- GraphQLQueryResult queryResult ) {
85+ protected QueryResponseWriter createWriter (GraphQLInvocationInput invocationInput , GraphQLQueryResult queryResult ) {
6086 return QueryResponseWriter .createWriter (queryResult , configuration .getObjectMapper (),
6187 configuration .getSubscriptionTimeout ());
6288 }
6389
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 ,
6697 HttpServletResponse response ) {
6798 if (invocationInput instanceof GraphQLSingleInvocationInput ) {
68- return graphQLInvoker .query (invocationInput );
99+ return graphQLInvoker .queryAsync (invocationInput );
69100 }
70101 return invokeBatched ((GraphQLBatchedInvocationInput ) invocationInput , request , response );
71102 }
72103
73- private GraphQLQueryResult invokeBatched (GraphQLBatchedInvocationInput batchedInvocationInput ,
104+ private CompletableFuture < GraphQLQueryResult > invokeBatched (GraphQLBatchedInvocationInput batchedInvocationInput ,
74105 HttpServletRequest request ,
75106 HttpServletResponse response ) {
76107 BatchInputPreProcessor preprocessor = configuration .getBatchInputPreProcessor ();
77108 BatchInputPreProcessResult result = preprocessor
78109 .preProcessBatch (batchedInvocationInput , request , response );
79110 if (result .isExecutable ()) {
80- return graphQLInvoker .query (result .getBatchedInvocationInput ());
111+ return graphQLInvoker .queryAsync (result .getBatchedInvocationInput ());
81112 }
82113
83- return GraphQLQueryResult .createError (result .getStatusCode (), result .getStatusMessage ());
114+ return CompletableFuture . completedFuture ( GraphQLQueryResult .createError (result .getStatusCode (), result .getStatusMessage () ));
84115 }
85116
86117}
0 commit comments