我有一些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
启用请求重读。但是,当使用管道时,这不再起作用(或者我做错了其他事情)。
我昨天创建了一个问题。参见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
不仅可以转发消费位置,还可以更改检查位置)
我一直在使用控制器的jkotalik's comment方法读取和重置请求正文。这对我有用:
bodyReader.AdvanceTo(readResult.Buffer.Start, readResult.Buffer.Start);
也许这在管道中也起作用?