22
22
import java .util .List ;
23
23
import java .util .Map ;
24
24
import java .util .Optional ;
25
- import java .util .regex .Pattern ;
26
25
27
26
import javax .servlet .ServletException ;
28
27
29
28
import com .fasterxml .jackson .core .JsonProcessingException ;
30
29
import com .fasterxml .jackson .core .type .TypeReference ;
30
+ import com .fasterxml .jackson .databind .ObjectMapper ;
31
31
import org .apache .commons .logging .Log ;
32
32
import org .apache .commons .logging .LogFactory ;
33
+ import org .springframework .graphql .server .support .MultipartVariableMapper ;
33
34
import org .springframework .web .multipart .MultipartFile ;
34
35
import org .springframework .web .multipart .support .AbstractMultipartHttpServletRequest ;
35
36
import reactor .core .publisher .Mono ;
@@ -69,15 +70,32 @@ public class GraphQlHttpHandler {
69
70
70
71
private final WebGraphQlHandler graphQlHandler ;
71
72
73
+ private final ObjectMapper objectMapper ;
74
+
72
75
/**
73
76
* Create a new instance.
74
77
* @param graphQlHandler common handler for GraphQL over HTTP requests
78
+ * @deprecated Use GraphQlHttpHandler(WebGraphQlHandler graphQlHandler, ObjectMapper objectMapper) instead.
75
79
*/
76
- public GraphQlHttpHandler (WebGraphQlHandler graphQlHandler ) {
80
+ @ Deprecated
81
+ public GraphQlHttpHandler (WebGraphQlHandler graphQlHandler ) {
77
82
Assert .notNull (graphQlHandler , "WebGraphQlHandler is required" );
78
83
this .graphQlHandler = graphQlHandler ;
84
+ this .objectMapper = new ObjectMapper ();
79
85
}
80
86
87
+ /**
88
+ * Create a new instance.
89
+ * @param graphQlHandler common handler for GraphQL over HTTP requests
90
+ * @param objectMapper ObjectMapper used for parsing form parts
91
+ */
92
+ public GraphQlHttpHandler (WebGraphQlHandler graphQlHandler , ObjectMapper objectMapper ) {
93
+ Assert .notNull (graphQlHandler , "WebGraphQlHandler is required" );
94
+ Assert .notNull (objectMapper , "ObjectMapper is required" );
95
+ this .graphQlHandler = graphQlHandler ;
96
+ this .objectMapper = objectMapper ;
97
+ }
98
+
81
99
/**
82
100
* Handle GraphQL requests over HTTP.
83
101
* @param serverRequest the incoming HTTP request
@@ -112,7 +130,7 @@ public ServerResponse handleRequest(ServerRequest serverRequest) throws ServletE
112
130
public ServerResponse handleMultipartRequest (ServerRequest serverRequest ) throws ServletException {
113
131
Optional <String > operation = serverRequest .param ("operations" );
114
132
Optional <String > mapParam = serverRequest .param ("map" );
115
- Map <String , Object > inputQuery = readJson (operation , new TypeReference <>() {});
133
+ Map <String , Object > inputQuery = readJson (operation , new TypeReference <Map < String , Object > >() {});
116
134
final Map <String , Object > queryVariables ;
117
135
if (inputQuery .containsKey ("variables" )) {
118
136
queryVariables = (Map <String , Object >)inputQuery .get ("variables" );
@@ -125,7 +143,7 @@ public ServerResponse handleMultipartRequest(ServerRequest serverRequest) throws
125
143
}
126
144
127
145
Map <String , MultipartFile > fileParams = getMultipartMap (serverRequest );
128
- Map <String , List <String >> fileMapInput = readJson (mapParam , new TypeReference <>() {});
146
+ Map <String , List <String >> fileMapInput = readJson (mapParam , new TypeReference <Map < String , List < String >> >() {});
129
147
fileMapInput .forEach ((String fileKey , List <String > objectPaths ) -> {
130
148
MultipartFile file = fileParams .get (fileKey );
131
149
if (file != null ) {
@@ -210,83 +228,3 @@ private static MediaType selectResponseMediaType(ServerRequest serverRequest) {
210
228
}
211
229
212
230
}
213
-
214
- // As in DGS, this is borrowed from https://github.com/graphql-java-kickstart/graphql-java-servlet/blob/eb4dfdb5c0198adc1b4d4466c3b4ea4a77def5d1/graphql-java-servlet/src/main/java/graphql/kickstart/servlet/core/internal/VariableMapper.java
215
- class MultipartVariableMapper {
216
-
217
- private static final Pattern PERIOD = Pattern .compile ("\\ ." );
218
-
219
- private static final Mapper <Map <String , Object >> MAP_MAPPER =
220
- new Mapper <Map <String , Object >>() {
221
- @ Override
222
- public Object set (Map <String , Object > location , String target , MultipartFile value ) {
223
- return location .put (target , value );
224
- }
225
-
226
- @ Override
227
- public Object recurse (Map <String , Object > location , String target ) {
228
- return location .get (target );
229
- }
230
- };
231
- private static final Mapper <List <Object >> LIST_MAPPER =
232
- new Mapper <List <Object >>() {
233
- @ Override
234
- public Object set (List <Object > location , String target , MultipartFile value ) {
235
- return location .set (Integer .parseInt (target ), value );
236
- }
237
-
238
- @ Override
239
- public Object recurse (List <Object > location , String target ) {
240
- return location .get (Integer .parseInt (target ));
241
- }
242
- };
243
-
244
- @ SuppressWarnings ({"unchecked" , "rawtypes" })
245
- public static void mapVariable (String objectPath , Map <String , Object > variables , MultipartFile part ) {
246
- String [] segments = PERIOD .split (objectPath );
247
-
248
- if (segments .length < 2 ) {
249
- throw new RuntimeException ("object-path in map must have at least two segments" );
250
- } else if (!"variables" .equals (segments [0 ])) {
251
- throw new RuntimeException ("can only map into variables" );
252
- }
253
-
254
- Object currentLocation = variables ;
255
- for (int i = 1 ; i < segments .length ; i ++) {
256
- String segmentName = segments [i ];
257
- Mapper mapper = determineMapper (currentLocation , objectPath , segmentName );
258
-
259
- if (i == segments .length - 1 ) {
260
- if (null != mapper .set (currentLocation , segmentName , part )) {
261
- throw new RuntimeException ("expected null value when mapping " + objectPath );
262
- }
263
- } else {
264
- currentLocation = mapper .recurse (currentLocation , segmentName );
265
- if (null == currentLocation ) {
266
- throw new RuntimeException (
267
- "found null intermediate value when trying to map " + objectPath );
268
- }
269
- }
270
- }
271
- }
272
-
273
- private static Mapper <?> determineMapper (
274
- Object currentLocation , String objectPath , String segmentName ) {
275
- if (currentLocation instanceof Map ) {
276
- return MAP_MAPPER ;
277
- } else if (currentLocation instanceof List ) {
278
- return LIST_MAPPER ;
279
- }
280
-
281
- throw new RuntimeException (
282
- "expected a map or list at " + segmentName + " when trying to map " + objectPath );
283
- }
284
-
285
- interface Mapper <T > {
286
-
287
- Object set (T location , String target , MultipartFile value );
288
-
289
- Object recurse (T location , String target );
290
- }
291
- }
292
-
0 commit comments