【问题标题】:Using Apache mod_rewrite to redirect to static content if exists如果存在,使用 Apache mod_rewrite 重定向到静态内容
【发布时间】:2012-03-02 19:37:42
【问题描述】:

背景

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

规格

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

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

我以这种方式拆分它是为了避免在一个目录中包含成千上万个文件 - 据我所知,这会影响性能。我熟悉 mod_rewrite,但不太清楚如何捕获 URL 的必要部分并确定文件是否存在。

以下是传入 URL 的示例:

/2011/37823/some_slug

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

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

问题

  • 如何为上述创建RewriteRule?
  • 有没有更好的方法来做到这一点(使用 LAMP 堆栈的技术)?

【问题讨论】:

  • 我没用过,但依稀记得有个mod_cache。或者你已经调查过了?
  • 没有,但我会的。不幸的是,我目前处于共享托管环境中。因此,即使它确实适用,我也可能无法使用它。与此同时,我确信有一种方法可以使用 mod_rewrite。
  • 啊,在共享主机上,我怀疑这不是一个选择。

标签: php apache mod-rewrite


【解决方案1】:

这需要调整,因为您的正则表达式与您列出的模式不匹配(顺序更改),但以下内容基于您的示例 URL:

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 使用来自RewriteRule 的捕获检查文件是否存在(DOCUMENT_ROOT 是站点根目录)。如果存在,则满足条件,RewriteRule 重写 URL,在停止尝试重写 [L] 之前提供缓存页面。

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

【讨论】:

  • 对每个请求的模式检查都是正确的。我很好奇你的看法。我想如果我把它作为我最后的规则之一,我可以缓解这个问题。
  • 如果你想检查缓存,你必须在每个请求上检查一些东西。这是一个(希望非常紧凑但简单)正则表达式和文件系统检查,这并不可怕。我认为排序取决于它发生的频率。如果 90% 的请求将被缓存,则将其放在顶部附近,因为它有 [L] 以停止进一步处理。如果 1% 的内容将被缓存,则将任何其他更频繁发生的 [L] 规则放在它之前。
【解决方案2】:

我认为这应该适合你:

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)。括号告诉系统将里面的值存储到变量 %1-%4 中。请注意括号内有括号的棘手部分。似乎正则表达式从开始/打开括号开始计算顺序,所以 id 周围的外部 ( 将是 %2 然后 digit1 是 %3 等等

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

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

【讨论】:

  • 你能解释一下你的RewriteRule吗?我想学习。具体来说,为什么这与 IBBoard 的答案不同?
  • 这对我不起作用。我想这是我错过的东西。最后,另一个答案奏效了,对我来说更直观。
猜你喜欢
  • 1970-01-01
  • 2011-01-27
  • 1970-01-01
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 2020-01-22
相关资源
最近更新 更多