gpt4 book ai didi

c# - 如何安全地拦截自定义 Owin 中间件中的响应流

转载 作者:IT王子 更新时间:2023-10-29 04:42:10 25 4
gpt4 key购买 nike

我正在尝试编写一个简单的 OWIN中间件,为了拦截响应流。我想要做的是用基于流的自定义类替换原始流,我将能够在其中拦截对响应流的写入。

但是,我遇到了一些问题,因为我无法知道链中的内部中间件组件何时完全写入响应。永远不会调用 Stream 的 Dispose 覆盖。所以我不知道什么时候执行我的处理,这应该发生在响应流的末尾。

这是一个示例代码:

public sealed class CustomMiddleware: OwinMiddleware
{
public CustomMiddleware(OwinMiddleware next)
: base(next)
{
}

public override async Task Invoke(IOwinContext context)
{
var request = context.Request;
var response = context.Response;

// capture response stream

var vr = new MemoryStream();
var responseStream = new ResponseStream(vr, response.Body);

response.OnSendingHeaders(state =>
{
var resp = (state as IOwinContext).Response;
var contentLength = resp.Headers.ContentLength;

// contentLength == null for Chunked responses

}, context);

// invoke the next middleware in the pipeline

await Next.Invoke(context);
}
}

public sealed class ResponseStream : Stream
{
private readonly Stream stream_; // MemoryStream
private readonly Stream output_; // Owin response
private long writtenBytes_ = 0L;

public ResponseStream(Stream stream, Stream output)
{
stream_ = stream;
output_ = output;
}

... // System.IO.Stream implementation

public override void Write(byte[] buffer, int offset, int count)
{
// capture writes to the response stream in our local stream
stream_.Write(buffer, offset, count);

// write to the real output stream
output_.Write(buffer, offset, count);

// update the number of bytes written

writtenBytes_ += count;

// how do we know the response is complete ?
// we could check that the number of bytes written
// is equal to the content length, but content length
// is not available for Chunked responses.
}

protected override void Dispose(bool disposing)
{
// we could perform our processing
// when the stream is disposed of.
// however, this method is never called by
// the OWIN/Katana infrastructure.
}
}

正如我在上面代码的注释中提到的,我可以想到两种策略来检测响应是否完整。

a) 我可以记录写入响应流的字节数并将其与预期的响应长度相关联。但是,对于使用分 block 传输编码的响应,长度是未知的。

b) 当在响应流上调用 Dispose 时,我可以确定响应流已完成。但是,OWIN/Katana 基础结构从不在替换的流上调用 Dispose。

我一直在调查Opaque Streaming为了看看操纵底层 HTTP 协议(protocol)是否是一种可行的方法,但我似乎没有发现 Katana 是否支持 Opaque Streaming。

有没有办法实现我想要的?

最佳答案

我认为您不需要子分类流,但这里是您阅读响应的方法。只需确保此中间件是 OWIN 管道中的第一个中间件,这样它将是最后一个检查响应的中间件。

using AppFunc = Func<IDictionary<string, object>, Task>;

public class CustomMiddleware
{
private readonly AppFunc next;

public CustomMiddleware(AppFunc next)
{
this.next = next;
}

public async Task Invoke(IDictionary<string, object> env)
{
IOwinContext context = new OwinContext(env);

// Buffer the response
var stream = context.Response.Body;
var buffer = new MemoryStream();
context.Response.Body = buffer;

await this.next(env);

buffer.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(buffer);
string responseBody = await reader.ReadToEndAsync();

// Now, you can access response body.
Debug.WriteLine(responseBody);

// You need to do this so that the response we buffered
// is flushed out to the client application.
buffer.Seek(0, SeekOrigin.Begin);
await buffer.CopyToAsync(stream);
}
}

顺便说一句,据我所知,从 OwinMiddleware 派生并不是一个好的做法,因为 OwinMiddleware 是 Katana 特有的。但是,这与您的问题无关。

关于c# - 如何安全地拦截自定义 Owin 中间件中的响应流,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26214113/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com