Modify Content of Page using HttpModule (as Filter)

Mar 4, 2010 at 9:57 AM

Hi,

based on this thread that the ManagedFusion proxy does not change the content of the page that is being proxied.
http://urlrewriter.codeplex.com/Thread/View.aspx?ThreadId=61268
and nberardi suggests to create a Filter and add it as HttpModule if we want to modify the content of the page being proxied.
I have followed the instruction based on this thread http://urlrewriter.codeplex.com/Thread/View.aspx?ThreadId=61026.

First, I created a small application that uses HttpModule. and it works. I'm able to get the content and modify it before sending it to the browser/client.
But, the problem is when I add a new HttpModule and register it in web.config along with ManagedFusion dll.

My HttpModule is executed but when I tried to get the content in the Filter class, it display a weird characters instead of the content of the page that i'm expected.

Please help me how to solve this. I can email the source code if required.

Thanks.

Coordinator
Mar 4, 2010 at 3:32 PM

You need to be more specific.

Mar 5, 2010 at 3:04 AM

Hi Nick,

Thanks for the reply.

I'm installing the ManagedFusion proxy on the Virtual Directory, not in the root directory. (Note: If I install this in the root it works perfectly but unfortunately this is not our requirement).
for example, I create a rule to open wikipedia web site and to access it is by typing: http://mysite/Proxy/wiki/ (Note: the "Proxy" directory is where I install the ManagedFusion).
The main page is opened perfectly but when I hover to the links inside, they're link to http://mysite/wiki/ (Notes: The "Proxy" directory is missing), I have found that it's because this component doesn't change the content of the page being proxied.
So the background is I want to create a Filter to change the content of the page but without having to change the original source code of ManagedFusion.
And I found the discussion about this, which I supply the links above.

So, I created a new DLL that contains the HttpModule class and a Filter class, like this:

HttpModule class:

    public class ResponseRewriter : IHttpModule
    {
        public void Dispose()
        {
        }

        public void Init(HttpApplication context)
        {
            context.PostReleaseRequestState += new EventHandler(context_PostReleaseRequestState);
        }

        void context_PostReleaseRequestState(object sender, EventArgs e)
        {
            HttpContext context = ((HttpApplication)sender).Context;

            if (context.Response.ContentType != null && context.Response.ContentType.IndexOf("text/html", StringComparison.InvariantCultureIgnoreCase) >= 0)
            {
                context.Response.Filter = new ResponseRewriterFilter(context.Response.Filter);
            }
        }
    }

 The Filter class:

    public class ResponseRewriterFilter : Stream
    {
		private Stream _internalStream;

	        public ResponseRewriterFilter(Stream stream)
		{
			_internalStream = stream;
		}

		public override bool CanRead
		{
			get { return _internalStream.CanRead; }
		}

		public override bool CanSeek
		{
			get { return _internalStream.CanSeek; }
		}

		public override bool CanWrite
		{
			get { return _internalStream.CanWrite; }
		}

		public override void Flush()
		{
			_internalStream.Flush();
		}

		public override void Close()
		{
			_internalStream.Close();
		}

		public override long Length
		{
			get { return _internalStream.Length; }
		}

		public override long Position
		{
			get { return _internalStream.Position; }
			set { _internalStream.Position = value; }
		}

		public override int Read(byte[] buffer, int offset, int count)
		{
			return _internalStream.Read(buffer, offset, count);
		}

		public override long Seek(long offset, SeekOrigin origin)
		{
			return _internalStream.Seek(offset, origin);
		}

		public override void SetLength(long value)
		{
			_internalStream.SetLength(value);
		}

		public override void Write(byte[] buffer, int offset, int count)
		{
            		string textBuffer = Encoding.UTF8.GetString(buffer, offset, count);
            		string strsourcesite = "\"/";
            		string strdestinationsite = "\"";

            		if (textBuffer.IndexOf(strsourcesite) > -1)
            		{
                		try
                		{
                    			textBuffer = textBuffer.Replace(strsourcesite, strdestinationsite);
                    
                    			byte[] response = Encoding.UTF8.GetBytes(textBuffer);
                    			_internalStream.Write(response, 0, response.Length);
                    
                    			return;
                		}
                		catch (HttpException) { }
            		}

           		 _internalStream.Write(buffer, offset, count);
        	}
    }

and I register the HttpModule in the web.config along with the ManagedFusion:
		<httpModules>
			<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
			<add name="RewriterModule" type="ManagedFusion.Rewriter.RewriterModule, ManagedFusion.Rewriter"/>
			<add name="ResponseRewriter" type="ReverseProxy.ResponseRewriter, ReverseProxy"/>
		</httpModules>

When I test to access http://mysite/Proxy/wiki/ and debug it, my HttpModule (ResponseRewriter) is executed but when it goes to the Write method inside ResponseRewriterFilter, the value of textBuffer is not
the content of the page being proxied, instead it display weird characters ("\b\0\0\0\0\b\0\0", something like this).
What I'm expected is the ResponseRewriter HttpModule is triggered after the ManagedFusion finish to process the page that is requested, i.e. client request a page thru proxy and the ManagedFusion process it and retrieved the content of the page.
and before sending it back to the browser/client, the ResponseRewriter httpmodule will be triggered and do changes to the content of the page and pass it to the browser/client.
Perhaps, it's not related to the product, but it would be great if you can give an idea how to solve this.

Many Thanks and Best Regards,

 

<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
<add name="RewriterModule" type="ManagedFusion.Rewriter.RewriterModule, ManagedFusion.Rewriter"/>
<add name="ResponseRewriter" type="ReverseProxy.ResponseRewriter, ReverseProxy"/>

</httpModules>

Mar 6, 2010 at 1:49 PM

Hi,

I think i'm going to try the OutRewriteRule to change the content of the page being proxied, even though it's still beta version.

Please see this thread for more detail: http://urlrewriter.codeplex.com/Thread/View.aspx?ThreadId=203630

Thanks and Best Regards.