Is it possible to modify the content of HttpRequest POST in an IIS HttpModule?
Asked Answered
L

3

8

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
    }
}
Larimore answered 17/6, 2010 at 4:54 Comment(1)
I have a similar problem. Which approach did you take? Did you use reflection to enable writes to the Request objects or did you implement a Request Filter?Exponential
H
0

I do not believe it is possible to modify the request with an http module, however it is possible to modify the response. The HttpRequest object is mostly read-only, so it is generally immutable in any context, not just from a module.

If you were really desperate, you might try using reflection to get access to more of the http request object. To access, modify, or invoke non-public members, however, your process would need full trust permissions, which is very risky in a web environment.

Haley answered 17/6, 2010 at 5:2 Comment(1)
This is not correct. It is possible in some circumstances to use an HttpModule to implement an HttpRequest.Filter to modify an inbound http payload. This post is an example of someone succeeding #3240670Inattentive
M
4

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:

  1. 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.

  2. 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

  3. 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.

  4. 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.

  5. 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

Monstrance answered 23/2, 2016 at 23:39 Comment(3)
That GitHub sample was exactly what I needed!Tu
It seems like the GitHub sample is only working when the ContentType is "x-www-form-urlencoded" and the endpoint ends with .aspx. Even if I remove the if statement in the GitHub sample that checks if it ends with .aspx it wont work for other extensions. Any idea why?Effector
@JesperLundin There's probably dozens of reasons: improper configuration, security, authentication, authorization, mappings, handlers, permissions, rewriting rules, runtime, events, etc. OTTOMH make sure IIS handler mappings are set to invoke the ASP.NET runtime for those requests. Beyond that I would direct you to study the IIS Request Pipeline Architecture learn.microsoft.com/en-us/iis/get-started/introduction-to-iis/…Monstrance
A
1

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.

Autoionization answered 9/5, 2014 at 12:23 Comment(0)
H
0

I do not believe it is possible to modify the request with an http module, however it is possible to modify the response. The HttpRequest object is mostly read-only, so it is generally immutable in any context, not just from a module.

If you were really desperate, you might try using reflection to get access to more of the http request object. To access, modify, or invoke non-public members, however, your process would need full trust permissions, which is very risky in a web environment.

Haley answered 17/6, 2010 at 5:2 Comment(1)
This is not correct. It is possible in some circumstances to use an HttpModule to implement an HttpRequest.Filter to modify an inbound http payload. This post is an example of someone succeeding #3240670Inattentive

© 2022 - 2024 — McMap. All rights reserved.