如何重置PipeReader以便能够在ASP.NET Core中重新读取请求正文

问题描述 投票:2回答:2

我有一些ASP.NET Core中间件(AuthorizationHandler),需要访问请求的主体以执行授权检查。我使用新的pipelines APIs访问请求正文。代码如下:

PipeReader bodyReader = httpContext.Request.BodyReader;

ReadResult readResult = await bodyReader.ReadAsync();
ReadOnlySequence<byte> readResultBuffer = readResult.Buffer;

var utf8JsonReader = new Utf8JsonReader(bytes);
while (utf8JsonReader.Read()) { ... }

运行此代码后,将读取主体流。我要调用的控制器抛出验证错误,因为由于已被读取而没有看到请求正文。

因此,如何重置PipeReader,以便可以重新读取请求正文?

我知道,当您不使用BodyReader而是使用BodyReader时,可以使用Body启用请求重读。但是,当使用管道时,这不再起作用(或者我做错了其他事情)。

asp.net-core io asp.net-core-3.0 asp.net-core-3.1
2个回答
1
投票

我昨天创建了一个问题。参见Body

通过传递readResult.Buffer.Start进行消耗,是说您没有消耗任何ReadResult。通过传递readResult.Buffer.End,就意味着您已经检查了所有内容,这告诉Pipe不释放任何缓冲区,并且下次ReadAsync返回时,缓冲区中将包含更多数据

这激励我调用EnableBuffering以重置检查的位置。

例如,您的中间件可以编写如下:

异步任务IMiddleware.InvokeAsync(HttpContext httpContext,RequestDelegate接下来){if(httpContext.Request.Method!= HttpMethods.Post){返回;}var bodyReader = httpContext.Request.BodyReader; //不要通过`PipeReader.Create(httpContext.Request.Body);`来获取//演示:读取所有正文而不消耗它ReadResult readResult;while(true){readResult =等待bodyReader.ReadAsync();if(readResult.IsCompleted){中断; }//不要消耗它们,但要检查它们bodyReader.AdvanceTo(readResult.Buffer.Start,readResult.Buffer.End);}//现在,所有主体有效负载都已读入缓冲区var buffer = readResult.Buffer;处理(参考缓冲区); //处理有效载荷(ReadOnlySequence)//最后,在这里重设已检查的位置bodyReader.AdvanceTo(readResult.Buffer.Start,readResult.Buffer.Start);等待next(httpContext);}无效处理(ref ReadOnlySequence 缓冲区){var utf8JsonReader = new Utf8JsonReader(buffer);while(utf8JsonReader.Read()){Console.WriteLine($“ {utf8JsonReader.TokenType}”);...}}

((键为EnableBuffering不仅可以转发消费位置,还可以更改检查位置)


0
投票

我一直在使用控制器的jkotalik's comment方法读取和重置请求正文。这对我有用:

bodyReader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.Start);

也许这在管道中也起作用?

© www.soinside.com 2019 - 2024. All rights reserved.