سؤال

I'm using ManagedFusion Rewriter as a reverse proxy. The configuration is fairly simple:

RewriteRule ^/api/(.*) http://www.example.com/api/$1 [P]

This will work pretty much for any URL. However, if the URL happens to not end on a trailing slash, it will fail.

A request like this will go fine perfectly: GET api/report/

2013-10-10T11:27:11 [Rewrite] Input: http://localhost:50070/api/report/
2013-10-10T11:27:11 [Rule 0] Input: /api/report/
2013-10-10T11:27:11 [Rule 0] Rule Pattern Matched
2013-10-10T11:27:11 [Rule 0] Output: http://www.example.com/api/report/
2013-10-10T11:27:11 [Rewrite] Proxy: http://www.example.com/api/report/
2013-10-10T11:27:11 **********************************************************************************
2013-10-10T11:27:11 [Proxy] Request: http://www.example.com/api/report/
2013-10-10T11:27:12 [Proxy] System.Net.HttpWebResponse
2013-10-10T11:27:12 [Proxy] Received '200 OK'
2013-10-10T11:27:12 [Proxy] Response: http://localhost:50070/api/report/
2013-10-10T11:27:12 [Proxy] Response is being buffered
2013-10-10T11:27:12 [Proxy] Responding '200 OK'

However, a request like this will return a 404 without even making the request on the proxied URL: GET api/report/1

2013-10-10T11:27:13 [Rewrite] Input: http://localhost:50070/api/report/1
2013-10-10T11:27:13 [Rule 0] Input: /api/report/1
2013-10-10T11:27:13 [Rule 0] Rule Pattern Matched
2013-10-10T11:27:13 [Rule 0] Output: http://www.example.com/api/report/1
2013-10-10T11:27:13 [Rewrite] Proxy: http://www.example.com/api/report/1
(the log file finishes right here)

This is my whole configuration file:

RewriteEngine On
RewriteLog "log.txt"
RewriteLogLevel 9
RewriteRule ^/api/(.*) http://www.example.com/api/$1 [P]

Any idea where may I be wrong?

هل كانت مفيدة؟

المحلول

EDIT: My workaround has been accepted as the solution in the Rewriter codebase, so I'll make this the accepted answer. Please, still provide feedback on possible approaches to it.


Found a workaround, but I don't think this is the actual solution, so I'll answer my own question but won't accept it as an answer. (Unless I change my mind later. Fate is a fickle mistress.)

I downloaded the source code of ManagedFusion.Rewriter (the latest one, apparently from GitHub, here: https://github.com/managedfusion/managedfusion-rewriter/releases) and integrated it into my code base.

The class ManagedFusion.Rewriter.RewriterModule contains the following two methods:

private void context_PostResolveRequestCache(object sender, EventArgs e)
{
    var context = new HttpContextWrapper(((HttpApplication)sender).Context);

    // check to see if this is a proxy request
    if (context.Items.Contains(Manager.ProxyHandlerStorageName))
        context.RewritePath("~/RewriterProxy.axd");
}

private void context_PostMapRequestHandler(object sender, EventArgs e)
{
    var context = new HttpContextWrapper(((HttpApplication)sender).Context);

    // check to see if this is a proxy request
    if (context.Items.Contains(Manager.ProxyHandlerStorageName))
    {
        var proxy = context.Items[Manager.ProxyHandlerStorageName] as IHttpProxyHandler;

        context.RewritePath("~" + proxy.ResponseUrl.PathAndQuery);
        context.Handler = proxy;
    }
}

As the names imply, the first one is the handler of PostResolveRequestCache, while the second one is the handler for PostMapRequestHandler.

In both of my example requests, the PostResolveRequestCache handler was being invoked and working fine. However, for my failing request, PostMapRequestHandler was not being executed.

This made me think that maybe, for some reason, rewriting a specific resource that does not look like a directory to a resource that looks like a file through the usage of RewritePath was preventing the actual actual handler from being picked up, thus preventing the raising of PostMapRequestHandler.

As such, I upgraded the Rewriter project from .NET 3.5 to 4.5 and replaced these lines:

if (context.Items.Contains(Manager.ProxyHandlerStorageName))
    context.RewritePath("~/RewriterProxy.axd");

by these ones

if (context.Items.Contains(Manager.ProxyHandlerStorageName)) {
    var proxyHandler = context.Items[Manager.ProxyHandlerStorageName] as IHttpHandler;
    context.RemapHandler(proxyHandler);
}

With this, all the requests were being properly picked up by the handler and started working.


As a side note, I had some mistakes in the original rules, instead of

RewriteRule ^/api/(.*) http://www.example.com/api/$1 [P]

It should have been:

RewriteRule ^/api/(.*) http://www.example.com/api/$1 [QSA,P,NC]
  • QSA to append the query string of the original request
  • NC to match the regex case insensitive
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top