Skip to content

Commit ff6b4f5

Browse files
authored
Merge pull request #156 from jmccaull/allow_batch_handler_full_response_control
Allow batch handler to set http status
2 parents 4e75830 + 232f2b4 commit ff6b4f5

File tree

6 files changed

+39
-21
lines changed

6 files changed

+39
-21
lines changed

src/main/java/graphql/servlet/AbstractGraphQLHttpServlet.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,7 @@ private void query(GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQL
365365
}
366366

367367
private void queryBatched(GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQLObjectMapper, GraphQLBatchedInvocationInput invocationInput, HttpServletResponse resp) throws Exception {
368-
resp.setContentType(APPLICATION_JSON_UTF8);
369-
resp.setStatus(STATUS_OK);
370-
371-
Writer respWriter = resp.getWriter();
372-
373-
queryInvoker.query(invocationInput, respWriter, graphQLObjectMapper);
368+
queryInvoker.query(invocationInput, resp, graphQLObjectMapper);
374369
}
375370

376371
private <R> List<R> runListeners(Function<? super GraphQLServletListener, R> action) {

src/main/java/graphql/servlet/BatchExecutionHandler.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import graphql.ExecutionInput;
44
import graphql.ExecutionResult;
55

6+
import javax.servlet.http.HttpServletResponse;
67
import java.io.Writer;
78
import java.util.function.BiFunction;
89

@@ -16,9 +17,9 @@ public interface BatchExecutionHandler {
1617
* @param batchedInvocationInput the batch query input
1718
* @param queryFunction Function to produce query results.
1819
* @param graphQLObjectMapper object mapper used to serialize results
19-
* @param writer request writer to ouput results.
20+
* @param response http response object
2021
*/
21-
void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, Writer writer, GraphQLObjectMapper graphQLObjectMapper,
22+
void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletResponse response, GraphQLObjectMapper graphQLObjectMapper,
2223
BiFunction<GraphQLInvocationInput, ExecutionInput, ExecutionResult> queryFunction);
2324
}
2425

src/main/java/graphql/servlet/DefaultBatchExecutionHandler.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import graphql.ExecutionInput;
44
import graphql.ExecutionResult;
55

