缓存页面的Mod重写规则

时间:2010-12-15 00:21:59

标签: mod-rewrite subdomain

我在基于子域的我的(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

1 个答案:

答案 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

希望有所帮助。