c# - 我可以使用 HTTP 模块更改传入 HTTP 请求的内容吗?

标签 c# asp.net wcf filter gzip

我正在尝试扩展我的 REST 服务(使用 WCF/webHttpBinding 构建),以便客户端可以上传压缩数据。我不确定实现此目的的最佳方法是什么,但我认为通过添加一个 HTTP 模块会相当容易,如果传入请求的内容编码设置为 gzip,该模块将解压缩数据。

所以我创建了一个派生自 IHttpModule 的类,实现如下:

  private void OnBeginRequest(object sender, EventArgs e)
  {
     var app = (HttpApplication) sender;
     var context = app.Context;

     var contentEncoding = context.Request.Headers["Content-Encoding"];

     if (contentEncoding == "gzip")
     {
        // some debug code:
        var decompressedStream = new GZipStream(context.Request.InputStream, CompressionMode.Decompress);
        var memoryStream = new MemoryStream();
        decompressedStream.CopyTo(memoryStream);
        memoryStream.Seek(0, SeekOrigin.Begin);

        var streamReader = new StreamReader(memoryStream);
        string msg = streamReader.ReadToEnd();

        context.Request.InputStream.Seek(0, SeekOrigin.Begin);

        app.Request.Filter = //new TestFilterStream(app.Request.Filter);
                    new System.IO.Compression.GZipStream(
                    app.Request.Filter, CompressionMode.Decompress);
     }

  }

我看到的问题是 GZipStream 解压缩实际上从未执行过。我已经确认传入的数据实际上是 gzip 压缩的(msg 变量包含正确的数据)。我还尝试在上面创建自己的流类 (TestFilterStream) 并将其分配给 app.Request.Filter 并且我已经确认流类中没有任何成员实际上被 ASP.NET 调用。所以看起来虽然可以指定一个过滤器,但实际上并没有使用该过滤器。

HttpApplication.Request.Filter 真的没有用吗?

最佳答案

我尝试通过两种方式设置请求过滤器:

  1. 使用 HttpModule
  2. 将其设置在 Application_BeginRequest() (Global.asax) 的开头

两者的结果相同(VS2012 web 项目 + IISExpress):

  • 如果没有输入数据(GET 请求或类似请求),则不会调用 Filter.Read
  • 如果是带有实际数据的 POST,则执行过滤器并且网络服务获取过滤后的数据
  • 即使我在设置过滤器之前从 Request.InputStream 中读取,我仍然会从我的服务代码中触发过滤器。

我没有简单的方法来测试 Gzippet 输入,所以我没有尝试实际的过滤器是否有效。但是,我知道它已被触发,因为我在 GZipStream 尝试查找输入时收到错误消息。

也许您有其他 HttpModule 或 Filter 会破坏您的输入或控制流?

This post提出了一种类似于您的方法,但也说明了以下内容,这可能会导致一些副作用(我的测试未使用 WCF):

"It appears that this approach trigger a problem in WCF, as WCF relies on the original Content-Length and not the value obtained after decompressing."

关于c# - 我可以使用 HTTP 模块更改传入 HTTP 请求的内容吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20249997/

相关文章:

c# - 为什么我的 PNG 纹理不透明?

c# - 从标记中的对象获取属性

asp.net - 重定向到发布方法/操作

C# 8.0 不可为空的引用类型和选项模式

c# - 服务无法在 WCF 中找到其他服务的端点

wcf - 生成的元数据 (WSDL) 中的 .net 4 WCF 端点指向节点而不是托管在负载平衡 (NLBS) IIS6 上的虚拟主机

c# - 并非所有路径都返回一个值。 - 可选返回?

c# - StyleCop 疯狂 : protected field

c# - 从 WCF 服务流式传输文件

ASP.NET 分析