如果存在,使用Apache mod_rewrite重定向到静态内容

时间:2012-03-02 19:37:42

标签: php apache mod-rewrite

背景

我正在通过创建静态缓存来优化一些高流量的页面。由于内容不经常更改,因此生成缓存并使缓存无效的机制非常简单。目前,我正在通过PHP访问缓存(基本file_exists()检查)。我想把它带到Web服务器级别来完全削减PHP。

规格

我将拥有数千个缓存页面。所以我设想的目录树是:

year -> first id of digit -> second id of digit -> id.html

我正在以这种方式将其拆分以避免在一个目录中存储数十万个文件 - 据我所知,这是一个性能损失。我熟悉mod_rewrite,但不太确定如何捕获URL的必要部分并确定文件是否存在。

以下是传入网址的示例:

/2011/37823/some_slug

一些伪代码,使用上面的URL:

RewriteCond %{REQUEST_URL} ^(\d{4})/...
RewriteCond /cache/$1/$3/$4/$2.html -f
RewriteRule - /cache/$1/$3/$4/$2.html [L]

问题

  • 如何为上述内容创建RewriteRule
  • 有没有更好的方法(使用LAMP堆栈的技术)?

2 个答案:

答案 0 :(得分:1)

由于您的正则表达式与您列出的模式(订单更改)不匹配,因此需要进行调整,但以下内容基于您的示例网址:

RewriteCond %{DOCUMENT_ROOT}/cache/$1$2$3\.html -f
RewriteRule ^(\d+)(/\d+)(/[^/]+)$ /cache/$1$2$3.html [L]

如果你想要更多的嵌套(基于ID的第一和第二位的文件夹,但忽略URL中间部分的其余部分)那么它将是:

RewriteCond %{DOCUMENT_ROOT}/cache/$1$2/$3$4\.html -f
RewriteRule ^(\d+)(/\d)(\d)\d*(/[^/]+)$ /cache/$1$2/$3$4.html [L]

首先检查RewriteRule以查看规则是否适用。 RewriteCond然后使用DOCUMENT_ROOT中的捕获来检查文件是否存在(RewriteRule是站点根目录)。如果存在,则满足条件,RewriteRule重写URL,在停止尝试重写[L]之前为缓存页面提供服务。

就更好的选项而言,这比你拥有的PHP更好,因为它不会为缓存页面启动PHP。但是,它会检查每个资源请求的模式。

答案 1 :(得分:0)

我认为这应该适合你:

RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(\d{4})\/((\d)(\d)\d+)
RewriteCond %{DOCUMENT_ROOT}/cache/%1/%3/%4/%2.html -f
RewriteRule ^.* /cache/%1/%3/%4/%2.html [L,QSA]

第一个条件匹配/(YEAR)/((digit1)(digit2)digit3-to-n)。 parantheses告诉系统将值存储在变量%1-%4中。请注意在parantheses内有parantheses的棘手部分。似乎regexp从开始/开放paranthese计算顺序,因此id周围的外(将为%2,然后digit1为%3,依此类推

第二个条件检查完整的文件路径。 DOCUMENT_ROOT为您提供本地文件系统路径。请注意我使用的是%而不是$。这是因为我使用上一个行中存储的变量,而不是当前的。

RewriteRule只会将所有内容重写为新路径。 [L]告诉apache停止寻找更多的重写,[QSA](查询字符串追加)在重写后放回查询字符串(不确定是否需要)。