Skip to content

Commit 894476f

Browse files
committed
Added a web context interface, removed optional
1 parent 83384ec commit 894476f

File tree

7 files changed

+204
-31
lines changed

7 files changed

+204
-31
lines changed

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

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ public void init() {
132132
}
133133
if (path.contentEquals("/schema.json")) {
134134
query(queryInvoker, graphQLObjectMapper, invocationInputFactory.create(INTROSPECTION_REQUEST, request, response),
135-
Optional.of(request), response);
135+
request, response);
136136
} else {
137137
String query = request.getParameter("query");
138138
if (query != null) {
@@ -152,7 +152,7 @@ public void init() {
152152

153153
query(queryInvoker, graphQLObjectMapper,
154154
invocationInputFactory.createReadOnly(new GraphQLRequest(query, variables, operationName), request, response),
155-
Optional.of(request), response);
155+
request, response);
156156
}
157157
} else {
158158
response.setStatus(STATUS_BAD_REQUEST);
@@ -171,7 +171,7 @@ public void init() {
171171
String query = CharStreams.toString(request.getReader());
172172
query(queryInvoker, graphQLObjectMapper,
173173
invocationInputFactory.create(new GraphQLRequest(query, null, null), request, response),
174-
Optional.of(request), response);
174+
request, response);
175175
} else if (request.getContentType() != null && request.getContentType().startsWith("multipart/form-data") && !request.getParts().isEmpty()) {
176176
final Map<String, List<Part>> fileItems = request.getParts()
177177
.stream()
@@ -199,7 +199,7 @@ public void init() {
199199
graphQLObjectMapper.readBatchedGraphQLRequest(inputStream);
200200
variablesMap.ifPresent(map -> graphQLRequests.forEach(r -> mapMultipartVariables(r, map, fileItems)));
201201
GraphQLBatchedInvocationInput batchedInvocationInput = invocationInputFactory.create(configuration.getContextSetting(),
202-
graphQLRequests, request, response);
202+
graphQLRequests, request, response, fileItems);
203203
queryBatched(queryInvoker, batchedInvocationInput, request, response, configuration);
204204
return;
205205
} else {
@@ -212,8 +212,8 @@ public void init() {
212212

213213
variablesMap.ifPresent(m -> mapMultipartVariables(graphQLRequest, m, fileItems));
214214
GraphQLSingleInvocationInput invocationInput =
215-
invocationInputFactory.create(graphQLRequest, request, response);
216-
query(queryInvoker, graphQLObjectMapper, invocationInput, Optional.of(request), response);
215+
invocationInputFactory.create(graphQLRequest, request, response, fileItems);
216+
query(queryInvoker, graphQLObjectMapper, invocationInput, request, response);
217217
return;
218218
}
219219
}
@@ -230,7 +230,7 @@ public void init() {
230230
invocationInputFactory.create(configuration.getContextSetting(), requests, request, response);
231231
queryBatched(queryInvoker, batchedInvocationInput, request, response, configuration);
232232
} else {
233-
query(queryInvoker, graphQLObjectMapper, invocationInputFactory.create(graphQLObjectMapper.readGraphQLRequest(inputStream), request, response), Optional.of(request), response);
233+
query(queryInvoker, graphQLObjectMapper, invocationInputFactory.create(graphQLObjectMapper.readGraphQLRequest(inputStream), request, response), request, response);
234234
}
235235
}
236236
} catch (Exception e) {
@@ -356,18 +356,20 @@ private Optional<Part> getFileItem(Map<String, List<Part>> fileItems, String nam
356356
}
357357

358358
private void query(GraphQLQueryInvoker queryInvoker, GraphQLObjectMapper graphQLObjectMapper, GraphQLSingleInvocationInput invocationInput,
359-
Optional<HttpServletRequest> httpServletRequest, HttpServletResponse resp) throws IOException {
359+
HttpServletRequest req, HttpServletResponse resp) throws IOException {
360360
ExecutionResult result = queryInvoker.query(invocationInput);
361361

362362
if (!(result.getData() instanceof Publisher)) {
363363
resp.setContentType(APPLICATION_JSON_UTF8);
364364
resp.setStatus(STATUS_OK);
365365
resp.getWriter().write(graphQLObjectMapper.serializeResultAsJson(result));
366366
} else {
367+
if (req == null) {
368+
throw new IllegalStateException("Http servlet request can not be null");
369+
}
367370
resp.setContentType(APPLICATION_EVENT_STREAM_UTF8);
368371
resp.setStatus(STATUS_OK);
369372

370-
HttpServletRequest req = httpServletRequest.orElseThrow(IllegalStateException::new);
371373
boolean isInAsyncThread = req.isAsyncStarted();
372374
AsyncContext asyncContext = isInAsyncThread ? req.getAsyncContext() : req.startAsync(req, resp);
373375
asyncContext.setTimeout(configuration.getSubscriptionTimeout());

src/main/java/graphql/servlet/context/DefaultGraphQLContextBuilder.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,25 @@
22

33
import javax.servlet.http.HttpServletRequest;
44
import javax.servlet.http.HttpServletResponse;
5+
import javax.servlet.http.Part;
56
import javax.websocket.Session;
67
import javax.websocket.server.HandshakeRequest;
8+
import java.util.List;
9+
import java.util.Map;
710

811
/**
912
* Returns an empty context.
1013
*/
1114
public class DefaultGraphQLContextBuilder implements GraphQLContextBuilder {
1215

1316
@Override
14-
public GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
15-
return new DefaultGraphQLServletContext();
17+
public GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map<String, List<Part>> fileParts) {
18+
return DefaultGraphQLWebSocketContext.createWebContext().with(httpServletRequest).with(httpServletResponse).with(fileParts).build();
1619
}
1720

1821
@Override
1922
public GraphQLContext build(Session session, HandshakeRequest handshakeRequest) {
20-
return new DefaultGraphQLServletContext();
23+
return DefaultGraphQLWebSocketContext.createWebContext().with(session).with(handshakeRequest).build();
2124
}
2225

2326
@Override
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package graphql.servlet.context;
2+
3+
import graphql.servlet.core.ApolloSubscriptionConnectionListener;
4+
import org.dataloader.DataLoaderRegistry;
5+
6+
import javax.security.auth.Subject;
7+
import javax.servlet.http.HttpServletRequest;
8+
import javax.servlet.http.HttpServletResponse;
9+
import javax.servlet.http.Part;
10+
import javax.websocket.Session;
11+
import javax.websocket.server.HandshakeRequest;
12+
import java.util.Collection;
13+
import java.util.HashMap;
14+
import java.util.List;
15+
import java.util.Map;
16+
import java.util.Optional;
17+
import java.util.stream.Collectors;
18+
19+
public class DefaultGraphQLWebSocketContext extends DefaultGraphQLServletContext implements GraphQLWebSocketContext {
20+
21+
private final HttpServletRequest httpServletRequest;
22+
private final HttpServletResponse httpServletResponse;
23+
private final Session session;
24+
private final HandshakeRequest handshakeRequest;
25+
private final Map<String, List<Part>> parts;
26+
27+
private DefaultGraphQLWebSocketContext(DataLoaderRegistry dataLoaderRegistry, Subject subject, HttpServletRequest httpServletRequest,
28+
HttpServletResponse httpServletResponse, Session session, HandshakeRequest handshakeRequest,
29+
Map<String, List<Part>> parts) {
30+
super(dataLoaderRegistry, subject);
31+
this.httpServletRequest = httpServletRequest;
32+
this.httpServletResponse = httpServletResponse;
33+
this.session = session;
34+
this.handshakeRequest = handshakeRequest;
35+
this.parts = parts;
36+
}
37+
38+
@Override
39+
public Optional<HttpServletRequest> getHttpServletRequest() {
40+
return Optional.ofNullable(httpServletRequest);
41+
}
42+
43+
@Override
44+
public Optional<HttpServletResponse> getHttpServletResponse() {
45+
return Optional.ofNullable(httpServletResponse);
46+
}
47+
48+
@Override
49+
public List<Part> getFileParts() {
50+
return parts.values()
51+
.stream()
52+
.flatMap(Collection::stream)
53+
.filter(part -> part.getContentType() != null)
54+
.collect(Collectors.toList());
55+
}
56+
57+
@Override
58+
public Map<String, List<Part>> getParts() {
59+
return parts;
60+
}
61+
62+
@Override
63+
public Optional<Session> getSession() {
64+
return Optional.ofNullable(session);
65+
}
66+
67+
@Override
68+
public Optional<Object> getConnectResult() {
69+
return getSession().map(session -> session.getUserProperties().get(ApolloSubscriptionConnectionListener.CONNECT_RESULT_KEY));
70+
}
71+
72+
@Override
73+
public Optional<HandshakeRequest> getHandshakeRequest() {
74+
return Optional.ofNullable(handshakeRequest);
75+
}
76+
77+
public static Builder createWebContext(DataLoaderRegistry registry, Subject subject) {
78+
return new Builder(registry, subject);
79+
}
80+
81+
public static Builder createWebContext() {
82+
return new Builder(null, null);
83+
}
84+
85+
public static class Builder {
86+
private HttpServletRequest httpServletRequest;
87+
private HttpServletResponse httpServletResponse;
88+
private Session session;
89+
private HandshakeRequest handshakeRequest;
90+
private Map<String, List<Part>> parts = new HashMap<>();
91+
private DataLoaderRegistry dataLoaderRegistry;
92+
private Subject subject;
93+
94+
private Builder(DataLoaderRegistry dataLoaderRegistry, Subject subject) {
95+
this.dataLoaderRegistry = dataLoaderRegistry;
96+
this.subject = subject;
97+
}
98+
99+
public DefaultGraphQLWebSocketContext build() {
100+
return new DefaultGraphQLWebSocketContext(dataLoaderRegistry, subject, httpServletRequest, httpServletResponse, session, handshakeRequest, parts);
101+
}
102+
103+
public Builder with(HttpServletRequest httpServletRequest) {
104+
this.httpServletRequest = httpServletRequest;
105+
return this;
106+
}
107+
108+
public Builder with(HttpServletResponse httpServletResponse) {
109+
this.httpServletResponse = httpServletResponse;
110+
return this;
111+
}
112+
113+
public Builder with(Session session) {
114+
this.session = session;
115+
return this;
116+
}
117+
118+
public Builder with(HandshakeRequest handshakeRequest) {
119+
this.handshakeRequest = handshakeRequest;
120+
return this;
121+
}
122+
123+
public Builder with(Map<String, List<Part>> parts) {
124+
if (parts != null) {
125+
this.parts.putAll(parts);
126+
}
127+
return this;
128+
}
129+
}
130+
}

src/main/java/graphql/servlet/context/GraphQLContextBuilder.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
import javax.servlet.http.HttpServletRequest;
44
import javax.servlet.http.HttpServletResponse;
5+
import javax.servlet.http.Part;
56
import javax.websocket.Session;
67
import javax.websocket.server.HandshakeRequest;
8+
import java.util.List;
9+
import java.util.Map;
710

811
public interface GraphQLContextBuilder {
912

10-
GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse);
13+
GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map<String, List<Part>> fileParts);
1114

1215
GraphQLContext build(Session session, HandshakeRequest handshakeRequest);
1316

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package graphql.servlet.context;
2+
3+
import javax.servlet.http.HttpServletRequest;
4+
import javax.servlet.http.HttpServletResponse;
5+
import javax.servlet.http.Part;
6+
import javax.websocket.Session;
7+
import javax.websocket.server.HandshakeRequest;
8+
import java.util.List;
9+
import java.util.Map;
10+
import java.util.Optional;
11+
12+
public interface GraphQLWebSocketContext extends GraphQLContext {
13+
14+
List<Part> getFileParts();
15+
16+
Map<String, List<Part>> getParts();
17+
18+
Optional<Session> getSession();
19+
20+
Optional<Object> getConnectResult();
21+
22+
Optional<HandshakeRequest> getHandshakeRequest();
23+
24+
Optional<HttpServletRequest> getHttpServletRequest();
25+
26+
Optional<HttpServletResponse> getHttpServletResponse();
27+
}

src/main/java/graphql/servlet/input/GraphQLInvocationInputFactory.java

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212

1313
import javax.servlet.http.HttpServletRequest;
1414
import javax.servlet.http.HttpServletResponse;
15+
import javax.servlet.http.Part;
1516
import javax.websocket.Session;
1617
import javax.websocket.server.HandshakeRequest;
1718
import java.util.List;
19+
import java.util.Map;
1820
import java.util.function.Supplier;
1921

2022
/**
@@ -37,19 +39,30 @@ public GraphQLSchemaProvider getSchemaProvider() {
3739
}
3840

3941
public GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest, HttpServletRequest request, HttpServletResponse response) {
40-
return create(graphQLRequest, request, response, false);
42+
return create(graphQLRequest, request, response, null);
4143
}
4244

43-
public GraphQLBatchedInvocationInput create(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request, HttpServletResponse response) {
44-
return create(contextSetting, graphQLRequests, request, response, false);
45+
public GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest, HttpServletRequest request, HttpServletResponse response, Map<String,
46+
List<Part>> fileParts) {
47+
return create(graphQLRequest, request, response, false, fileParts);
48+
}
49+
50+
public GraphQLBatchedInvocationInput create(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request,
51+
HttpServletResponse response) {
52+
return create(contextSetting, graphQLRequests, request, response, null);
53+
}
54+
55+
public GraphQLBatchedInvocationInput create(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request,
56+
HttpServletResponse response, Map<String, List<Part>> fileParts) {
57+
return create(contextSetting, graphQLRequests, request, response, false, fileParts);
4558
}
4659

4760
public GraphQLSingleInvocationInput createReadOnly(GraphQLRequest graphQLRequest, HttpServletRequest request, HttpServletResponse response) {
48-
return create(graphQLRequest, request, response, true);
61+
return create(graphQLRequest, request, response, true, null);
4962
}
5063

5164
public GraphQLBatchedInvocationInput createReadOnly(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request, HttpServletResponse response) {
52-
return create(contextSetting, graphQLRequests, request, response, true);
65+
return create(contextSetting, graphQLRequests, request, response, true, null);
5366
}
5467

5568
public GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest) {
@@ -61,20 +74,22 @@ public GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest) {
6174
);
6275
}
6376

64-
private GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest, HttpServletRequest request, HttpServletResponse response, boolean readOnly) {
77+
private GraphQLSingleInvocationInput create(GraphQLRequest graphQLRequest, HttpServletRequest request, HttpServletResponse response,
78+
boolean readOnly, Map<String, List<Part>> fileParts) {
6579
return new GraphQLSingleInvocationInput(
6680
graphQLRequest,
6781
readOnly ? schemaProviderSupplier.get().getReadOnlySchema(request) : schemaProviderSupplier.get().getSchema(request),
68-
contextBuilderSupplier.get().build(request, response),
82+
contextBuilderSupplier.get().build(request, response,fileParts),
6983
rootObjectBuilderSupplier.get().build(request)
7084
);
7185
}
7286

73-
private GraphQLBatchedInvocationInput create(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request, HttpServletResponse response, boolean readOnly) {
87+
private GraphQLBatchedInvocationInput create(ContextSetting contextSetting, List<GraphQLRequest> graphQLRequests, HttpServletRequest request,
88+
HttpServletResponse response, boolean readOnly, Map<String, List<Part>> fileParts) {
7489
return contextSetting.getBatch(
7590
graphQLRequests,
7691
readOnly ? schemaProviderSupplier.get().getReadOnlySchema(request) : schemaProviderSupplier.get().getSchema(request),
77-
() -> contextBuilderSupplier.get().build(request, response),
92+
() -> contextBuilderSupplier.get().build(request, response, fileParts),
7893
rootObjectBuilderSupplier.get().build(request)
7994
);
8095
}
@@ -111,7 +126,6 @@ public static Builder newBuilder(Supplier<GraphQLSchemaProvider> schemaProviderS
111126

112127
public static class Builder {
113128
private final Supplier<GraphQLSchemaProvider> schemaProviderSupplier;
114-
private ContextSetting contextSetting = ContextSetting.PER_QUERY;
115129
private Supplier<GraphQLContextBuilder> contextBuilderSupplier = DefaultGraphQLContextBuilder::new;
116130
private Supplier<GraphQLRootObjectBuilder> rootObjectBuilderSupplier = DefaultGraphQLRootObjectBuilder::new;
117131

@@ -141,13 +155,6 @@ public Builder withGraphQLRootObjectBuilder(Supplier<GraphQLRootObjectBuilder> r
141155
return this;
142156
}
143157

144-
public Builder withContextSetting(ContextSetting contextSetting) {
145-
if (contextSetting != null) {
146-
this.contextSetting = contextSetting;
147-
}
148-
return this;
149-
}
150-
151158
public GraphQLInvocationInputFactory build() {
152159
return new GraphQLInvocationInputFactory(schemaProviderSupplier, contextBuilderSupplier, rootObjectBuilderSupplier);
153160
}

src/test/groovy/graphql/servlet/DataLoaderDispatchingSpec.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import spock.lang.Specification
1818

1919
import javax.servlet.http.HttpServletRequest
2020
import javax.servlet.http.HttpServletResponse
21+
import javax.servlet.http.Part
2122
import javax.websocket.Session
2223
import javax.websocket.server.HandshakeRequest
2324
import java.util.concurrent.CompletableFuture
@@ -74,7 +75,7 @@ class DataLoaderDispatchingSpec extends Specification {
7475
def contextBuilder () {
7576
return new GraphQLContextBuilder() {
7677
@Override
77-
GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
78+
GraphQLContext build(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map<String, List<Part>> fileParts) {
7879
new DefaultGraphQLServletContext(registry(), null)
7980
}
8081

0 commit comments

Comments
 (0)