I have an ISAPI filter for IIS 6 which does some custom processing using the bytes-sent field of the response. I'd like to update that for IIS 7, but I'm running into a problem. None of the IIS 7 events seem to have access to the content-length, bytes sent, or any data which would let me calculate the content-length or bytes sent. (I know the content-length header and bytes sent are not the same, but either will work for this purpose.)
我有一个IIS 6的ISAPI过滤器,它使用响应的字节发送字段进行一些自定义处理。我想为IIS 7更新它,但我遇到了一个问题。 IIS 7事件似乎都没有访问内容长度,发送的字节数或任何可以让我计算发送的内容长度或字节数的数据。 (我知道内容长度标头和发送的字节不一样,但两者都可以用于此目的。)
From what I can tell, the content-length header is added by HTTP.SYS after the managed modules have finished executing. Right now I have an event handler which runs on EndRequest. If I could get at the output stream I could calculate what I need myself but the managed pipeline doesn't seem to have access to that either.
据我所知,在托管模块完成执行后,HTTP.SYS会添加内容长度标头。现在我有一个在EndRequest上运行的事件处理程序。如果我可以得到输出流,我可以计算出我自己需要的东西,但托管管道似乎也无法访问。
Is there some way of getting the content-length or bytes sent in the managed pipeline? Failing that, is there some way I can calculate content-length or bytes sent from objects available in the managed pipeline?
是否有某种方法可以获取托管管道中发送的内容长度或字节数?如果失败了,我是否可以通过某种方式计算托管管道中可用对象发送的内容长度或字节数?
1 个解决方案
#1
To get at the bytes sent you can use the HttpResponse.Filter
property. As the MSDN docs say this property gets or sets a wrapping filter object that is used to modify the HTTP entity body before transmission.
要获取发送的字节,您可以使用HttpResponse.Filter属性。正如MSDN文档所说,此属性获取或设置一个包装过滤器对象,用于在传输之前修改HTTP实体主体。
You can create a new System.IO.Stream
that wraps the existing HttpResponse.Filter
stream and counts the bytes passed in to the Write
method before passing them on. For example:
您可以创建一个新的System.IO.Stream,它包装现有的HttpResponse.Filter流,并在传递它们之前计算传入Write方法的字节数。例如:
public class ContentLengthModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OnBeginRequest;
context.EndRequest += OnEndRequest;
}
void OnBeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication) sender;
application.Response.Filter = new ContentLengthFilter(application.Response.Filter);
}
void OnEndRequest(object sender, EventArgs e)
{
var application = (HttpApplication) sender;
var contentLengthFilter = (ContentLengthFilter) application.Response.Filter;
var contentLength = contentLengthFilter.BytesWritten;
}
public void Dispose()
{
}
}
public class ContentLengthFilter : Stream
{
private readonly Stream _responseFilter;
public int BytesWritten { get; set; }
public ContentLengthFilter(Stream responseFilter)
{
_responseFilter = responseFilter;
}
public override void Flush()
{
_responseFilter.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return _responseFilter.Seek(offset, origin);
}
public override void SetLength(long value)
{
_responseFilter.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
return _responseFilter.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
BytesWritten += count;
_responseFilter.Write(buffer, offset, count);
}
public override bool CanRead
{
get { return _responseFilter.CanRead; }
}
public override bool CanSeek
{
get { return _responseFilter.CanSeek; }
}
public override bool CanWrite
{
get { return _responseFilter.CanWrite; }
}
public override long Length
{
get { return _responseFilter.Length; }
}
public override long Position
{
get { return _responseFilter.Position; }
set { _responseFilter.Position = value; }
}
}
#1
To get at the bytes sent you can use the HttpResponse.Filter
property. As the MSDN docs say this property gets or sets a wrapping filter object that is used to modify the HTTP entity body before transmission.
要获取发送的字节,您可以使用HttpResponse.Filter属性。正如MSDN文档所说,此属性获取或设置一个包装过滤器对象,用于在传输之前修改HTTP实体主体。
You can create a new System.IO.Stream
that wraps the existing HttpResponse.Filter
stream and counts the bytes passed in to the Write
method before passing them on. For example:
您可以创建一个新的System.IO.Stream,它包装现有的HttpResponse.Filter流,并在传递它们之前计算传入Write方法的字节数。例如:
public class ContentLengthModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += OnBeginRequest;
context.EndRequest += OnEndRequest;
}
void OnBeginRequest(object sender, EventArgs e)
{
var application = (HttpApplication) sender;
application.Response.Filter = new ContentLengthFilter(application.Response.Filter);
}
void OnEndRequest(object sender, EventArgs e)
{
var application = (HttpApplication) sender;
var contentLengthFilter = (ContentLengthFilter) application.Response.Filter;
var contentLength = contentLengthFilter.BytesWritten;
}
public void Dispose()
{
}
}
public class ContentLengthFilter : Stream
{
private readonly Stream _responseFilter;
public int BytesWritten { get; set; }
public ContentLengthFilter(Stream responseFilter)
{
_responseFilter = responseFilter;
}
public override void Flush()
{
_responseFilter.Flush();
}
public override long Seek(long offset, SeekOrigin origin)
{
return _responseFilter.Seek(offset, origin);
}
public override void SetLength(long value)
{
_responseFilter.SetLength(value);
}
public override int Read(byte[] buffer, int offset, int count)
{
return _responseFilter.Read(buffer, offset, count);
}
public override void Write(byte[] buffer, int offset, int count)
{
BytesWritten += count;
_responseFilter.Write(buffer, offset, count);
}
public override bool CanRead
{
get { return _responseFilter.CanRead; }
}
public override bool CanSeek
{
get { return _responseFilter.CanSeek; }
}
public override bool CanWrite
{
get { return _responseFilter.CanWrite; }
}
public override long Length
{
get { return _responseFilter.Length; }
}
public override long Position
{
get { return _responseFilter.Position; }
set { _responseFilter.Position = value; }
}
}