I need to modify the content of certain HttpRequests (SSAS connection strings) in IIS. Basically, I need to add an element to the SOAP contained in the request.
My approach so far has been to add a Filter to the HttpRequest, and perform the change in the filter's Read method. As far as I can tell, though, Read is never being executed.
My understanding of the Request.Filter is that it gets read from when IIS processes the request, so IIS should see my modified Request.
Is what I'm trying to do actually possible using an HttpModule and is my Filter approach correct?
If so, what would cause Read to not be hit?
Here's a simplified version of my code:
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
}
}
Actually, it is possible to modify the contents of the HttpRequest POST in IIS via an HttpModule in IIS 7.0+. I had this very issue and was able to solve it. I'm posting for future reference because there aren't many posts that detail when/why it will or won't work.
Here's a checklist for troubleshooting:
Make sure your module, and any other modules are not accessing the Request object in such as way as to cause it to evaluate the inputstream PRIOR to adding your filter to the the request filter. Accessing Request.Form["param"]
for example would trigger evaluation of the inputstream. One symptom of this is that your filters Read
method is never called.
Look at the order of events in the unified IIS pipeline https://msdn.microsoft.com/en-us/library/bb470252.aspx. You will see that the PreRequestHandlerExecute
event occurs as like the 12th event raised. To have the best chance of setting a request filter and having it apply you should do so in the BeginRequest
event, it's the first event after request validation and url mapping (exposed in an HttpModule, there are others exposed in an ISAPI extension or filter). ISAPI filters and extensions do have some events which may occur prior to HttpModule events, but since
Consider that the Request.Filter is a chain of Streams, they get evaluated in succession passing the output from one to the input of the next, they may also modify the request prior to your module receiving the input. If there is some bizarre behavior, consider removing some other filters to isolate the issue or change the order that they are loaded.
Also consider the Read and Write methods of your Stream filter are called in chunks, so they can be called multiple times, with different offsets, so ensure your rewrite logic behaves properly, especially if you are replacing content resulting in different overall request or response sizes see below.
If you are performing a search/replace in your Read or Write, you need to consider your data may span multiple reads/writes. In this case you probably want to consider buffering the Request or Response stream in a MemoryStream and operate on that instead.
If you isolate and simplify the problem down to its most basic scenario you will eventually identify what is causing it to not work. The simple example here demonstrates https://msdn.microsoft.com/en-us/library/system.web.httprequest.filter.aspx however it doesn't demonstrate operating on a buffered stream.
I've put together a sample demonstrating a buffered request and response rewrite HttpModule for reference. https://github.com/snives/HttpModuleRewrite
It's possible by overriding WorkerRequest. You can get current worker request like below:
(HttpWorkerRequest)context.GetService(typeof(HttpWorkerRequest))
And you can implement derived worker request by referencing IIS7WorkerRequest.cs .net reference source.
Hard part is read all bytes from input stream and parse the data. You shuould know HTTP Multipart-form data spec.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With