@Override
    protected HttpResponse doPost(ServiceRequestContext ctx, HttpRequest request) throws Exception {
        final MediaType contentType = request.contentType();
        if (contentType == null) {
            return unsupportedMediaType();
        }

        // See https://github.com/jaydenseric/graphql-multipart-request-spec/blob/master/readme.md
        if (contentType.is(MediaType.MULTIPART_FORM_DATA)) {
            return HttpResponse.of(FileAggregatedMultipart.aggregateMultipart(ctx, request)
                                                          .thenApply(multipart -> {
                try {
                    final ListMultimap<String, String> multipartParams = multipart.params();
                    final String operationsParam = getValueFromMultipartParam("operations", multipartParams);
                    final String mapParam = getValueFromMultipartParam("map", multipartParams);

                    final Map<String, Object> operations = parseJsonString(operationsParam, JSON_MAP);
                    final Map<String, List<String>> map = parseJsonString(mapParam, MAP_PARAM);
                    final String query = toStringFromJson("query", operations.get("query"));
                    if (Strings.isNullOrEmpty(query)) {
                        return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                               "query is missing: " + operationsParam);
                    }
                    final Map<String, Object> variables = toMapFromJson(operations.get("variables"));
                    final Map<String, Object> copiedVariables = new HashMap<>(variables);
                    final Map<String, Object> extensions = toMapFromJson(operations.get("extensions"));
                    for (Map.Entry<String, List<String>> entry : map.entrySet()) {
                        final List<MultipartFile> multipartFiles = multipart.files().get(entry.getKey());
                        bindMultipartVariable(copiedVariables, entry.getValue(), multipartFiles);
                    }

                    return executeGraphql(ctx, GraphqlRequest.of(query, null, copiedVariables, extensions));
                } catch (JsonProcessingException ex) {
                    return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                           "Failed to parse a JSON document: " + ex.getMessage());
                } catch (IllegalArgumentException ex) {
                    return createResponse(ex);
                } catch (Exception ex) {
                    return HttpResponse.ofFailure(ex);
                }
            }));
        }

        if (contentType.isJson()) {
            return HttpResponse.of(request.aggregate(ctx.eventLoop()).thenApply(req -> {
                try (SafeCloseable ignored = ctx.push()) {
                    final String body = req.contentUtf8();
                    if (Strings.isNullOrEmpty(body)) {
                        return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                               "Missing request body");
                    }

                    try {
                        final Map<String, Object> requestMap = parseJsonString(body, JSON_MAP);
                        final String query = toStringFromJson("query", requestMap.get("query"));
                        if (Strings.isNullOrEmpty(query)) {
                            return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                                   "query is missing");
                        }

                        final String operationName =
                                toStringFromJson("operationName", requestMap.get("operationName"));
                        final Map<String, Object> variables = toMapFromJson(requestMap.get("variables"));
                        final Map<String, Object> extensions = toMapFromJson(requestMap.get("extensions"));

                        return executeGraphql(ctx, GraphqlRequest.of(query, operationName,
                                                                     variables, extensions));
                    } catch (JsonProcessingException ex) {
                        return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                               "Failed to parse a JSON document: " + body);
                    } catch (IllegalArgumentException ex) {
                        return createResponse(ex);
                    } catch (Exception ex) {
                        return HttpResponse.ofFailure(ex);
                    }
                }
            }));
        }

        if (contentType.is(MediaType.GRAPHQL)) {
            return HttpResponse.of(request.aggregate(ctx.eventLoop()).thenApply(req -> {
                try (SafeCloseable ignored = ctx.push()) {
                    final String query = req.contentUtf8();
                    if (Strings.isNullOrEmpty(query)) {
                        return HttpResponse.of(HttpStatus.BAD_REQUEST, MediaType.PLAIN_TEXT,
                                               "query is missing");
                    }

                    try {
                        return executeGraphql(ctx, GraphqlRequest.of(query));
                    } catch (Exception ex) {
                        return HttpResponse.ofFailure(ex);
                    }
                }
            }));
        }

        return unsupportedMediaType();
    }
Should not use {@link JacksonUtil#newDefaultObjectMapper()} that will convert a JSON object into
`scala.Map` if a `jackson-module-scala` module is registered.
graphql-protocol/src/main/java/com/linecorp/armeria/server/graphql/protocol/AbstractGraphqlService.java