private static async Task <GraphQlParameters> GetParametersAsync(HttpRequest request)
        {
            // http://graphql.org/learn/serving-over-http/#http-methods-headers-and-body

            string body = null;

            if (request.Method == "POST")
            {
                // Read request body
                using (var sr = new StreamReader(request.Body))
                {
                    body = await sr.ReadToEndAsync();
                }
            }

            MediaTypeHeaderValue.TryParse(request.ContentType, out MediaTypeHeaderValue contentType);

            GraphQlParameters parameters;

            switch (contentType.MediaType)
            {
            case "application/json":
                // Parse request as json
                parameters = JsonConvert.DeserializeObject <GraphQlParameters>(body);
                break;

            case "application/graphql":
                // The whole body is the query
                parameters = new GraphQlParameters {
                    Query = body
                };
                break;

            default:
                // Don't parse anything
                parameters = new GraphQlParameters();
                break;
            }

            string query = request.Query["query"];

            // Query string "query" overrides a query in the body
            parameters.Query = query ?? parameters.Query;

            return(parameters);
        }
        public async Task Invoke(HttpContext httpContext)
        {
            var logger = httpContext.RequestServices.GetService <ILogger <GraphQlMiddleware> >();

            HttpRequest  request  = httpContext.Request;
            HttpResponse response = httpContext.Response;

            // GraphQL HTTP only supports GET and POST methods.
            if (request.Method != "GET" && request.Method != "POST")
            {
                response.Headers.Add("Allow", "GET, POST");
                response.StatusCode = 405;

                return;
            }

            // Check authorization
            if (_options.AuthorizationPolicy != null)
            {
                var authorizationService = httpContext.RequestServices.GetRequiredService <IAuthorizationService>();
                var authzResult          = await authorizationService.AuthorizeAsync(httpContext.User, _options.AuthorizationPolicy);

                if (!authzResult.Succeeded)
                {
                    await httpContext.ForbidAsync();

                    return;
                }
            }

            GraphQlParameters parameters = await GetParametersAsync(request);

            ISchema schema = _schemaProvider.Create(httpContext.RequestServices);

            var executer = new DocumentExecuter();

            var result = await executer.ExecuteAsync(options =>
            {
                options.Schema                  = schema;
                options.Query                   = parameters.Query;
                options.OperationName           = parameters.OperationName;
                options.Inputs                  = parameters.GetInputs();
                options.CancellationToken       = httpContext.RequestAborted;
                options.ComplexityConfiguration = _options.ComplexityConfiguration;
                options.UserContext             = httpContext;
                options.ExposeExceptions        = _options.ExposeExceptions;
            });

            if (result.Errors?.Count > 0)
            {
                logger.LogError("GraphQL Result {Errors}", result.Errors);
            }

            var writer = new DocumentWriter(indent: _options.FormatOutput);
            var json   = writer.Write(result);

            response.StatusCode  = 200;
            response.ContentType = "application/json; charset=utf-8";

            await response.WriteAsync(json);
        }