gpt4 book ai didi

asp.net-mvc - 在 ASP.NET MVC 和 IIS7 中记录原始 HTTP 请求/响应

转载 作者:行者123 更新时间:2023-12-03 04:26:53 25 4
gpt4 key购买 nike

我正在编写一个 Web 服务(使用 ASP.NET MVC),出于支持目的,我们希望能够以尽可能接近原始的在线格式记录请求和响应(即包括 HTTP 方法、路径、所有 header 和正文)到数据库中。

我不确定如何以最少“损坏”的方式获取这些数据。我可以通过检查 HttpRequest 对象的所有属性并从中构建一个字符串(对于响应也类似)来重新构建我认为请求的样子,但我真的很想掌握通过网络发送的实际请求/响应数据。

我很乐意使用任何拦截机制,例如过滤器、模块等,并且该解决方案可以特定于 IIS7。但是,我更愿意仅将其保留在托管代码中。

有什么建议吗?

编辑:我注意到 HttpRequest 有一个 SaveAs方法可以将请求保存到磁盘,但这使用大量无法公开访问的内部帮助器方法从内部状态重建请求(我不知道为什么这不允许保存到用户提供的流) 。因此,看起来我必须尽力从对象中重建请求/响应文本……唉。

编辑2:请注意,我说的是整个请求,包括方法、路径、 header 等。当前响应仅查看正文流,不包括此内容信息。

编辑 3:没有人阅读这里的问题吗?到目前为止有五个答案,但没有一个甚至暗示一种获取整个原始在线请求的方法。是的,我知道我可以捕获输出流、 header 、URL 以及请求对象中的所有内容。我已经在问题中说过了,请参阅:

I can re-constitute what I believe the request looks like by inspecting all the properties of the HttpRequest object and building a string from them (and similarly for the response) but I'd really like to get hold of the actual request/response data that's sent on the wire.

如果您知道无法检索完整原始数据(包括 header 、URL、http 方法等),那么了解这一点将会很有用。同样,如果您知道如何以原始格式获取所有内容(是的,我的意思仍然是包括 header 、url、http 方法等),而无需重建它(这就是我所要求的),那么这将非常有用。但是告诉我可以从 HttpRequest/HttpResponse 对象重建它是没有用的。我知道。我已经说过了。

<小时/>

请注意:在有人开始说这是一个坏主意,或者会限制可扩展性等之前,我们还将在分布式环境中实现节流、顺序交付和反重放机制,因此数据库无论如何,日志记录是必需的。我不是在寻找关于这是否是一个好主意的讨论,而是在寻找如何实现它。

最佳答案

一定要使用 IHttpModule 并实现 BeginRequestEndRequest 事件。

所有“原始”数据都存在于 HttpRequestHttpResponse 之间,只是不是单一的原始格式。以下是构建 Fiddler 风格转储所需的部分(大约尽可能接近原始 HTTP):

request.HttpMethod + " " + request.RawUrl + " " + request.ServerVariables["SERVER_PROTOCOL"]
request.Headers // loop through these "key: value"
request.InputStream // make sure to reset the Position after reading or later reads may fail

对于响应:

"HTTP/1.1 " + response.Status
response.Headers // loop through these "key: value"

请注意,您无法读取响应流,因此您必须向输出流添加过滤器并捕获副本。

在您的BeginRequest中,您需要添加一个响应过滤器:

HttpResponse response = HttpContext.Current.Response;
OutputFilterStream filter = new OutputFilterStream(response.Filter);
response.Filter = filter;

filter 存储在您可以在 EndRequest 处理程序中访问的位置。我建议在 HttpContext.Items 中。然后可以在filter.ReadStream()中获取完整的响应数据。

然后使用装饰器模式作为流的包装器来实现 OutputFilterStream:

/// <summary>
/// A stream which keeps an in-memory copy as it passes the bytes through
/// </summary>
public class OutputFilterStream : Stream
{
private readonly Stream InnerStream;
private readonly MemoryStream CopyStream;

public OutputFilterStream(Stream inner)
{
this.InnerStream = inner;
this.CopyStream = new MemoryStream();
}

public string ReadStream()
{
lock (this.InnerStream)
{
if (this.CopyStream.Length <= 0L ||
!this.CopyStream.CanRead ||
!this.CopyStream.CanSeek)
{
return String.Empty;
}

long pos = this.CopyStream.Position;
this.CopyStream.Position = 0L;
try
{
return new StreamReader(this.CopyStream).ReadToEnd();
}
finally
{
try
{
this.CopyStream.Position = pos;
}
catch { }
}
}
}


public override bool CanRead
{
get { return this.InnerStream.CanRead; }
}

public override bool CanSeek
{
get { return this.InnerStream.CanSeek; }
}

public override bool CanWrite
{
get { return this.InnerStream.CanWrite; }
}

public override void Flush()
{
this.InnerStream.Flush();
}

public override long Length
{
get { return this.InnerStream.Length; }
}

public override long Position
{
get { return this.InnerStream.Position; }
set { this.CopyStream.Position = this.InnerStream.Position = value; }
}

public override int Read(byte[] buffer, int offset, int count)
{
return this.InnerStream.Read(buffer, offset, count);
}

public override long Seek(long offset, SeekOrigin origin)
{
this.CopyStream.Seek(offset, origin);
return this.InnerStream.Seek(offset, origin);
}

public override void SetLength(long value)
{
this.CopyStream.SetLength(value);
this.InnerStream.SetLength(value);
}

public override void Write(byte[] buffer, int offset, int count)
{
this.CopyStream.Write(buffer, offset, count);
this.InnerStream.Write(buffer, offset, count);
}
}

关于asp.net-mvc - 在 ASP.NET MVC 和 IIS7 中记录原始 HTTP 请求/响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1038466/

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