一定要使用 IHttpModule
并实现 BeginRequest
和 EndRequest
事件。
所有的“原始”数据都存在于 HttpRequest
和 HttpResponse
之间,只是它们不是以单个原始格式存在。以下是构建类似 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
作为流的包装器:
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);
}
}