我需要在IIS中修改某些HttpRequests(SSAS连接字符串)的内容。基本上,我需要在请求中包含的SOAP中添加一个元素。
到目前为止,我的方法是向HttpRequest添加一个Filter,并在过滤器的Read方法中执行更改。据我所知,Read永远不会被执行。
我对Request.Filter的理解是它从IIS处理请求时读取,因此IIS应该看到我修改过的请求。
我正在尝试使用HttpModule实际可行吗?我的Filter方法是否正确?
如果是这样,什么会导致Read不被命中?
以下是我的代码的简化版本:
public class CustomHttpModule : IHttpModule {
private HttpApplication app;
public string ModuleName {
get { return "CustomHttpModule"; }
}
public void Init(HttpApplication context) {
app = context;
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
void context_PreRequestHandlerExecute(object sender, EventArgs e) {
var request = app.Context.Request;
request.Filter = new CustomHttpFilter(request.Filter);
}
}
public class CustomHttpFilter : Stream {
private Stream outputStream;
public CustomHttpFilter(Stream outputFilter) {
outputStream = outputFilter;
}
public override int Read(byte[] buffer, int offset, int count) {
// read and make the necessary changes
}
}
答案 0 :(得分:2)
实际上,可以通过IIS 7.0+中的HttpModule 修改IIS中HttpRequest POST的内容。我有这个问题,并且能够解决它。我发布以供将来参考,因为没有很多帖子详细说明何时/为什么它将起作用或不起作用。
这是一个故障排除清单:
确保您的模块和任何其他模块未访问Request对象,以便在将过滤器添加到请求过滤器之前评估输入流。例如,访问Request.Form["param"]
将触发对输入流的评估。其中一个症状是您的过滤器Read
方法永远不会被调用。
查看统一IIS管道https://msdn.microsoft.com/en-us/library/bb470252.aspx中的事件顺序。您将看到PreRequestHandlerExecute
事件与第12个事件一样发生。为了最好地设置请求过滤器并将其应用,您应该在BeginRequest
事件中执行此操作,这是请求验证和URL映射后的第一个事件(在HttpModule中公开,在ISAPI中还有其他事件暴露)扩展或过滤)。 ISAPI过滤器和扩展确实有一些事件可能发生在HttpModule事件之前,但是从
考虑到Request.Filter是一个Streams链,它们会连续评估,将输出从一个传递到下一个的输入,它们也可以在模块接收输入之前修改请求。如果存在一些奇怪的行为,请考虑删除其他一些过滤器以隔离问题或更改它们的加载顺序。
还要考虑Stream过滤器的读取和写入方法是以块的形式调用的,因此可以多次调用它们,具有不同的偏移量,因此请确保您的重写逻辑正常运行,尤其是在替换内容时不同的总体请求或响应大小请参见下文。
如果您在“读取”或“写入”中执行搜索/替换,则需要考虑您的数据可能跨越多个读/写。在这种情况下,您可能需要考虑在MemoryStream中缓冲请求或响应流并改为对其进行操作。
如果您将问题隔离并简化为最基本的方案,您最终将确定导致其无法工作的原因。这里的简单示例演示了https://msdn.microsoft.com/en-us/library/system.web.httprequest.filter.aspx但是它没有演示在缓冲流上运行。
我已经整理了一个示例,演示了缓冲请求和响应重写HttpModule以供参考。 https://github.com/snives/HttpModuleRewrite
答案 1 :(得分:1)
可以通过覆盖WorkerRequest来实现。您可以获得如下的当前工作人员请求:
(HttpWorkerRequest)context.GetService(typeof(HttpWorkerRequest))
您可以通过引用IIS7WorkerRequest.cs .net参考源来实现派生的工作者请求。
硬件从输入流中读取所有字节并解析数据。您应该知道HTTP Multipart-form数据规范。
答案 2 :(得分:0)
我认为无法使用http模块修改请求,但可以修改响应。 HttpRequest
对象大部分是只读的,因此它通常在任何上下文中都是不可变的,而不仅仅是来自模块。
如果您真的很绝望,可以尝试使用反射来访问更多的http请求对象。但是,要访问,修改或调用非公开成员,您的流程需要完全信任权限 ,这在网络环境中风险很大