Skip to content

Commit ab4891c

Browse files
author
agairol
committed
Merge branch 'master' into DataLoader-in-context
# Conflicts: # src/main/java/graphql/servlet/SimpleGraphQLServlet.java
2 parents 6b8df8a + f418e68 commit ab4891c

File tree

3 files changed

+67
-19
lines changed

3 files changed

+67
-19
lines changed

src/main/java/graphql/servlet/GraphQLServlet.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import com.fasterxml.jackson.databind.*;
77
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
88
import com.google.common.io.ByteStreams;
9+
import com.google.common.io.CharStreams;
910
import graphql.ExecutionInput;
1011
import graphql.ExecutionResult;
1112
import graphql.GraphQL;
@@ -19,6 +20,7 @@
1920
import org.slf4j.LoggerFactory;
2021

2122
import javax.security.auth.Subject;
23+
import javax.servlet.AsyncContext;
2224
import javax.servlet.Servlet;
2325
import javax.servlet.ServletException;
2426
import javax.servlet.http.HttpServlet;
@@ -43,6 +45,7 @@ public abstract class GraphQLServlet extends HttpServlet implements Servlet, Gra
4345
public static final Logger log = LoggerFactory.getLogger(GraphQLServlet.class);
4446

4547
public static final String APPLICATION_JSON_UTF8 = "application/json;charset=UTF-8";
48+
public static final String APPLICATION_GRAPHQL = "application/graphql";
4649
public static final int STATUS_OK = 200;
4750
public static final int STATUS_BAD_REQUEST = 400;
4851

@@ -65,14 +68,17 @@ public abstract class GraphQLServlet extends HttpServlet implements Servlet, Gra
6568

6669
private final HttpRequestHandler getHandler;
6770
private final HttpRequestHandler postHandler;
71+
72+
private final boolean asyncServletMode;
6873

6974
public GraphQLServlet() {
70-
this(null, null);
75+
this(null, null, false);
7176
}
7277

