public async Task Invoke(HttpContext context) { // POST application/graphql body is query // POST application/json and { "query": "..." } // TODO: POST /graphql?query={users{name}} // TODO: GET /graphql?query={users{name}} if (!context.Request.Path.Value.StartsWith($"/{Config.GraphQLRoute}")) { await _next(context).ConfigureAwait(false); return; } if (_authenticationEnabled && !context.User.Identity.IsAuthenticated) { context.Response.StatusCode = (int)HttpStatusCode.Unauthorized; return; } if (context.Request.Method != "POST" || !_allowedTypes.Any(context.Request.ContentType.Contains)) { context.Response.StatusCode = (int)HttpStatusCode.NotImplemented; await context.Response.WriteAsync(JsonConvert.SerializeObject(new { errors = new[] { "Not implemented" } })); return; } GraphQLResult result = null; var(success, query, error) = await ParseQuery(context); if (!success) { result = new GraphQLResult { Errors = new List <string> { error } }; } else { var toReplace = new[] { "\r\n", "\\r\\n", "\\n", "\n" }; query = toReplace.Aggregate(query, (acc, curr) => acc.Replace(curr, "")); result = await GraphQL.HandleQuery(query, _datastore); } var json = result.Errors?.Any() == true ? JsonConvert.SerializeObject(new { data = result.Data, errors = result.Errors }) : JsonConvert.SerializeObject(new { data = result.Data }); result.Notifications?.ForEach(msg => _bus.Publish("updated", msg)); context.Response.ContentType = "application/json"; context.Response.StatusCode = result.Errors?.Any() == true ? (int)HttpStatusCode.BadRequest : (int)HttpStatusCode.OK; await context.Response.WriteAsync(json); }
private static Dictionary <string, dynamic> ExecuteMutationFields(dynamic source, dynamic target, Dictionary <string, Fields> fields, string idFieldName, bool isRoot = false) { return(fields.ToDictionary( pair => GetResponseName(pair), pair => { var allowedActions = new[] { "add", "update", "replace", "delete" }; var fieldsToUse = CollectFields(pair.Value.First().SelectionSet); var collectionName = fieldsToUse.Any() ? fieldsToUse.FirstOrDefault().Key : allowedActions.Aggregate(pair.Value.First().Name, (e, c) => e.Replace(c, "")).ToLower(); var collection = ((IDataStore)source).GetCollection(collectionName); if (pair.Value.First().Name.StartsWith("add")) { var newItem = ResolveMutationField(fieldsToUse.First().Key, target, pair.Value, isRoot); var success = collection.InsertOne(newItem); var itemId = ((dynamic)newItem).id; dynamic updateData = success ? new { Method = "POST", Path = $"{collectionName}/{itemId}", Collection = collectionName, ItemId = itemId } : null; ExecutionResult item = GetMutationReturnItem(source, fieldsToUse, itemId, idFieldName); return Tuple.Create(item.Data as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("update")) { dynamic id = GraphQL.GetInputId(pair, idFieldName); ExpandoObject newItem = ResolveMutationField("patch", target, pair.Value, isRoot); var success = collection.UpdateOne(id, newItem); dynamic updateData = success ? new { Method = "PATCH", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; ExecutionResult item = GetMutationReturnItem(source, fieldsToUse, id, idFieldName); return Tuple.Create(item.Data as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("replace")) { dynamic id = GraphQL.GetInputId(pair, idFieldName); dynamic newItem = ResolveMutationField(collectionName, target, pair.Value, isRoot); // Make sure that new data has id field correctly ObjectHelper.SetFieldValue(newItem, idFieldName, id); //newItem.id = id; var success = collection.ReplaceOne(id, newItem as ExpandoObject); dynamic updateData = success ? new { Method = "PUT", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; ExecutionResult item = GetMutationReturnItem(source, fieldsToUse, id, idFieldName); return Tuple.Create(item.Data as object, updateData); //return item.Value as object; } else if (pair.Value.First().Name.StartsWith("delete")) { dynamic id = GraphQL.GetInputId(pair, idFieldName); var success = collection.DeleteOne(id); dynamic updateData = success ? new { Method = "DELETE", Path = $"{collectionName}/{id}", Collection = collectionName, ItemId = id } : null; var item = new ExecutionResult { Data = success }; return Tuple.Create(success, updateData); //return success; } else { return Tuple.Create <dynamic, dynamic>(null, null); } })); }
private static Task <Dictionary <string, object> > ExecuteMutationFieldsAsync(dynamic source, dynamic target, Dictionary <string, Fields> fields, bool isRoot = false) { return(fields.ToDictionaryAsync <KeyValuePair <string, Fields>, string, ResolveFieldResult <object>, object>( pair => GetResponseName(pair), pair => { var allowedActions = new[] { "add", "update", "replace", "delete" }; var fieldsToUse = CollectFields(pair.Value.First().SelectionSet); var collectionName = fieldsToUse.Any() ? fieldsToUse.FirstOrDefault().Key : allowedActions.Aggregate(pair.Value.First().Name, (e, c) => e.Replace(c, "")).ToLower(); var collection = ((IDataStore)source).GetCollection(collectionName); if (pair.Value.First().Name.StartsWith("add")) { var newItem = ResolveMutationFieldAsync(fieldsToUse.First().Key, target, pair.Value, isRoot); var success = collection.InsertOne(newItem); var itemId = ((dynamic)newItem).id; dynamic updateData = success ? new { Method = "POST", Path = $"{collection}/{itemId}", Collection = collection, ItemId = itemId } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, itemId); //return Tuple.Create(item, updateData); //return item; return Task.FromResult(item); } else if (pair.Value.First().Name.StartsWith("update")) { dynamic id = GraphQL.GetInputId(pair); ExpandoObject newItem = ResolveMutationFieldAsync("patch", target, pair.Value, isRoot); var success = collection.UpdateOne(e => e.id == id, newItem); dynamic updateData = success ? new { Method = "PATCH", Path = $"{collection}/{id}", Collection = collection, ItemId = id } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, id); //return Tuple.Create(item, updateData); //return item; return Task.FromResult(item); } else if (pair.Value.First().Name.StartsWith("replace")) { dynamic id = GraphQL.GetInputId(pair); dynamic newItem = ResolveMutationFieldAsync(collectionName, target, pair.Value, isRoot); // Make sure that new data has id field correctly newItem.id = id; var success = collection.ReplaceOne(e => e.id == id, newItem as ExpandoObject); dynamic updateData = success ? new { Method = "PUT", Path = $"{collection}/{id}", Collection = collection, ItemId = id } : null; ResolveFieldResult <object> item = GetMutationReturnItem(source, fieldsToUse, id); //return Tuple.Create(item, updateData); //return item; return Task.FromResult(item); } else if (pair.Value.First().Name.StartsWith("delete")) { dynamic id = GraphQL.GetInputId(pair); var success = collection.DeleteOne(e => e.id == id); dynamic updateData = success ? new { Method = "DELETE", Path = $"{collection}/{id}", Collection = collection, ItemId = id } : null; var item = new ResolveFieldResult <object> { Value = success }; //return Tuple.Create(item, updateData); //return item; return Task.FromResult(item); } else { dynamic r = null; return Tuple.Create(new ResolveFieldResult <object>(), r); } })); }