public async Task <ExecutionResultResponse> ExecuteAsync(GraphQlDomainRequest graphQlDomainRequest)
        {
            bool.TryParse(_configuration["GraphQl:EnableMetrics"], out var enableMetrics);
            bool.TryParse(_configuration["GraphQl:ExposeExceptions"], out var exposeExceptions);

            var start = DateTime.UtcNow;

            _graphRequestContext.HttpRequest = _requestContext;

            var options = new ExecutionOptions
            {
                OperationName             = graphQlDomainRequest.OperationName,
                Schema                    = _schema,
                Query                     = graphQlDomainRequest.Query,
                EnableMetrics             = enableMetrics,
                UserContext               = _graphRequestContext.ToUserContext(),
                ThrowOnUnhandledException = !exposeExceptions,
                ValidationRules           = DocumentValidator.CoreRules.Concat(_validationRules)
            };

            if (graphQlDomainRequest.Variables != null)
            {
                options.Inputs = JsonConvert.DeserializeObject <Inputs>(graphQlDomainRequest.Variables.ToString());
            }

            var results = await _documentExecuter.ExecuteAsync(options);

            if (results.Errors != null && results.Errors.Count > 0)
            {
                results.Errors.ToList().ForEach(ex =>
                {
                    _logger.LogError(ex.Message);
                });
            }

            if (enableMetrics)
            {
                results.EnrichWithApolloTracing(start);
            }

            // Using the default ExecutionResult would return a large amount of data back. Hence, we are controlling it with our own wrapper.
            return(results.ToExecutionResultResponse());
        }
        public async Task <ExecutionResult> ExecuteAsync(GraphQlDomainRequest graphQlDomainRequest)
        {
            bool.TryParse(_configuration["GraphQl:EnableMetrics"], out var enableMetrics);
            bool.TryParse(_configuration["GraphQl:ExposeExceptions"], out var exposeExceptions);

            var start = DateTime.UtcNow;

            _graphRequestContext.HttpRequest = _requestContext;

            var options = new ExecutionOptions
            {
                OperationName    = graphQlDomainRequest.OperationName,
                Schema           = _schema,
                Query            = graphQlDomainRequest.Query,
                EnableMetrics    = enableMetrics,
                UserContext      = _graphRequestContext,
                ExposeExceptions = exposeExceptions,
                ValidationRules  = DocumentValidator.CoreRules().Concat(_validationRules)
            };

            if (graphQlDomainRequest.Variables != null)
            {
                options.Inputs = JsonConvert.SerializeObject(graphQlDomainRequest.Variables).ToInputs();
            }

            var results = await _documentExecuter.ExecuteAsync(options);

            if (results.Errors != null && results.Errors.Count > 0)
            {
                results.Errors.ToList().ForEach(ex =>
                {
                    _logger.LogError(ex.Message);
                });
            }

            if (enableMetrics)
            {
                results.EnrichWithApolloTracing(start);
            }

            return(results);
        }
Example #3
0
        public static async Task <IActionResult> ProcessGraphQlRequest(this ExecutionContext executionContext, HttpRequest httpRequest)
        {
            var validateionResult = executionContext.ValidateJwt();

            if (validateionResult != null)
            {
                return(validateionResult);
            }

            var logger = executionContext.Resolve <ILogger>();

            if (string.IsNullOrEmpty(httpRequest.ContentType))
            {
                logger.LogWarning($"Content-type is required.");
                return(new BadRequestResult());
            }

            var contentTypes = httpRequest.ContentType.Split(';');

            if (contentTypes.Contains("application/graphql"))
            {
                // https://graphql.org/learn/serving-over-http/
                // If the "application/graphql" Content-Type header is present, treat the HTTP POST body contents as the GraphQL query string.
                return(await ProcessRequest(executionContext, httpRequest, logger, body =>
                {
                    JObject o;
                    try
                    {
                        o = JObject.Parse(body);
                    }
                    catch
                    {
                        return new GraphQlDomainRequest {
                            Query = body
                        };
                    }

                    if (o.ContainsKey("query"))
                    {
                        var request = new GraphQlDomainRequest
                        {
                            Query = o["query"].ToString()
                        };

                        if (o.ContainsKey("variables"))
                        {
                            request.Variables = o["variables"].ToString();
                        }

                        return request;
                    }

                    return new GraphQlDomainRequest {
                        Query = body
                    };
                }));
            }

            if (contentTypes.Contains("application/json"))
            {
                return(await ProcessRequest(executionContext, httpRequest, logger, JsonConvert.DeserializeObject <GraphQlDomainRequest>));
            }

            logger.LogWarning($"{httpRequest.ContentType} is not supported.");
            return(new BadRequestResult());
        }