0

我使用 ManagedFusion Rewriter 作为反向代理。配置相当简单:

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

这几乎适用于任何 URL。但是,如果 URL 碰巧没有以斜杠结尾,它将失败。

像这样的请求会很顺利: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'

但是,这样的请求将返回 404,甚至不会在代理 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)

这是我的整个配置文件:

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

知道我哪里错了吗?

4

1 回答 1

0

编辑:我的解决方法已被接受为重写器代码库中的解决方案,因此我将把它作为接受的答案。请仍然提供有关可能的方法的反馈。


找到了解决方法,但我认为这不是实际的解决方案,所以我会回答我自己的问题,但不会接受它作为答案。(除非我以后改变主意。命运是一个善变的情妇。)

我下载了 ManagedFusion.Rewriter 的源代码(最新的,显然来自 GitHub,在这里:https ://github.com/managedfusion/managedfusion-rewriter/releases )并将其集成到我的代码库中。

ManagedFusion.Rewriter.RewriterModule 类包含以下两个方法:

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;
    }
}

顾名思义,第一个是 的处理程序PostResolveRequestCache,而第二个是 的处理程序PostMapRequestHandler

在我的两个示例请求中,PostResolveRequestCache处理程序都被调用并且工作正常。但是,对于我失败的请求,PostMapRequestHandler没有被执行。

这让我想到,也许出于某种原因,通过使用将看起来不像目录的特定资源重写为看起来像文件的资源会RewritePath阻止实际的实际处理程序被拾取,从而防止引发PostMapRequestHandler.

因此,我将 Rewriter 项目从 .NET 3.5 升级到 4.5 并替换了这些行:

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

通过这些

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

有了这个,处理程序正确地接收了所有请求并开始工作。


作为旁注,我在原始规则中有一些错误,而不是

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

它应该是:

RewriteRule ^/api/(.*) http://www.example.com/api/$1 [QSA,P,NC]
  • QSA附加原始请求的查询字符串
  • NC匹配正则表达式不区分大小写
于 2013-10-11T20:41:52.137 回答