6
6
import com .fasterxml .jackson .databind .*;
7
7
import com .fasterxml .jackson .databind .annotation .JsonDeserialize ;
8
8
import com .google .common .io .ByteStreams ;
9
+ import com .google .common .io .CharStreams ;
9
10
import graphql .ExecutionInput ;
10
11
import graphql .ExecutionResult ;
11
12
import graphql .GraphQL ;
19
20
import org .slf4j .LoggerFactory ;
20
21
21
22
import javax .security .auth .Subject ;
23
+ import javax .servlet .AsyncContext ;
22
24
import javax .servlet .Servlet ;
23
25
import javax .servlet .ServletException ;
24
26
import javax .servlet .http .HttpServlet ;
@@ -43,6 +45,7 @@ public abstract class GraphQLServlet extends HttpServlet implements Servlet, Gra
43
45
public static final Logger log = LoggerFactory .getLogger (GraphQLServlet .class );
44
46
45
47
public static final String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8" ;
48
+ public static final String APPLICATION_GRAPHQL = "application/graphql" ;
46
49
public static final int STATUS_OK = 200 ;
47
50
public static final int STATUS_BAD_REQUEST = 400 ;
48
51
@@ -65,14 +68,17 @@ public abstract class GraphQLServlet extends HttpServlet implements Servlet, Gra
65
68
66
69
private final HttpRequestHandler getHandler ;
67
70
private final HttpRequestHandler postHandler ;
71
+
72
+ private final boolean asyncServletMode ;
68
73
69
74
public GraphQLServlet () {
70
- this (null , null );
75
+ this (null , null , false );
71
76
}
72
77
73
- public GraphQLServlet (ObjectMapperConfigurer objectMapperConfigurer , List <GraphQLServletListener > listeners ) {
78
+ public GraphQLServlet (ObjectMapperConfigurer objectMapperConfigurer , List <GraphQLServletListener > listeners , boolean asyncServletMode ) {
74
79
this .lazyObjectMapperBuilder = new LazyObjectMapperBuilder (objectMapperConfigurer != null ? objectMapperConfigurer : new DefaultObjectMapperConfigurer ());
75
80
this .listeners = listeners != null ? new ArrayList <>(listeners ) : new ArrayList <>();
81
+ this .asyncServletMode = asyncServletMode ;
76
82
77
83
this .getHandler = (request , response ) -> {
78
84
final GraphQLContext context = createContext (Optional .of (request ), Optional .of (response ));
@@ -114,12 +120,16 @@ public GraphQLServlet(ObjectMapperConfigurer objectMapperConfigurer, List<GraphQ
114
120
final Object rootObject = createRootObject (Optional .of (request ), Optional .of (response ));
115
121
116
122
try {
117
- if (request .getContentType () != null && request .getContentType ().startsWith ("multipart/form-data" ) && !request .getParts ().isEmpty ()) {
123
+ if (APPLICATION_GRAPHQL .equals (request .getContentType ())) {
124
+ String query = CharStreams .toString (request .getReader ());
125
+ doQuery (query , null , null , getSchemaProvider ().getSchema (request ), context , rootObject , request , response );
126
+ } else if (request .getContentType () != null && request .getContentType ().startsWith ("multipart/form-data" ) && !request .getParts ().isEmpty ()) {
118
127
final Map <String , List <Part >> fileItems = request .getParts ().stream ()
119
128
.collect (Collectors .toMap (
120
129
Part ::getName ,
121
130
Collections ::singletonList ,
122
131
(l1 , l2 ) -> Stream .concat (l1 .stream (), l2 .stream ()).collect (Collectors .toList ())));
132
+
123
133
context .setFiles (Optional .of (fileItems ));
124
134
125
135
if (fileItems .containsKey ("graphql" )) {
@@ -244,7 +254,7 @@ public String executeQuery(String query) {
244
254
}
245
255
}
246
256
247
- private void doRequest (HttpServletRequest request , HttpServletResponse response , HttpRequestHandler handler ) {
257
+ private void doRequest (HttpServletRequest request , HttpServletResponse response , HttpRequestHandler handler , AsyncContext asyncContext ) {
248
258
249
259
List <GraphQLServletListener .RequestCallback > requestCallbacks = runListeners (l -> l .onRequest (request , response ));
250
260
@@ -257,17 +267,33 @@ private void doRequest(HttpServletRequest request, HttpServletResponse response,
257
267
runCallbacks (requestCallbacks , c -> c .onError (request , response , t ));
258
268
} finally {
259
269
runCallbacks (requestCallbacks , c -> c .onFinally (request , response ));
270
+ if (asyncContext !=null )
271
+ asyncContext .complete ();
260
272
}
261
273
}
262
274
263
- @ Override
264
- protected void doGet (HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
265
- doRequest (req , resp , getHandler );
266
- }
275
+ @ Override
276
+ protected void doGet (HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
277
+ if (asyncServletMode ) {
278
+ AsyncContext asyncContext = req .startAsync ();
279
+ HttpServletRequest request = (HttpServletRequest ) asyncContext .getRequest ();
280
+ HttpServletResponse response = (HttpServletResponse ) asyncContext .getResponse ();
281
+ new Thread (() -> doRequest (request , response , getHandler , asyncContext )).start ();
282
+ } else {
283
+ doRequest (req , resp , getHandler , null );
284
+ }
285
+ }
267
286
268
287
@ Override
269
288
protected void doPost (HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException {
270
- doRequest (req , resp , postHandler );
289
+ if (asyncServletMode ) {
290
+ AsyncContext asyncContext = req .startAsync ();
291
+ HttpServletRequest request = (HttpServletRequest ) asyncContext .getRequest ();
292
+ HttpServletResponse response = (HttpServletResponse ) asyncContext .getResponse ();
293
+ new Thread (() -> doRequest (request , response , postHandler , asyncContext )).start ();
294
+ } else {
295
+ doRequest (req , resp , postHandler , null );
296
+ }
271
297
}
272
298
273
299
private Optional <Part > getFileItem (Map <String , List <Part >> fileItems , String name ) {
0 commit comments