public void WriteToOutput(PipeWriter bodyPipe, TagUrlResponse response) { var jsonWriter = new Utf8JsonWriter(bodyPipe, state: default); jsonWriter.WriteStartObject(); jsonWriter.WriteString("url", response.Url); jsonWriter.WriteString("title", response.Title); jsonWriter.WriteString("body", response.Body); jsonWriter.WriteStartArray("existingTags"); foreach (var tag in response.ExistingTags) { jsonWriter.WriteStringValue(tag); } jsonWriter.WriteEndArray(); jsonWriter.WriteStartArray("suggestions"); foreach (var suggestion in response.Suggestions) { jsonWriter.WriteStartObject(); jsonWriter.WriteString("tag", suggestion.Tag); jsonWriter.WriteStartArray("sources"); foreach (var source in suggestion.Sources) { jsonWriter.WriteStringValue(source); } jsonWriter.WriteEndArray(); jsonWriter.WriteEndObject(); } jsonWriter.WriteEndArray(); jsonWriter.WriteEndObject(); jsonWriter.Flush(true); }
public async Task SuggestTags(HttpContext context) { string url = ""; string title = ""; string body = ""; string[] existingTags = { }; if (HttpMethods.IsPost(context.Request.Method)) { if (context.Request.ContentType != MediaTypeNames.Application.Json && context.Request.ContentType != MediaTypeNames.Application.Json + ";charset=utf-8") { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync($"Content type {context.Request.ContentType} not acceptable. Use {MediaTypeNames.Application.Json}"); return; } var requestBody = await JsonDocument.ParseAsync(context.Request.Body); if (!requestBody.RootElement.TryGetProperty("url", out var urlProp)) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync("Missing property 'url'"); return; } if (requestBody.RootElement.TryGetProperty("body", out var bodyProp)) { body = bodyProp.GetString() ?? ""; } if (requestBody.RootElement.TryGetProperty("title", out var titleProp)) { title = titleProp.GetString() ?? ""; } if (requestBody.RootElement.TryGetProperty("existingTags", out var existingTagsProp)) { existingTags = existingTagsProp.EnumerateArray().Select(e => e.GetString()).ToArray(); } url = urlProp.GetString(); } else { if (!context.Request.Query.ContainsKey("url")) { context.Response.StatusCode = (int)HttpStatusCode.BadRequest; await context.Response.WriteAsync("Missing query string parameter 'url'"); return; } url = context.Request.Query["url"].First(); } var key = ("tagSuggestions", url, title, body); var suggestions = await _suggestionsCache.GetOrCreateAsync(key, async cacheEntry => await _tagUrlService .SuggestionsForAsync(url, title, body, existingTags)); var response = new TagUrlResponse { Url = url, Title = title, Body = body, ExistingTags = existingTags, Suggestions = suggestions }; context.Response.ContentType = MediaTypeNames.Application.Json; WriteToOutput(context.Response.BodyPipe, response); // Question: Do I really need this flushasync here? or should that happen somewhere else? await context.Response.BodyPipe.FlushAsync(); }