private void writeErrors(ExecutionErrors errors, JsonWriter writer, JsonSerializer serializer, bool exposeExceptions) { if (errors == null || !errors.Any()) { return; } writer.WritePropertyName("errors"); writer.WriteStartArray(); errors.Apply(error => { writer.WriteStartObject(); writer.WritePropertyName("message"); // check if return StackTrace, including all inner exceptions serializer.Serialize(writer, exposeExceptions ? error.ToString() : error.Message); if (error.Locations != null) { writer.WritePropertyName("locations"); writer.WriteStartArray(); error.Locations.Apply(location => { writer.WriteStartObject(); writer.WritePropertyName("line"); serializer.Serialize(writer, location.Line); writer.WritePropertyName("column"); serializer.Serialize(writer, location.Column); writer.WriteEndObject(); }); writer.WriteEndArray(); } if (error.Path != null && error.Path.Any()) { writer.WritePropertyName("path"); serializer.Serialize(writer, error.Path); } if (error is ValidationError ve) { writer.WritePropertyName("errorCode"); serializer.Serialize(writer, ve.ErrorCode); } writer.WriteEndObject(); }); writer.WriteEndArray(); }
public override async Task Invoke(IOwinContext context) { try { var schema = _applicationContext.ApplicationCache.RuntimeCache.GetCacheItem <UmbracoSchema>( "Our.Umbraco.GraphQL::Schema", () => new UmbracoSchema( _applicationContext.Services.ContentTypeService, _applicationContext.Services.MemberTypeService, _options ) ); if (false == context.Request.Path.HasValue) { var request = context.Get <GraphQLRequest>("Our.Umbraco.GraphQL::Request"); switch (context.Request.Method) { case "POST": if (request == null) { context.Response.StatusCode = 400; await context.Response.WriteAsync("POST body missing."); return; } break; default: context.Response.StatusCode = 405; await context.Response.WriteAsync("Server supports only POST requests."); return; } IEnumerable <Task <ExecutionResult> > requests = request.Select(async requestParams => { string query = requestParams.Query; string operationName = requestParams.OperationName; string accessToken = context.Request.Query["accessToken"]; Inputs variables = requestParams.Variables; var validationRules = new List <IValidationRule> { new RequiresAuthValidationRule() }; var start = DateTime.Now; MiniProfiler.Start(); var errors = new ExecutionErrors(); var result = await _documentExecutor .ExecuteAsync(x => { x.CancellationToken = context.Request.CallCancelled; //x.ComplexityConfiguration = new ComplexityConfiguration(); x.ExposeExceptions = _options.Debug; if (_options.EnableMetrics) { x.EnableMetrics = true; x.FieldMiddleware.Use <InstrumentFieldsMiddleware>(); x.FieldMiddleware.Use <MiniProfilerFieldsMiddleware>(); } x.FieldNameConverter = new DefaultFieldNameConverter(); x.Inputs = variables; x.OperationName = operationName; x.Query = query; //x.Root = x.Schema = schema; x.UserContext = new UmbracoGraphQLContext( context.Request.Uri, _applicationContext, UmbracoContext.Current, _options, accessToken, out errors ); x.ValidationRules = validationRules; }); // Save any of our errors reported by our authentication stuff in UserContext if (errors.Any()) { if (result.Errors != null) { result.Errors.Concat(errors); } else { result.Errors = errors; } } if (_options.EnableMetrics && result.Errors == null) { result.EnrichWithApolloTracing(start); if (result.Extensions == null) { result.Extensions = new Dictionary <string, object>(); } result.Extensions["miniProfiler"] = JObject.FromObject(MiniProfiler.Current, new JsonSerializer { ContractResolver = new CamelCasePropertyNamesContractResolver() }); } MiniProfiler.Stop(); return(result); }); var responses = await Task.WhenAll(requests); context.Response.ContentType = "application/json"; if (false == request.IsBatched) { var response = _documentWriter.Write(responses[0]); await context.Response.WriteAsync(response); } else { var response = _documentWriter.Write(responses); await context.Response.WriteAsync(response); } } else if (context.Request.Path.ToString() == "/schema") { using (var schemaPrinter = new SchemaPrinter(schema)) { context.Response.ContentType = "text/plain"; await context.Response.WriteAsync(schemaPrinter.Print()); } } } catch (Exception ex) { context.Response.ContentType = "text/plain"; context.Response.StatusCode = 500; if (_options.Debug) { await context.Response.WriteAsync(ex.ToString()); } else { await context.Response.WriteAsync("Internal server error"); } } }