public void validate_core_schema() { var documentExecuter = new DocumentExecuter(); var executionResult = documentExecuter.ExecuteAsync(new Schema(), null, SchemaIntrospection.IntrospectionQuery, null).Result; var json = new DocumentWriter(true).Write(executionResult.Data); json.ShouldBe(IntrospectionResult.Data); }
public async Task ExecutingThenDisposing_DoesNotThrowException() { var executer = new DocumentExecuter(); var schema = new Schema(); await executer.ExecuteAsync(schema, null, "{noop}", null).ConfigureAwait(false); Should.NotThrow(() => schema.Dispose()); }
public void validate_non_null_schema() { var documentExecuter = new DocumentExecuter(); var executionResult = documentExecuter.ExecuteAsync(new TestSchema(), null, InputObjectBugQuery, null).Result; var json = new DocumentWriter(true).Write(executionResult.Data); executionResult.Errors.ShouldBeNull(); json.ShouldBe(InputObjectBugResult); }
public async Task<ExecutionResult> Execute( Schema schema, object rootObject, string query, string operationName = null, Inputs inputs = null) { var executer = new DocumentExecuter(); return await executer.ExecuteAsync(schema, rootObject, query, operationName); }
public ExecutionResult Execute( Schema schema, object rootObject, string query, string operationName = null, Inputs inputs = null) { var executer = new DocumentExecuter(); return executer.Execute(schema, rootObject, query, operationName); }
public GraphQLModule(ISchema schema) { _schema = schema; Get["/graphql", runAsync: true] = async (_, token) => { var queryModel = this.Bind<GraphQLQuery>(); var executer = new DocumentExecuter(); var queryResult = await executer.ExecuteAsync(_schema, null, queryModel.Query, null); return queryResult; ; }; }
public async Task LongMaxValueShouldBeSerialized(IGraphQLTextSerializer serializer) { var documentExecuter = new DocumentExecuter(); var executionResult = await documentExecuter.ExecuteAsync(_ => { _.Schema = new LongSchema(); _.Query = "{ testField }"; }).ConfigureAwait(false); var json = serializer.Serialize(executionResult); executionResult.Errors.ShouldBeNull(); json.ShouldBe(@"{ ""data"": { ""testField"": 9223372036854775807 } }"); }
public void GlobalSetup() { var services = new ServiceCollection(); services.AddSingleton <StarWarsData>(); services.AddSingleton <StarWarsQuery>(); services.AddSingleton <StarWarsMutation>(); services.AddSingleton <HumanType>(); services.AddSingleton <HumanInputType>(); services.AddSingleton <DroidType>(); services.AddSingleton <CharacterInterface>(); services.AddSingleton <EpisodeEnum>(); services.AddSingleton <ISchema, StarWarsSchema>(); _provider = services.BuildServiceProvider(); _schema = _provider.GetRequiredService <ISchema>(); //_schema = new SchemaForIntrospection(); _executer = new DocumentExecuter(); }
public static Task <ExecutionResult> ExecuteQueryAsync <TObjectGraphType>( string query, IDictionary <string, object> userContext = null, object source = null) where TObjectGraphType : IObjectGraphType, new() { var documentExecutor = new DocumentExecuter(); return(documentExecutor.ExecuteAsync(new ExecutionOptions { Query = query, Schema = new Schema { Query = new TObjectGraphType(), }, UserContext = userContext, Root = source, })); }
public async Task Uses_ExecutionStrategySelector() { var queryStrategy = new TestQueryExecutionStrategy(); var mutationStrategy = new TestMutationExecutionStrategy(); var selector = new DefaultExecutionStrategySelector( new[] { new ExecutionStrategyRegistration(queryStrategy, GraphQLParser.AST.OperationType.Query), new ExecutionStrategyRegistration(mutationStrategy, GraphQLParser.AST.OperationType.Mutation), }); var executer = new DocumentExecuter( new GraphQLDocumentBuilder(), new DocumentValidator(), new ComplexityAnalyzer(), DefaultDocumentCache.Instance, new IConfigureExecutionOptions[] { }, selector); var schema = new Schema(); var graphType = new AutoRegisteringObjectGraphType <SampleGraph>(); schema.Query = graphType; schema.Mutation = graphType; schema.Initialize(); var ret = await executer.ExecuteAsync(new ExecutionOptions() { Schema = schema, Query = "{hero}", Root = new SampleGraph(), }).ConfigureAwait(false); ret.Errors.ShouldBeNull(); queryStrategy.Executed.ShouldBeTrue(); ret = await executer.ExecuteAsync(new ExecutionOptions() { Schema = schema, Query = "mutation{hero}", Root = new SampleGraph(), }).ConfigureAwait(false); ret.Errors.ShouldBeNull(); mutationStrategy.Executed.ShouldBeTrue(); }
public void GlobalSetup() { var services = new ServiceCollection(); services.AddSingleton <StarWarsData>(); services.AddSingleton <StarWarsQuery>(); services.AddSingleton <StarWarsMutation>(); services.AddSingleton <HumanType>(); services.AddSingleton <HumanInputType>(); services.AddSingleton <DroidType>(); services.AddSingleton <CharacterInterface>(); services.AddSingleton <EpisodeEnum>(); services.AddSingleton <ISchema, StarWarsSchema>(); _provider = services.BuildServiceProvider(); _schema = _provider.GetRequiredService <ISchema>(); _schema.Initialize(); _executer = new DocumentExecuter(); _cachedExecuter = new DocumentExecuter(new GraphQLDocumentBuilder(), new DocumentValidator(), new ComplexityAnalyzer(), new MemoryDocumentCache()); }
public static async Task <string> ExecuteQuery(string queryString, Inputs?inputs, ValidatorTypeCache cache) { Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US"); queryString = queryString.Replace("'", "\""); using var schema = new Schema(); var documentExecuter = new DocumentExecuter(); var executionOptions = new ExecutionOptions { Schema = schema, Query = queryString, Inputs = inputs } .UseFluentValidation(cache); var result = await documentExecuter.ExecuteAsync(executionOptions); return(await new DocumentWriter(indent: true).WriteToStringAsync(result)); }
public async Task test_parallel() { Num = 0; CancellationTokenSource = new CancellationTokenSource(); var de = new DocumentExecuter(); try { _ = await de.ExecuteAsync(new ExecutionOptions { Query = "{a b}", Schema = new MySchema(), Root = this, CancellationToken = CancellationTokenSource.Token, }); } catch (OperationCanceledException) { } Num.ShouldBe(1); }
public async Task <IActionResult> Post([FromBody] GraphQLQuery query) { if (query == null) { throw new ArgumentNullException(nameof(query)); } var executionOptions = new ExecutionOptions { Schema = Schema, Query = query.Query, Inputs = query.Variables.ToInputs(), ExposeExceptions = true, ValidationRules = DocumentValidator.CoreRules().Concat(ValidationRules) }; var result = await DocumentExecuter.ExecuteAsync(executionOptions).ConfigureAwait(false); return(Ok(result)); }
public IHttpActionResult Post([FromBody] GraphQLQuery query) { var schema = new Schema { Query = new StarWarsQuery(new StarWarsContext()) }; var result = new DocumentExecuter().ExecuteAsync(_ => { _.Schema = schema; _.Query = query.Query; }).Result; if (result.Errors?.Count > 0) { var errors = String.Join(Environment.NewLine, result.Errors.Select(x => x.Message)); return(BadRequest(errors)); } return(Ok(result)); }
public static async Task <ExecutionResult> ExecuteWithErrorCheck(this DocumentExecuter documentExecuter, ExecutionOptions executionOptions) { Guard.AgainstNull(nameof(documentExecuter), documentExecuter); Guard.AgainstNull(nameof(executionOptions), executionOptions); var executionResult = await documentExecuter.ExecuteAsync(executionOptions) .ConfigureAwait(false); var errors = executionResult.Errors; if (errors != null && errors.Count > 0) { if (errors.Count == 1) { throw errors.First(); } throw new AggregateException(errors); } return(executionResult); }
public async Task schema_first_generate_exception_with_normal_stack_trace_for_property() { var schema = Schema.For(@" type Query { method: String! property: Int! } ", builder => builder.Types.Include <Query>()); var executor = new DocumentExecuter(); var result = await executor.ExecuteAsync(options => { options.Schema = schema; options.Query = "{ property }"; }).ConfigureAwait(false); result.Errors.Count.ShouldBe(1); result.Errors[0].Code.ShouldBe("DIVIDE_BY_ZERO"); result.Errors[0].Message.ShouldBe("Error trying to resolve field 'property'."); result.Errors[0].InnerException.ShouldBeOfType <DivideByZeroException>().StackTrace.ShouldStartWith(" at GraphQL.Tests.Utilities.SchemaBuilderExecutionTests.Query.get_Property()"); }
public static void QuerySuccess(GraphQL.Types.Schema schema, string query, string expected, string variables = null, bool compareBoth = true) { var exec = new DocumentExecuter(new GraphQLDocumentBuilder(), new DocumentValidator(), new ComplexityAnalyzer()); var result = exec.ExecuteAsync(schema, null, query, null, variables?.ToInputs()).Result; var result2 = DocumentOperations.ExecuteOperationsAsync(schema, null, query, variables?.ToInputs()).Result; var writtenResult = JsonConvert.SerializeObject(result.Data); var writtenResult2 = JsonConvert.SerializeObject(result2.Data); var queryResult = CreateQueryResult(expected); var expectedResult = JsonConvert.SerializeObject(queryResult.Data); var errors = result.Errors?.FirstOrDefault(); var errors2 = result2.Errors?.FirstOrDefault(); //for easy debugging var allTypes = schema.AllTypes; Assert.Null(errors?.Message); Assert.Null(errors2?.Message); Assert.Equal(expectedResult, writtenResult); Assert.Equal(expectedResult, writtenResult2); }
public async Task DocumentExecuter_really_big_double_Invalid() { var de = new DocumentExecuter(); _maxNumber.ShouldBe("1797693134862320000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0"); var valid = await de.ExecuteAsync(new ExecutionOptions { // create a floating-point value that is larger than double.MaxValue // in the expression "{double.MaxValue:0}0.0" below, the 0.0 effectively // multiplies double.MaxValue by 10 and the .0 forces the parser to // assume it is a floating point value rather than a large integer Query = $"{{ test(arg:{_maxNumber}) }}", Schema = Schema, }).ConfigureAwait(false); valid.ShouldNotBeNull(); valid.Data.ShouldBeNull(); valid.Errors.ShouldNotBeNull(); valid.Errors.Count.ShouldBe(1); valid.Errors[0].Message.ShouldBe($"Argument 'arg' has invalid value. Expected type 'Float', found {_maxNumber}."); }
public static Task <ExecutionResult> ExecuteQueryAsync <TObjectGraphType>( IServiceProvider serviceProvider, string query, IDictionary <string, object>?userContext = null, object?source = null) where TObjectGraphType : IObjectGraphType { var graphType = (IObjectGraphType)serviceProvider.GetService(typeof(TObjectGraphType)); var documentExecutor = new DocumentExecuter(); return(documentExecutor.ExecuteAsync(new ExecutionOptions { Query = query, Schema = new Schema { Query = graphType, }, UserContext = userContext, Root = source, })); }
public async Task DocumentExecuter_has_valid_options() { var de = new DocumentExecuter(); var valid = await de.ExecuteAsync(new ExecutionOptions { Query = "{test}", Schema = Schema, }); await Assert.ThrowsAsync <InvalidOperationException>(async() => { await de.ExecuteAsync(new ExecutionOptions() { Query = null, Schema = Schema, }); }); await Assert.ThrowsAsync <InvalidOperationException>(async() => { await de.ExecuteAsync(new ExecutionOptions() { Query = "{test}", Schema = null, }); }); await Assert.ThrowsAsync <InvalidOperationException>(async() => { await de.ExecuteAsync(new ExecutionOptions() { Query = "{test}", Schema = Schema, FieldMiddleware = null, }); }); }
public async Task schema_first_generate_exception_with_normal_stack_trace_for_method() { var schema = Schema.For(@" type Query { method: String! property: Int! } ", builder => builder.Types.Include <Query>()); var executor = new DocumentExecuter(); var result = await executor.ExecuteAsync(options => { options.Schema = schema; options.Query = "{ method }"; }).ConfigureAwait(false); result.Errors.Count.ShouldBe(1); result.Errors[0].Code.ShouldBe("OVERFLOW"); result.Errors[0].Message.ShouldBe("Error trying to resolve field 'method'."); var stack = result.Errors[0].InnerException.ShouldBeOfType <OverflowException>().StackTrace; if (stack.StartsWith(" в ")) { stack = stack.Remove(0, 5); } if (stack.StartsWith(" at ")) { stack = stack.Remove(0, 6); } if (stack.StartsWith(" 在 ")) { stack = stack.Remove(0, 5); } stack.ShouldStartWith("GraphQL.Tests.Utilities.SchemaBuilderExecutionTests.Query.Method()"); }
static void Main(string[] args) { /* * Schema schema = new Schema { Query = new RootQueries() }; * string resultJson = schema.Execute(_ => * { * _.Query = "{queryPerson{id name age}}"; * _.FieldMiddleware.Use(next => * { * return context =>{ * return new MyMiddleWare().Invock(context, next); * }; * * }); * }); * Console.WriteLine(resultJson); * Console.ReadKey(); */ Schema schema = new Schema { Query = new RootQueries() }; var start = DateTime.UtcNow; var executor = new DocumentExecuter(); ExecutionResult result = executor.ExecuteAsync(_ => { _.Schema = schema; _.Query = "query{queryPerson{id name age}}"; _.EnableMetrics = true; _.FieldMiddleware.Use <MyMiddleWare>(); }).Result; result.EnrichWithApolloTracing(start); string serialStr = Newtonsoft.Json.JsonConvert.SerializeObject(result); Console.WriteLine(serialStr); Console.ReadKey(); }
public async Task GraphQLFieldQuery_Test() { var root = new RootQuery(); var mutation = new RootMutation(); var schema = new GraphQLRootSchema(root, mutation); var queryBuilder = new BasicQueryBuilder(); var executor = new DocumentExecuter(); schema.Register(queryBuilder); Assert.True(schema.Query.HasField("defaultTest")); var result = await executor.ExecuteAsync(new ExecutionOptions() { Schema = schema, Query = "query TestQuery { defaultTest(returnOne: 5, returnTwo: 5) }", OperationName = "TestQuery" }).ConfigureAwait(false); Assert.NotNull(result); Assert.NotNull(result?.Data); Assert.Equal(10, ((Dictionary <string, object>)result?.Data)["defaultTest"]); }
public GraphQLTestBase(ITestOutputHelper output) { Log.Logger = new LoggerConfiguration().MinimumLevel.Debug().WriteTo.Console().CreateLogger(); _output = output; var store = new DefaultStore(null); var stateStore = new TrieStateStore( new DefaultKeyValueStore(null), new DefaultKeyValueStore(null) ); var genesisBlock = BlockChain <PolymorphicAction <ActionBase> > .MakeGenesisBlock(blockAction : new RewardGold()); var blockPolicy = new BlockPolicy <PolymorphicAction <ActionBase> >(blockAction: new RewardGold()); var blockChain = new BlockChain <PolymorphicAction <ActionBase> >( blockPolicy, store, stateStore, genesisBlock, renderers: new IRenderer <PolymorphicAction <ActionBase> >[] { new BlockRenderer(), new ActionRenderer() } ); var tempKeyStorePath = Path.Join(Path.GetTempPath(), Path.GetRandomFileName()); var keyStore = new Web3KeyStore(tempKeyStorePath); StandaloneContextFx = new StandaloneContext { BlockChain = blockChain, KeyStore = keyStore, }; Schema = new StandaloneSchema(new TestServiceProvider(StandaloneContextFx)); Schema.Subscription.As <StandaloneSubscription>().RegisterTipChangedSubscription(); DocumentExecutor = new DocumentExecuter(); }
private static void RunQuery() { var query = @" { droids { droidId name primaryFunction appearsIn friends { name ... on Human { humanId appearsIn } } } }"; var executer = new DocumentExecuter(); var writer = new DocumentWriter(true); string output1, output2; // Example 1 - QueryRoot. using (var root = new QueryRoot()) using (var schema = new Schema <QueryRoot>()) { var result = executer.ExecuteAsync(schema, root, query, null).Result; output1 = writer.Write(result); Console.WriteLine("Example 1 output (QueryRoot):"); Console.WriteLine("-----------------------------"); Console.WriteLine(output1); Console.WriteLine(); } // Example 2 - DbContext. // I get the feeling there are reasons why wouldn't // want to do this but for simple scenarios it seems to suffice. using (var db = new StarWarsContext()) using (var schema = new Schema <StarWarsContext>()) { var result = executer.ExecuteAsync(schema, db, query, null).Result; output2 = writer.Write(result); Console.WriteLine("Example 2 output (StarWarsContext):"); Console.WriteLine("-----------------------------------"); Console.WriteLine(output2); Console.WriteLine(); } // Confirm we got the same result, just 'cause... var defaultColor = Console.ForegroundColor; if (output1 == output2) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("✓ Outputs are the same"); } else { Console.ForegroundColor = ConsoleColor.DarkRed; Console.WriteLine("× Outputs are different"); } Console.ForegroundColor = defaultColor; }
public async Task VerifyCorrectExecutionOrder() { var sb = new StringBuilder(); Func <IResolveFieldContext, object> resolver = context => { sb.AppendLine(string.Join(".", context.ResponsePath)); return("test"); }; var leaderGraphType = new ObjectGraphType() { Name = "LoaderType" }; leaderGraphType.Field <StringGraphType>("lastName", resolve: resolver); leaderGraphType.Field <StringGraphType>("name", resolve: resolver); var familiesGraphType = new ObjectGraphType() { Name = "FamiliesType" }; familiesGraphType.Field("leader", leaderGraphType, resolve: resolver); familiesGraphType.Field("leader_dataLoader", leaderGraphType, resolve: context => { resolver(context); return(new SimpleDataLoader <object>(ctx => { sb.AppendLine(string.Join(".", context.ResponsePath) + "-completed"); return Task.FromResult <object>("test"); })); }); var queryGraphType = new ObjectGraphType(); queryGraphType.Field("families", new ListGraphType(familiesGraphType), resolve: context => { resolver(context); return(new object[] { "a", "a", "a" }); }); var schema = new Schema { Query = queryGraphType, Mutation = queryGraphType, }; var documentExecuter = new DocumentExecuter(); var executionOptions = new ExecutionOptions() { Schema = schema, Query = "mutation { families { leader_dataLoader { lastName name } leader { lastName name } } }", }; await documentExecuter.ExecuteAsync(executionOptions); sb.ToString().ShouldBeCrossPlat(@"families families.0.leader_dataLoader families.0.leader families.0.leader.lastName families.0.leader.name families.1.leader_dataLoader families.1.leader families.1.leader.lastName families.1.leader.name families.2.leader_dataLoader families.2.leader families.2.leader.lastName families.2.leader.name families.0.leader_dataLoader-completed families.1.leader_dataLoader-completed families.2.leader_dataLoader-completed families.0.leader_dataLoader.lastName families.0.leader_dataLoader.name families.1.leader_dataLoader.lastName families.1.leader_dataLoader.name families.2.leader_dataLoader.lastName families.2.leader_dataLoader.name "); }
public QueryGraphTypeTests() { Schema = new SimpleSchema(); Executer = new DocumentExecuter(); Serializer = new GraphQLSerializer(); }
public BaseGraphQLController(ISchema schema, DocumentExecuter documentExecuter, ILogger <BaseGraphQLController> logger) { _schema = schema; _documentExecuter = documentExecuter; _logger = logger; }
public ApiController(IContainer container) { Container = container; Executer = new DocumentExecuter(); Schema = Container.GetInstance <ApiSchema>(); }
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); }
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.WebSockets.IsWebSocketRequest) { await next(context); return; } // Handle requests as per recommendation at http://graphql.org/learn/serving-over-http/ var httpRequest = context.Request; var gqlRequest = new GraphQLRequest(); var documentWriter = new DocumentWriter(_schema.GetJsonSerializerSettings()); if (HttpMethods.IsGet(httpRequest.Method) || (HttpMethods.IsPost(httpRequest.Method) && httpRequest.Query.ContainsKey(GraphQLRequest.QueryKey))) { ExtractGraphQLRequestFromQueryString(httpRequest.Query, gqlRequest); } else if (HttpMethods.IsPost(httpRequest.Method)) { if (!MediaTypeHeaderValue.TryParse(httpRequest.ContentType, out var mediaTypeHeader)) { await WriteBadRequestResponseAsync(context, documentWriter, $"Invalid 'Content-Type' header: value '{httpRequest.ContentType}' could not be parsed."); return; } switch (mediaTypeHeader.MediaType) { case JsonContentType: gqlRequest = Deserialize <GraphQLRequest>(httpRequest.Body); break; case GraphQLContentType: gqlRequest.Query = await ReadAsStringAsync(httpRequest.Body); break; case FormUrlEncodedContentType: var formCollection = await httpRequest.ReadFormAsync(); ExtractGraphQLRequestFromPostBody(formCollection, gqlRequest); break; default: await WriteBadRequestResponseAsync(context, documentWriter, $"Invalid 'Content-Type' header: non-supported media type. Must be of '{JsonContentType}', '{GraphQLContentType}', or '{FormUrlEncodedContentType}'. See: http://graphql.org/learn/serving-over-http/."); return; } } IEnumerable <IValidationRule> validationRules; try { validationRules = _container.GetAllInstances <IValidationRule>(); } catch (Exception ex) { _logger.LogError(ex.Message, ex); validationRules = new IValidationRule[0]; } var executer = new DocumentExecuter(); var result = await executer.ExecuteAsync(x => { x.Schema = _schema; x.OperationName = gqlRequest.OperationName; x.Query = gqlRequest.Query; x.Inputs = gqlRequest.GetInputs(); x.UserContext = _userContextBuilder.BuildContext(); x.ValidationRules = validationRules.Concat(DocumentValidator.CoreRules); x.CancellationToken = context.RequestAborted; x.ComplexityConfiguration = _complexityConfigurationFactory.GetComplexityConfiguration(); }); if (result.Errors?.Any(x => x.Code == "auth-required") == true && context.Response.Headers.ContainsKey("Token-Expired")) { await WriteUnauthorizedResponseAsync(context, documentWriter, result); } else { await WriteResponseAsync(context, documentWriter, result); } }
public ApiController(IContainer container) { Container = container; Executer = new DocumentExecuter(); Schema = new ApiSchema(container, Assembly.GetExecutingAssembly()); }
/// <summary> /// Execute all operations async. /// </summary> /// <returns>Aggregated results.</returns> public static async Task <ExecutionResult> ExecuteOperationsAsync( ISchema schema, object root, string query, Inputs inputs = null, CancellationToken cancellationToken = default(CancellationToken), IEnumerable <IValidationRule> rules = null, bool validate = true, IDocumentBuilder documentBuilder = null, int?maxOperationNodes = null, int?maxTasksAllowed = null ) { var savedDocument = new SavedDocumentBuilder(query, documentBuilder); if (savedDocument.OperationNodes > maxOperationNodes) { throw new InvalidOperationException($"Graph query contains more than the allowed operation limit ({maxOperationNodes}) for one request."); } if (savedDocument.Document.Operations == null || savedDocument.Document.Operations.Count() <= 1) { //run the typical way. var defaultBuilder = new DocumentExecuter(savedDocument, DocumentValidator, ComplexityAnalyzerInstance, maxTasksAllowed); return (await defaultBuilder.ExecuteAsync( new ExecutionOptions { Schema = schema, Root = root, Query = query, Inputs = inputs, CancellationToken = cancellationToken, ValidationRules = rules, EnableDocumentValidation = validate, EnableMetrics = false, SetFieldMiddleware = false })); } var result = new ExecutionResult(); var nonValidatedExecutionar = new DocumentExecuter(savedDocument, DocumentValidator, ComplexityAnalyzerInstance, maxTasksAllowed); var aggregateData = new Dictionary <string, object>(); try { if (validate) { var validationResult = DocumentValidator.Validate(query, schema, savedDocument.Document, rules); if (!validationResult.IsValid) { result.Data = aggregateData; result.Errors = validationResult.Errors; return(result); } } foreach (var operation in savedDocument.Document.Operations) { var opResult = await nonValidatedExecutionar.ExecuteAsync(new ExecutionOptions { Schema = schema, Root = root, Query = query, Inputs = inputs, CancellationToken = cancellationToken, ValidationRules = rules, OperationName = operation.Name, EnableDocumentValidation = false, EnableMetrics = false, SetFieldMiddleware = false }); if (opResult.Errors != null && opResult.Errors.Any()) { return(opResult); } aggregateData.Add(operation.Name, opResult.Data); } } catch (Exception exc) { if (result.Errors == null) { result.Errors = new ExecutionErrors(); } result.Data = null; result.Errors.Add(new ExecutionError(exc.Message, exc)); return(result); } result.Data = aggregateData; return(result); }
public async Task InvokeAsync(HttpContext context, RequestDelegate next) { if (context.WebSockets.IsWebSocketRequest || !context.Request.Path.StartsWithSegments(_path)) { await next(context); return; } // Handle requests as per recommendation at http://graphql.org/learn/serving-over-http/ var httpRequest = context.Request; var gqlRequest = new GraphQLRequest(); var documentWriter = new DocumentWriter(Formatting.Indented, _schema.GetJsonSerializerSettings()); if (HttpMethods.IsGet(httpRequest.Method) || (HttpMethods.IsPost(httpRequest.Method) && httpRequest.Query.ContainsKey(GraphQLRequest.QueryKey))) { ExtractGraphQLRequestFromQueryString(httpRequest.Query, gqlRequest); } else if (HttpMethods.IsPost(httpRequest.Method)) { if (!MediaTypeHeaderValue.TryParse(httpRequest.ContentType, out var mediaTypeHeader)) { await WriteBadRequestResponseAsync(context, documentWriter, $"Invalid 'Content-Type' header: value '{httpRequest.ContentType}' could not be parsed."); return; } switch (mediaTypeHeader.MediaType) { case JsonContentType: gqlRequest = Deserialize <GraphQLRequest>(httpRequest.Body); break; case GraphQLContentType: gqlRequest.Query = await ReadAsStringAsync(httpRequest.Body); break; case FormUrlEncodedContentType: var formCollection = await httpRequest.ReadFormAsync(); ExtractGraphQLRequestFromPostBody(formCollection, gqlRequest); break; default: await WriteBadRequestResponseAsync(context, documentWriter, $"Invalid 'Content-Type' header: non-supported media type. Must be of '{JsonContentType}', '{GraphQLContentType}', or '{FormUrlEncodedContentType}'. See: http://graphql.org/learn/serving-over-http/."); return; } } var executer = new DocumentExecuter(); var result = await executer.ExecuteAsync(x => { x.Schema = _schema; x.OperationName = gqlRequest.OperationName; x.Query = gqlRequest.Query; x.Inputs = gqlRequest.GetInputs(); x.UserContext = _userContextBuilder.BuildContext(); x.ValidationRules = new[] { new AuthenticationValidationRule() }.Concat(DocumentValidator.CoreRules); x.CancellationToken = context.RequestAborted; x.ComplexityConfiguration = _complexityConfigurationFactory.GetComplexityConfiguration(); }); if (result.Errors != null) { _logger.LogError("GraphQL execution error(s): {Errors}", result.Errors); } await WriteResponseAsync(context, documentWriter, result); }
/// <summary> /// Check the schema against introspection query /// </summary> /// <param name="schema">The schema</param> /// <returns>List of errors</returns> public static IEnumerable <string> CheckSchemaIntrospection(Schema schema) { var result = new DocumentExecuter().ExecuteAsync( r => { r.Schema = schema; r.Query = Queries.IntrospectionQuery; r.UserContext = new RequestContext(); }).Result; var response = new DocumentWriter(true).Write(result); var json = JObject.Parse(response); var types = (json.SelectToken("data.__schema.types") as JArray)?.ToDictionary( p => ((JObject)p).Property("name")?.Value, p => (JObject)p); if (types == null) { yield return("Could not get types list via introspection"); yield break; } var inputTypesChecked = new List <string>(); foreach (var type in types.Values.Where(t => !t.Property("name").Value.ToObject <string>().StartsWith("__"))) { var typeName = type.Property("name").Value.ToObject <string>(); var fields = type.Property("fields")?.Value as JArray; if (fields != null) { foreach (var field in fields) { var fieldType = field.SelectToken("type.kind")?.ToObject <string>() == "LIST" ? field.SelectToken("type.ofType.name")?.ToObject <string>() : field.SelectToken("type.name")?.ToObject <string>(); var fieldName = field.SelectToken("name")?.ToObject <string>(); if (!types.ContainsKey(fieldType ?? string.Empty)) { yield return($"{typeName} property {fieldName} has unknown type {fieldType}"); } var arguments = field.SelectToken("args") as JArray; if (arguments == null || arguments.Count == 0) { continue; } foreach (var argument in arguments) { var argumentType = argument.SelectToken("type.kind")?.ToObject <string>() == "LIST" ? argument.SelectToken("type.ofType.name")?.ToObject <string>() : argument.SelectToken("type.name")?.ToObject <string>(); var argumentName = argument.SelectToken("name")?.ToObject <string>(); JObject argumentTypeJson; if (!types.TryGetValue(argumentType ?? string.Empty, out argumentTypeJson)) { yield return ($"{typeName} property {fieldName} " + $"has argument {argumentName} of unknown type {argumentType}"); } else { var argumentTypeKind = argumentTypeJson.SelectToken("kind").ToObject <string>(); if (argumentTypeKind != "SCALAR" && argumentTypeKind != "ENUM" && argumentTypeKind != "INPUT_OBJECT") { yield return ($"{typeName} property {fieldName} " + $"has argument {argumentName} of type {argumentType} " + $"of unsupported kind {argumentTypeKind}"); } else if (argumentTypeKind == "INPUT_OBJECT") { foreach ( var error in CheckIntrospectionInputType(argumentTypeJson, types, inputTypesChecked)) { yield return(error); } } } } } } } }