6+
import javax.servlet.http.HttpServletResponse;
67
import java.io.IOException;
78
import java.io.Writer;
89
import java.util.Iterator;
@@ -11,10 +12,14 @@
1112
public class DefaultBatchExecutionHandler implements BatchExecutionHandler {
1213

1314
@Override
14-
public void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, Writer writer, GraphQLObjectMapper graphQLObjectMapper,
15+
public void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletResponse response, GraphQLObjectMapper graphQLObjectMapper,
1516
BiFunction<GraphQLInvocationInput, ExecutionInput, ExecutionResult> queryFunction) {
16-
Iterator<ExecutionInput> executionInputIterator = batchedInvocationInput.getExecutionInputs().iterator();
17+
response.setContentType(AbstractGraphQLHttpServlet.APPLICATION_JSON_UTF8);
18+
response.setStatus(AbstractGraphQLHttpServlet.STATUS_OK);
1719
try {
20+
Writer writer = response.getWriter();
21+
Iterator<ExecutionInput> executionInputIterator = batchedInvocationInput.getExecutionInputs().iterator();
22+
1823
writer.write("[");
1924
while (executionInputIterator.hasNext()) {
2025
ExecutionResult result = queryFunction.apply(batchedInvocationInput, executionInputIterator.next());

src/main/java/graphql/servlet/GraphQLQueryInvoker.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import graphql.schema.GraphQLSchema;
1414

1515
import javax.security.auth.Subject;
16+
import javax.servlet.http.HttpServletResponse;
1617
import java.io.Writer;
1718
import java.security.AccessController;
1819
import java.security.PrivilegedAction;
@@ -43,8 +44,8 @@ public ExecutionResult query(GraphQLSingleInvocationInput singleInvocationInput)
4344
return query(singleInvocationInput, singleInvocationInput.getExecutionInput());
4445
}
4546

46-
public void query(GraphQLBatchedInvocationInput batchedInvocationInput, Writer writer, GraphQLObjectMapper graphQLObjectMapper) {
47-
batchExecutionHandler.handleBatch(batchedInvocationInput, writer, graphQLObjectMapper, this::query);
47+
public void query(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletResponse response, GraphQLObjectMapper graphQLObjectMapper) {
48+
batchExecutionHandler.handleBatch(batchedInvocationInput, response, graphQLObjectMapper, this::query);
4849
}
4950

5051
private GraphQL newGraphQL(GraphQLSchema schema, Object context) {

src/test/groovy/graphql/servlet/AbstractGraphQLHttpServletSpec.groovy

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ class AbstractGraphQLHttpServletSpec extends Specification {
285285
getBatchedResponseContent()[1].data.echo == "test"
286286
}
287287

288-
def "Execution Result Handler allows limiting number of queries"() {
288+
def "Batch Execution Handler allows limiting batches and sending error messages."() {
289289
setup:
290290
servlet = TestUtils.createBatchCustomizedServlet({ env -> env.arguments.arg }, { env -> env.arguments.arg }, { env ->
291291
AtomicReference<SingleSubscriberPublisher<String>> publisherRef = new AtomicReference<>()
@@ -304,9 +304,8 @@ class AbstractGraphQLHttpServletSpec extends Specification {
304304
servlet.doGet(request, response)
305305

306306
then:
307-
response.getStatus() == STATUS_OK
308-
response.getContentType() == CONTENT_TYPE_JSON_UTF8
309-
getBatchedResponseContent().size() == 2
307+
response.getStatus() == STATUS_BAD_REQUEST
308+
response.getErrorMessage() == TestBatchExecutionHandler.BATCH_ERROR_MESSAGE
310309
}
311310

312311
def "Default Execution Result Handler does not limit number of queries"() {

src/test/groovy/graphql/servlet/TestBatchExecutionHandler.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import graphql.ExecutionInput;
44
import graphql.ExecutionResult;
55

6+
import javax.servlet.http.HttpServletResponse;
67
import java.io.IOException;
78
import java.io.Writer;
89
import java.util.Iterator;
@@ -12,18 +13,34 @@
1213

1314
public class TestBatchExecutionHandler implements BatchExecutionHandler {
1415

16+
public static String BATCH_ERROR_MESSAGE = "Batch limit exceeded";
17+
1518
@Override
16-
public void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, Writer writer, GraphQLObjectMapper graphQLObjectMapper,
19+
public void handleBatch(GraphQLBatchedInvocationInput batchedInvocationInput, HttpServletResponse response, GraphQLObjectMapper graphQLObjectMapper,
1720
BiFunction<GraphQLInvocationInput, ExecutionInput, ExecutionResult> queryFunction) {
18-
List<ExecutionResult> results = batchedInvocationInput.getExecutionInputs().parallelStream()
19-
.limit(2)
21+
List<ExecutionInput> inputs = batchedInvocationInput.getExecutionInputs();
22+
if (inputs.size() > 2) {
23+
handleBadInput(response);
24+
}
25+
List<ExecutionResult> results = inputs.parallelStream()
2026
.map(input -> queryFunction.apply(batchedInvocationInput, input))
2127
.collect(Collectors.toList());
22-
writeResults(results, writer, graphQLObjectMapper);
28+
writeResults(results, response, graphQLObjectMapper);
29+
}
30+
31+
private void handleBadInput(HttpServletResponse response) {
32+
try {
33+
response.sendError(HttpServletResponse.SC_BAD_REQUEST, BATCH_ERROR_MESSAGE);
34+
} catch (IOException e) {
35+
throw new RuntimeException(e);
36+
}
2337
}
2438

25-
private void writeResults(List<ExecutionResult> results, Writer writer, GraphQLObjectMapper mapper) {
39+
private void writeResults(List<ExecutionResult> results, HttpServletResponse response, GraphQLObjectMapper mapper) {
40+
response.setContentType(AbstractGraphQLHttpServlet.APPLICATION_JSON_UTF8);
41+
response.setStatus(AbstractGraphQLHttpServlet.STATUS_OK);
2642
try {
43+
Writer writer = response.getWriter();
2744
writer.write("[");
2845
Iterator<ExecutionResult> iter = results.iterator();
2946
while (iter.hasNext()) {

0 commit comments

Comments
 (0)