|
5 | 5 | using System.Buffers;
|
6 | 6 | using System.Collections.Generic;
|
7 | 7 | using System.Globalization;
|
| 8 | +using System.IO.Pipelines; |
8 | 9 | using System.Text;
|
9 | 10 | using System.Text.Encodings.Web;
|
10 | 11 | using System.Threading.Tasks;
|
@@ -32,39 +33,35 @@ public static int GetMultipleQueriesQueryCount(HttpContext httpContext)
|
32 | 33 | : 1;
|
33 | 34 | }
|
34 | 35 |
|
35 |
| - public static Task RenderFortunesHtml(IEnumerable<Fortune> model, HttpContext httpContext, HtmlEncoder htmlEncoder) |
| 36 | + public static async Task RenderFortunesHtml(IEnumerable<Fortune> model, HttpContext httpContext, HtmlEncoder htmlEncoder) |
36 | 37 | {
|
37 | 38 | httpContext.Response.StatusCode = StatusCodes.Status200OK;
|
38 | 39 | httpContext.Response.ContentType = "text/html; charset=UTF-8";
|
39 | 40 |
|
40 |
| - var sb = StringBuilderCache.Acquire(); |
41 |
| - sb.Append("<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>"); |
| 41 | + Encoding.UTF8.GetBytes("<!DOCTYPE html><html><head><title>Fortunes</title></head><body><table><tr><th>id</th><th>message</th></tr>", httpContext.Response.BodyWriter); |
42 | 42 |
|
43 |
| - Span<char> buffer = stackalloc char[256]; |
44 | 43 | foreach (var item in model)
|
45 | 44 | {
|
46 |
| - sb.Append("<tr><td>"); |
47 |
| - sb.Append(CultureInfo.InvariantCulture, $"{item.Id}"); |
48 |
| - sb.Append("</td><td>"); |
49 |
| - Encode(sb, htmlEncoder, item.Message); |
50 |
| - sb.Append("</td></tr>"); |
| 45 | + Encoding.UTF8.GetBytes("<tr><td>", httpContext.Response.BodyWriter); |
| 46 | + Encoding.UTF8.GetBytes(item.Id.ToString(CultureInfo.InvariantCulture), httpContext.Response.BodyWriter); |
| 47 | + Encoding.UTF8.GetBytes("</td><td>", httpContext.Response.BodyWriter); |
| 48 | + EncodeToPipe(httpContext.Response.BodyWriter, htmlEncoder, item.Message); |
| 49 | + Encoding.UTF8.GetBytes("</td></tr>", httpContext.Response.BodyWriter); |
51 | 50 | }
|
52 | 51 |
|
53 |
| - sb.Append("</table></body></html>"); |
54 |
| - var response = StringBuilderCache.GetStringAndRelease(sb); |
55 |
| - // fortunes includes multibyte characters so response.Length is incorrect |
56 |
| - httpContext.Response.ContentLength = Encoding.UTF8.GetByteCount(response); |
57 |
| - return httpContext.Response.WriteAsync(response); |
| 52 | + Encoding.UTF8.GetBytes("</table></body></html>", httpContext.Response.BodyWriter); |
58 | 53 |
|
59 |
| - static void Encode(StringBuilder sb, HtmlEncoder htmlEncoder, string item) |
| 54 | + await httpContext.Response.BodyWriter.FlushAsync(); |
| 55 | + |
| 56 | + static void EncodeToPipe(PipeWriter writer, HtmlEncoder htmlEncoder, string item) |
60 | 57 | {
|
61 | 58 | Span<char> buffer = stackalloc char[256];
|
62 | 59 | int remaining = item.Length;
|
63 | 60 | do
|
64 | 61 | {
|
65 | 62 | htmlEncoder.Encode(item.AsSpan()[..remaining], buffer, out var consumed, out var written, isFinalBlock: true);
|
66 | 63 | remaining -= consumed;
|
67 |
| - sb.Append(buffer.Slice(0, written)); |
| 64 | + Encoding.UTF8.GetBytes(buffer.Slice(0, written), writer); |
68 | 65 | } while (remaining != 0);
|
69 | 66 | }
|
70 | 67 | }
|
|
0 commit comments