我正在使用ManagedFusion重写器作为反向代理。配置非常简单:
RewriteRule ^/api/(.*) http://www.example.com/api/$1 [P]
这对任何网址都有效。但是,如果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,甚至没有在代理网址上发出请求: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]
知道我哪里错了吗?
答案 0 :(得分: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
的提升。
因此,我将重写器项目从.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
以匹配正则表达式不区分大小写