public static void AddLocation(this ExecutionError error, AbstractNode abstractNode, Document document) { if (abstractNode != null) { if (document != null) { var location = new Location(new Source(document.OriginalQuery), abstractNode.SourceLocation.Start); error.AddLocation(location.Line, location.Column); } else if (abstractNode.SourceLocation.Line > 0 && abstractNode.SourceLocation.Column > 0) { error.AddLocation(abstractNode.SourceLocation.Line, abstractNode.SourceLocation.Column); } } }
public void Validate(Document document, ComplexityConfiguration complexityParameters) { if (complexityParameters == null) return; var complexityResult = Analyze(document, complexityParameters.FieldImpact ?? 2.0f); #if DEBUG Debug.WriteLine($"Complexity: {complexityResult.Complexity}"); Debug.WriteLine($"Sum(Query depth across all subqueries) : {complexityResult.TotalQueryDepth}"); foreach (var node in complexityResult.ComplexityMap) Debug.WriteLine($"{node.Key} : {node.Value}"); #endif if (complexityParameters.MaxComplexity.HasValue && complexityResult.Complexity > complexityParameters.MaxComplexity.Value) throw new InvalidOperationException( $"Query is too complex to execute. The field with the highest complexity is: {complexityResult.ComplexityMap.OrderByDescending(pair => pair.Value).First().Key}"); if (complexityParameters.MaxDepth.HasValue && complexityResult.TotalQueryDepth > complexityParameters.MaxDepth) throw new InvalidOperationException( $"Query is too nested to execute. Depth is {complexityResult.TotalQueryDepth} levels, maximum allowed on this endpoint is {complexityParameters.MaxDepth}."); }
/// <summary> /// Analyzes the complexity of a document. /// </summary> internal ComplexityResult Analyze(Document doc, double avgImpact = 2.0d) { if (avgImpact <= 1) throw new ArgumentOutOfRangeException(nameof(avgImpact)); doc.Children.Where(node => node is FragmentDefinition).Apply(node => { var fragResult = new FragmentComplexity(); FragmentIterator(node, fragResult, avgImpact, avgImpact, 1d); _fragmentMap[(node as FragmentDefinition)?.Name] = fragResult; }); TreeIterator(doc, _result, avgImpact, avgImpact, 1d); // Cleanup in case Analyze is called again _loopCounter = 0; var retVal = _result; _result = new ComplexityResult(); return retVal; }
public IValidationResult Validate( string originalQuery, ISchema schema, Document document, IEnumerable<IValidationRule> rules = null, object userContext = null) { if (!schema.Initialized) { schema.Initialize(); } var context = new ValidationContext { OriginalQuery = originalQuery, Schema = schema, Document = document, TypeInfo = new TypeInfo(schema), UserContext = userContext }; if (rules == null) { rules = CoreRules(); } var visitors = rules.Select(x => x.Validate(context)).ToList(); visitors.Insert(0, context.TypeInfo); // #if DEBUG // visitors.Insert(1, new DebugNodeVisitor()); // #endif var basic = new BasicVisitor(visitors.ToArray()); basic.Visit(document); var result = new ValidationResult(); result.Errors.AddRange(context.Errors); return result; }
public object GetVariableValue(Document document, ISchema schema, VariableDefinition variable, object input) { var type = variable.Type.GraphTypeFromType(schema); if (IsValidValue(schema, type, input)) { if (input == null) { if (variable.DefaultValue != null) { return ValueFromAst(variable.DefaultValue); } } var coercedValue = CoerceValue(schema, type, input.AstFromValue(schema, type)); return coercedValue; } if (input == null) { var error2 = new ExecutionError("Variable '${0}' of required type '{1}' was not provided.".ToFormat(variable.Name, type.Name ?? variable.Type.FullName())); error2.AddLocation(variable, document); throw error2; } var error = new ExecutionError("Variable '${0}' expected value of type '{1}'.".ToFormat(variable.Name, type?.Name ?? variable.Type.FullName())); error.AddLocation(variable, document); throw error; }
public Variables GetVariableValues(Document document, ISchema schema, VariableDefinitions variableDefinitions, Inputs inputs) { var variables = new Variables(); variableDefinitions.Apply(v => { var variable = new Variable(); variable.Name = v.Name; object variableValue = null; inputs?.TryGetValue(v.Name, out variableValue); variable.Value = GetVariableValue(document, schema, v, variableValue); variables.Add(variable); }); return variables; }
public IObjectGraphType GetOperationRootType(Document document, ISchema schema, Operation operation) { IObjectGraphType type; ExecutionError error; switch (operation.OperationType) { case OperationType.Query: type = schema.Query; break; case OperationType.Mutation: type = schema.Mutation; if (type == null) { error = new ExecutionError("Schema is not configured for mutations"); error.AddLocation(operation, document); throw error; } break; case OperationType.Subscription: type = schema.Subscription; if (type == null) { error = new ExecutionError("Schema is not configured for subscriptions"); error.AddLocation(operation, document); throw error; } break; default: error = new ExecutionError("Can only execute queries, mutations and subscriptions."); error.AddLocation(operation, document); throw error; } return type; }
private Operation GetOperation(string operationName, Document document) { var operation = !string.IsNullOrWhiteSpace(operationName) ? document.Operations.WithName(operationName) : document.Operations.FirstOrDefault(); return operation; }
public ExecutionContext BuildExecutionContext( ISchema schema, object root, Document document, Operation operation, Inputs inputs, object userContext, CancellationToken cancellationToken, Metrics metrics) { var context = new ExecutionContext(); context.Document = document; context.Schema = schema; context.RootValue = root; context.UserContext = userContext; context.Operation = operation; context.Variables = GetVariableValues(document, schema, operation.Variables, inputs); context.Fragments = document.Fragments; context.CancellationToken = cancellationToken; context.Metrics = metrics; return context; }
public ExecutionContext BuildExecutionContext( ISchema schema, object root, Document document, string operationName, Inputs inputs, CancellationToken cancellationToken) { var context = new ExecutionContext(); context.Schema = schema; context.RootValue = root; var operation = !string.IsNullOrWhiteSpace(operationName) ? document.Operations.WithName(operationName) : document.Operations.FirstOrDefault(); if (operation == null) { context.Errors.Add(new ExecutionError("Unknown operation name: {0}".ToFormat(operationName))); return context; } context.Operation = operation; context.Variables = GetVariableValues(schema, operation.Variables, inputs); context.Fragments = document.Fragments; context.CancellationToken = cancellationToken; return context; }