73-
public GraphQLServlet(ObjectMapperConfigurer objectMapperConfigurer, List<GraphQLServletListener> listeners) {
78+
public GraphQLServlet(ObjectMapperConfigurer objectMapperConfigurer, List<GraphQLServletListener> listeners, boolean asyncServletMode) {
7479
this.lazyObjectMapperBuilder = new LazyObjectMapperBuilder(objectMapperConfigurer != null ? objectMapperConfigurer : new DefaultObjectMapperConfigurer());
7580
this.listeners = listeners != null ? new ArrayList<>(listeners) : new ArrayList<>();
81+
this.asyncServletMode = asyncServletMode;
7682

7783
this.getHandler = (request, response) -> {
7884
final GraphQLContext context = createContext(Optional.of(request), Optional.of(response));
@@ -114,12 +120,16 @@ public GraphQLServlet(ObjectMapperConfigurer objectMapperConfigurer, List<GraphQ
114120
final Object rootObject = createRootObject(Optional.of(request), Optional.of(response));
115121

116122
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()) {
118127
final Map<String, List<Part>> fileItems = request.getParts().stream()
119128
.collect(Collectors.toMap(
120129
Part::getName,
121130
Collections::singletonList,
122131
(l1, l2) -> Stream.concat(l1.stream(), l2.stream()).collect(Collectors.toList())));
132+
123133
context.setFiles(Optional.of(fileItems));
124134

125135
if (fileItems.containsKey("graphql")) {
@@ -244,7 +254,7 @@ public String executeQuery(String query) {
244254
}
245255
}
246256

247-
private void doRequest(HttpServletRequest request, HttpServletResponse response, HttpRequestHandler handler) {
257+
private void doRequest(HttpServletRequest request, HttpServletResponse response, HttpRequestHandler handler,AsyncContext asyncContext) {
248258

249259
List<GraphQLServletListener.RequestCallback> requestCallbacks = runListeners(l -> l.onRequest(request, response));
250260

@@ -257,17 +267,33 @@ private void doRequest(HttpServletRequest request, HttpServletResponse response,
257267
runCallbacks(requestCallbacks, c -> c.onError(request, response, t));
258268
} finally {
259269
runCallbacks(requestCallbacks, c -> c.onFinally(request, response));
270+
if(asyncContext !=null)
271+
asyncContext.complete();
260272
}
261273
}
262274

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+
}
267286

268287
@Override
269288
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+
}
271297
}
272298

273299
private Optional<Part> getFileItem(Map<String, List<Part>> fileItems, String name) {

src/main/java/graphql/servlet/SimpleGraphQLServlet.java

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
package graphql.servlet;
22

3+
import java.util.List;
4+
import java.util.Optional;
5+
6+
import javax.servlet.http.HttpServletRequest;
7+
import javax.servlet.http.HttpServletResponse;
8+
39
import graphql.execution.ExecutionStrategy;
410
import graphql.execution.instrumentation.ChainedInstrumentation;
511
import graphql.execution.instrumentation.Instrumentation;
@@ -9,17 +15,12 @@
915
import graphql.execution.preparsed.PreparsedDocumentProvider;
1016
import graphql.schema.GraphQLSchema;
1117

12-
import javax.servlet.http.HttpServletRequest;
13-
import javax.servlet.http.HttpServletResponse;
14-
import java.util.ArrayList;
15-
import java.util.List;
16-
import java.util.Optional;
17-
1818
/**
1919
* @author Andrew Potter
2020
*/
2121
public class SimpleGraphQLServlet extends GraphQLServlet {
2222

23+
2324
/**
2425
* @deprecated use {@link #builder(GraphQLSchema)} instead.
2526
*/
@@ -49,15 +50,16 @@ public SimpleGraphQLServlet(GraphQLSchema schema, ExecutionStrategyProvider exec
4950
*/
5051
@Deprecated
5152
public SimpleGraphQLServlet(final GraphQLSchema schema, ExecutionStrategyProvider executionStrategyProvider, ObjectMapperConfigurer objectMapperConfigurer, List<GraphQLServletListener> listeners, Instrumentation instrumentation, GraphQLErrorHandler errorHandler, GraphQLContextBuilder contextBuilder, GraphQLRootObjectBuilder rootObjectBuilder, PreparsedDocumentProvider preparsedDocumentProvider) {
52-
this(new DefaultGraphQLSchemaProvider(schema), executionStrategyProvider, objectMapperConfigurer, listeners, instrumentation, errorHandler, contextBuilder, rootObjectBuilder, preparsedDocumentProvider);
53+
this(new DefaultGraphQLSchemaProvider(schema), executionStrategyProvider, objectMapperConfigurer, listeners, instrumentation, errorHandler, contextBuilder, rootObjectBuilder, preparsedDocumentProvider,false);
5354
}
5455

56+
5557
/**
5658
* @deprecated use {@link #builder(GraphQLSchemaProvider)} instead.
5759
*/
5860
@Deprecated
59-
public SimpleGraphQLServlet(GraphQLSchemaProvider schemaProvider, ExecutionStrategyProvider executionStrategyProvider, ObjectMapperConfigurer objectMapperConfigurer, List<GraphQLServletListener> listeners, Instrumentation instrumentation, GraphQLErrorHandler errorHandler, GraphQLContextBuilder contextBuilder, GraphQLRootObjectBuilder rootObjectBuilder, PreparsedDocumentProvider preparsedDocumentProvider) {
60-
super(objectMapperConfigurer, listeners);
61+
public SimpleGraphQLServlet(GraphQLSchemaProvider schemaProvider, ExecutionStrategyProvider executionStrategyProvider, ObjectMapperConfigurer objectMapperConfigurer, List<GraphQLServletListener> listeners, Instrumentation instrumentation, GraphQLErrorHandler errorHandler, GraphQLContextBuilder contextBuilder, GraphQLRootObjectBuilder rootObjectBuilder, PreparsedDocumentProvider preparsedDocumentProvider, boolean asyncServletMode) {
62+
super(objectMapperConfigurer, listeners, asyncServletMode);
6163

6264
this.schemaProvider = schemaProvider;
6365
this.executionStrategyProvider = executionStrategyProvider;
@@ -94,7 +96,7 @@ public SimpleGraphQLServlet(GraphQLSchemaProvider schemaProvider, ExecutionStrat
9496
}
9597

9698
protected SimpleGraphQLServlet(Builder builder) {
97-
super(builder.objectMapperConfigurer, builder.listeners);
99+
super(builder.objectMapperConfigurer, builder.listeners, builder.asyncServletMode);
98100

99101
this.schemaProvider = builder.schemaProvider;
100102
this.executionStrategyProvider = builder.executionStrategyProvider;
@@ -139,6 +141,7 @@ public static class Builder {
139141
private GraphQLContextBuilder contextBuilder = new DefaultGraphQLContextBuilder();
140142
private GraphQLRootObjectBuilder rootObjectBuilder = new DefaultGraphQLRootObjectBuilder();
141143
private PreparsedDocumentProvider preparsedDocumentProvider = NoOpPreparsedDocumentProvider.INSTANCE;
144+
private boolean asyncServletMode;
142145

143146
public Builder(GraphQLSchema schema) {
144147
this(new DefaultGraphQLSchemaProvider(schema));
@@ -188,6 +191,11 @@ public Builder withListeners(List<GraphQLServletListener> listeners) {
188191
return this;
189192
}
190193

194+
public Builder withAsyncServletMode(boolean value) {
195+
this.asyncServletMode=value;
196+
return this;
197+
}
198+
191199
public SimpleGraphQLServlet build() {
192200
return new SimpleGraphQLServlet(this);
193201
}

src/test/groovy/graphql/servlet/GraphQLServletSpec.groovy

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,20 @@ class GraphQLServletSpec extends Specification {
327327
getResponseContent().data.echo == "test"
328328
}
329329

330+
def "query over HTTP POST body with graphql contentType returns data"() {
331+
setup:
332+
request.addHeader("Content-Type", "application/graphql")
333+
request.setContent('query { echo(arg:"test") }'.getBytes("UTF-8"))
334+
335+
when:
336+
servlet.doPost(request, response)
337+
338+
then:
339+
response.getStatus() == STATUS_OK
340+
response.getContentType() == CONTENT_TYPE_JSON_UTF8
341+
getResponseContent().data.echo == "test"
342+
}
343+
330344
def "query over HTTP POST body with variables returns data"() {
331345
setup:
332346
request.setContent(mapper.writeValueAsBytes([

0 commit comments

Comments
 (0)