我在基于子域的我的(Rails)应用程序中缓存页面。某些操作的页面缓存到/ public / cache /(subdomain)/。该应用程序在Apache下使用Phusion Passenger运行。缓存工作正常。问题是Apache没有拿起缓存的页面并绕过它应该的Rails。我的重写规则是错误的,我需要帮助修复它们。
作为众多例子之一,我使用了位于https://github.com/yeah/page_cache_fu#readme的建议,如下所示:
RewriteMap uri_escape int:escape
<Directory /var/www/example.com/current/public>
RewriteEngine On
RewriteCond %{REQUEST_METHOD} GET [NC]
RewriteCond %{DOCUMENT_ROOT}/cache/%{HTTP_HOST}%{REQUEST_URI}%{QUERY_STRING}.html -f
RewriteRule ^([^.]+)$ cache/%{HTTP_HOST}/$1${uri_escape:%{QUERY_STRING}}.html [L]
RewriteCond %{REQUEST_METHOD} GET [NC]
RewriteCond %{DOCUMENT_ROOT}/cache/%{HTTP_HOST}/index.html -f
RewriteRule ^$ cache/%{HTTP_HOST}/index.html
这个问题似乎是期望该目录成为完整的http主机(即它正在查看cache / subdomain.example.com而不仅仅是缓存/子域)。
编辑:即使我将Rails应用程序更改为缓存到cache / subdomain.example.com,Apache仍然不会使用它们,因此似乎存在更多错误,而不仅仅是子域方面。
有人可以帮我提出正确的规则吗?
编辑(2):
我已将我的重写简化为以下内容(只是为了尝试进入工作起点):
RewriteEngine On
RewriteCond %{HTTP_HOST} ^([^.]+)\.example\.com$ [NC]
RewriteCond ^stats$ cache/%1/stats.html [L]
我认为这会导致http://abc.example.com/stats被重写为http://abc.example.com/cache/abc/stats.html
不是。我还添加了一个RewriteLog条目,我在那里看到的东西让我觉得它正试图重定向到http://abc.example.com/var/www/example.com/current/public/cache/abc/stats.html。如果我在浏览器http://abc.example.com/var/www/....etc中添加'L'选项和'L',我们会进一步证实这一点。即它似乎是附加完整的文档根而不仅仅是面向公众的部分。
当然上面的结果是我得到了404错误返回给浏览器。
你能看出我的规则还有什么问题吗?
编辑:这实际上是一个错误。
http://code.google.com/p/phusion-passenger/issues/detail?id=563
答案 0 :(得分:1)
好吧,这个看起来像它应该有效,但事实并非如此。我用这个做了很多测试,看起来问题是RewriteRule中的^([^.]+)$
。现在,我对谷歌做了这个,看起来这是一个很常见的模式,所以我不明白这个问题是什么。我只知道当我在RewriteRule中使用那个模式时,规则就失败了。如果我将其更改为^([^.]+)
,它似乎可以正常工作。
希望对mod_rewrite有更多经验的人可以到我们解释该模式可能存在的问题。
编辑:我刚刚意识到问题^([^.]+)$
:
由于您正在构建缓存,因此“普通”文件将存在于其通常的位置。这意味着如果您向服务器询问/file
,那么根据您的配置,它会说“嘿,file
不存在,所以让我们尝试{{1的默认扩展名}}!”然后它就会发现.html
。现在,当您进入RewriteRule时,file.html
正则表达式将与^([^.]+)$
NOT file.html
匹配。
file
表示“字符串的开头,后跟尽可能多的非句点字符,然后是字符串的结尾”,这对^([^.]+)$
有效,因为它包含没有时期。它对file
失败,因为file.html
将匹配^[^.]+
,但正则表达式希望找到字符串的结尾(即file
),而是找到$
1}}并失败。
.html
的作用原因是保证只有^(.*)$
将是整个字符串,因为.*
匹配“任意字符的数量”,所以没有字符可能存在于正则表达式的.*
和(.*)
部分之间。 $
并非如此。
为了提取子域,您需要反向引用RewriteCond。基本上,如果你在RewriteCond中捕获一个引用(即在parens中封装一些东西),那些引用可以直接跟在它之后的RewriteRule中。
例如,如果我写了这个:
[^.]+
然后括号将捕获子域 - 请注意 RewriteCond %{HTTP_HOST} ^([^.]+)\.example.com
周围的()
如果我在下一行写一个RewriteRule,上面捕获的文本将可以[^.]+
访问。
所以你的RewriteRule看起来像这样:
%1
希望有所帮助。