如何使用PipeWriter阅读和更新HttpResponse正文?

时间:2019-10-07 20:28:34

标签: .net-core-3.0

这实际上是一个与.net core 3.0直接相关的两部分问题,尤其是与PipeWriter相关的问题:1)我应该如何在HttpResponse正文中阅读? 2)如何更新HttpResponse?我问这两个问题是因为我觉得解决方案可能会涉及相同的理解和代码。

下面是我如何在.net core 2.2中工作的注意-请注意,这是使用流而不是PipeWriter以及与流相关的其他“丑陋”事物-例如。 MemoryStream,Seek,StreamReader等。

public class MyMiddleware
{
    private RequestDelegate Next { get; }
    public MyMiddleware(RequestDelegate next) => Next = next;

    public async Task Invoke(HttpContext context)
    {
        var httpResponse = context.Response;
        var originalBody = httpResponse.Body;
        var newBody = new MemoryStream();
        httpResponse.Body = newBody;

        try
        {
            await Next(context);
        }
        catch (Exception)
        {
            // In this scenario, I would log out the actual error and am returning this "nice" error
            httpResponse.StatusCode = StatusCodes.Status500InternalServerError;
            httpResponse.ContentType = "application/json"; // I'm setting this because I might have a serialized object instead of a plain string
            httpResponse.Body = originalBody;
            await httpResponse.WriteAsync("We're sorry, but something went wrong with your request.");
            return;
        }

        // If everything worked
        newBody.Seek(0, SeekOrigin.Begin);
        var response = new StreamReader(newBody).ReadToEnd(); // This is the only way to read the existing response body
        httpResponse.Body = originalBody;
        await context.Response.WriteAsync(response);
    }
}

使用PipeWriter如何工作?例如。似乎最好使用管道而不是基础流,但是我还找不到任何有关如何使用它代替上面的代码的示例?

是否存在一种情况,我需要等待流/管道完成写入,然后才能将其读回和/或用新的字符串替换?我从来没有亲自做过,但是看PipeReader的例子似乎表明要分块阅读并检查IsComplete。

1 个答案:

答案 0 :(得分:0)

要更新HttpRepsonse是

 private  async Task WriteDataToResponseBodyAsync(PipeWriter writer, string jsonValue)
        {
            // use an oversized size guess
            Memory<byte> workspace = writer.GetMemory();
            // write the data to the workspace
            int bytes = Encoding.ASCII.GetBytes(
               jsonValue, workspace.Span);
            // tell the pipe how much of the workspace
            // we actually want to commit
            writer.Advance(bytes);
            // this is **not** the same as Stream.Flush!
            await writer.FlushAsync();
        }