我正在尝试使用文件创建一个缓存系统。我考虑使用 mod rewrite 来提供缓存文件(如果存在)或 php 文件(将创建 html 静态缓存),如果不存在的话。
这是我想出的第一个样本
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ /cache/home.html [L,NC]
RewriteCond %{REQUEST_URI} /cache/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^cache/home.html /index.php [L]
RewriteRule ^page/([0-9]*) /cache/page_$1.html [L,NC]
RewriteCond %{REQUEST_URI} /cache/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^cache/page_([0-9]*).html /page.php?&id=$1 [L]
</IfModule>
这对于内部页面来说是正确的。如果我调用http://www.example.site/page/1或者http://www.example.site/page/2它可以根据文件是否存在正确地提供缓存文件或 php 页面。
问题是它不适用于主网站http://www.example.site
如果我为主页添加重定向标志,它实际上可以正常工作
RewriteRule ^$ /cache/home.html [L,NC,R]
但显然,在这种情况下,如果我打电话给主站点,我得到的是 http://www.example.site/cache/home.html这不是我想要的。
以下是可能存在问题的几行日志:
[Wed Aug 05 11:59:11.751277 2015] [rewrite:trace1] [pid 30670] mod_rewrite.c(468): [client 10.1.1.1:53595] 10.1.1.1 - - [m.site.com/sid#7f7850ecb038][rid#7f7850e480a0/initial] [perdir /home/www/site.com/public/mobile/] internal redirect with /cache/home.html [INTERNAL REDIRECT]
[Wed Aug 05 11:59:11.751339 2015] [rewrite:trace3] [pid 30670] mod_rewrite.c(468): [client 10.1.1.1:53595] 10.1.1.1 - - [m.site.com/sid#7f7850ecb038][rid#7f7850e420a0/subreq] [perdir /home/www/site.com/public/mobile/] strip per-dir prefix: /home/www/site.com/public/mobile/index.html -> index.html
手持 R 旗时
[Wed Aug 05 12:04:34.333591 2015] [rewrite:trace1] [pid 31746] mod_rewrite.c(468): [client 10.1.1.1:53613] 10.1.1.1 - - [m.site.com/sid#7f7850ec1038][rid#7f7850e440a0/initial] [perdir /home/www/site.com/public/mobile/] redirect to http://m.cmstest.site.com/cache/home.html [REDIRECT/302]
[Wed Aug 05 12:04:34.343609 2015] [rewrite:trace3] [pid 31746] mod_rewrite.c(468): [client 10.1.1.1:53613] 10.1.1.1 - - [m.site.com/sid#7f7850ec1038][rid#7f7850e420a0/initial] [perdir /home/www/site.com/public/mobile/] strip per-dir prefix: /home/www/site.com/public/mobile/cache/home.html -> cache/home.html
似乎第一个没有 R 标志,在对 cache/home.html 执行正确的内部重定向后,它会去寻找 index.html(实际上并不存在)
答案1
你的第一条规则是:
RewriteRule ^$ /cache/home.html [L,NC]
该L
标志告诉 mod_rewrite 在此点停止处理,这就是您要问的问题。'R' 解决方法意味着新规则在第二个请求时按预期重写,但L
在第一个请求时阻止它。此外,该NC
标志在这里是多余的,因为没有路径字符会受到区分大小写的影响。
虽然这不是您问题的一部分,但也请重新考虑以下内容。
RewriteRule ^cache/home.html /index.php [L]
您可能希望与 匹配^cache/page.html$
,以便它不接受cache/home.htmlxyz
,实际影响可能很小。另外还有一条规则:
RewriteRule ^page/([0-9]*) /cache/page_$1.html [L,NC]
与之前一样,这些标志可能不合适。NC
标志实际上在这里起到了一定作用,但我认为这是不可取的。另外,请考虑正则表达式中的数字序列长度可以为零,我怀疑这是不可取的,所以也许你想要([0-9]+)
?你可能还想用“$”终止它,因为目前你将匹配例如/page/foobar
,并且你也不想匹配/page/123foobar
。所以你会有:
RewriteRule ^page/([0-9]+)$ /cache/page_$1.html
编辑:
请参阅下面的评论,了解匹配^$
可能不适合您的原因。此外,如果修复该问题不起作用,请尝试添加mod_rewrite:trace3
你的LogLevel
指令,并找出到底哪里出错了。输出内容很冗长,但你会学到很多东西,如果你仍然感到困惑,你可以向我们提供更多详细信息。
答案2
问题似乎出在子请求上,就像在这个答案中一样:https://stackoverflow.com/questions/9618865/mod-rewrite-mysterious-subreq
从日志中可以看出,在第一次正确的内部重定向之后,第二次调用是尝试在根目录中查找 index.html 的子请求。
我尝试添加-MultiViews
我链接的答案中的选项,但仍然不起作用。Apache 仍在查看网站根目录中的子请求。
所以我最终得到了一个小的“黑客”解决方案,它将检查请求是否是子请求,在这种情况下,如果它在根目录中寻找文件,index.*
它将重定向到/cache/home.html
RewriteCond %{IS_SUBREQ} t
RewriteCond %{REQUEST_URI} ^(/index.\w+|/)?$
RewriteRule ^ /cache/home.html [L]
从某种意义上说,这最终完成了我想要做的事情,效果很好。
我会再讨论这个问题一段时间,因为这仍然感觉像是一个“黑客”解决方案。不知道是否有更好的解决方案可以直接阻止这些子请求。