2222import java .util .List ;
2323import java .util .Map ;
2424import java .util .Optional ;
25- import java .util .regex .Pattern ;
2625
2726import javax .servlet .ServletException ;
2827
2928import com .fasterxml .jackson .core .JsonProcessingException ;
3029import com .fasterxml .jackson .core .type .TypeReference ;
30+ import com .fasterxml .jackson .databind .ObjectMapper ;
3131import org .apache .commons .logging .Log ;
3232import org .apache .commons .logging .LogFactory ;
33+ import org .springframework .graphql .server .support .MultipartVariableMapper ;
3334import org .springframework .web .multipart .MultipartFile ;
3435import org .springframework .web .multipart .support .AbstractMultipartHttpServletRequest ;
3536import reactor .core .publisher .Mono ;
@@ -69,22 +70,38 @@ public class GraphQlHttpHandler {
6970
7071 private final WebGraphQlHandler graphQlHandler ;
7172
73+ private final ObjectMapper objectMapper ;
74+
7275 /**
7376 * Create a new instance.
7477 * @param graphQlHandler common handler for GraphQL over HTTP requests
7578 */
7679 public GraphQlHttpHandler (WebGraphQlHandler graphQlHandler ) {
7780 Assert .notNull (graphQlHandler , "WebGraphQlHandler is required" );
7881 this .graphQlHandler = graphQlHandler ;
82+ this .objectMapper = new ObjectMapper ();
7983 }
8084
85+ /**
86+ * Create a new instance.
87+ * @param graphQlHandler common handler for GraphQL over HTTP requests
88+ * @param objectMapper ObjectMapper used for parsing form parts
89+ */
90+ public GraphQlHttpHandler (WebGraphQlHandler graphQlHandler , ObjectMapper objectMapper ) {
91+ Assert .notNull (graphQlHandler , "WebGraphQlHandler is required" );
92+ Assert .notNull (objectMapper , "ObjectMapper is required" );
93+ this .graphQlHandler = graphQlHandler ;
94+ this .objectMapper = objectMapper ;
95+ }
96+
8197 /**
8298 * Handle GraphQL requests over HTTP.
8399 * @param serverRequest the incoming HTTP request
84100 * @return the HTTP response
85101 * @throws ServletException may be raised when reading the request body, e.g.
86102 * {@link HttpMediaTypeNotSupportedException}.
87103 */
104+ @ Deprecated
88105 public ServerResponse handleRequest (ServerRequest serverRequest ) throws ServletException {
89106
90107 WebGraphQlRequest graphQlRequest = new WebGraphQlRequest (
@@ -112,7 +129,7 @@ public ServerResponse handleRequest(ServerRequest serverRequest) throws ServletE
112129 public ServerResponse handleMultipartRequest (ServerRequest serverRequest ) throws ServletException {
113130 Optional <String > operation = serverRequest .param ("operations" );
114131 Optional <String > mapParam = serverRequest .param ("map" );
115- Map <String , Object > inputQuery = readJson (operation , new TypeReference <>() {});
132+ Map <String , Object > inputQuery = readJson (operation , new TypeReference <Map < String , Object > >() {});
116133 final Map <String , Object > queryVariables ;
117134 if (inputQuery .containsKey ("variables" )) {
118135 queryVariables = (Map <String , Object >)inputQuery .get ("variables" );
@@ -125,7 +142,7 @@ public ServerResponse handleMultipartRequest(ServerRequest serverRequest) throws
125142 }
126143
127144 Map <String , MultipartFile > fileParams = getMultipartMap (serverRequest );
128- Map <String , List <String >> fileMapInput = readJson (mapParam , new TypeReference <>() {});
145+ Map <String , List <String >> fileMapInput = readJson (mapParam , new TypeReference <Map < String , List < String >> >() {});
129146 fileMapInput .forEach ((String fileKey , List <String > objectPaths ) -> {
130147 MultipartFile file = fileParams .get (fileKey );
131148 if (file != null ) {
@@ -210,83 +227,3 @@ private static MediaType selectResponseMediaType(ServerRequest serverRequest) {
210227 }
211228
212229}
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