Rewind request body stream

杀马特。学长 韩版系。学妹 提交于 2019-11-30 16:57:59

Just found one solution. Replacing the original stream with a new stream containing the data.

    public override Task Invoke(IOwinContext context)
    {
        return Task.Run(() => {
            string body = new StreamReader(context.Request.Body).ReadToEnd();
            // log body

            byte[] requestData = Encoding.UTF8.GetBytes(body);
            context.Request.Body = new MemoryStream(requestData);
            this.Next.Invoke(context);
        });
    }

If you are dealing with larger amounts of data, I'm sure a FileStream would also work as the replacement.

Here's a small improvement to the first answer by Despertar, which helped me a lot, but I ran into an issue when working with binary data. The intermediate step of extracting the stream into a string and then putting it back into a byte array using Encoding.UTF8.GetBytes(body) messes up the binary content (the contents will change unless it is an UTF8 encoded string). Here's my fix using Stream.CopyTo():

    public override async Task Invoke(IOwinContext context)
    {
        // read out body (wait for all bytes)
        using (var streamCopy = new MemoryStream())
        {
            context.Request.Body.CopyTo(streamCopy);
            streamCopy.Position = 0; // rewind

            string body = new StreamReader(streamCopy).ReadToEnd();
            // log body

            streamCopy.Position = 0; // rewind again
            context.Request.Body = streamCopy; // put back in place for downstream handlers

            await this.Next.Invoke(context);
        }
    }

Also, MemoryStream is nice because you can check the stream's length before logging the full body (which is something I don't want to do in case someone uploads a huge file).

I know this is old, but just to help anyone that comes across this. You need to seek on the stream: context.Request.Body.Seek(0, SeekOrigin.Begin);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!