不带 R 标志的 root 的 RewriteRule 不起作用

不带 R 标志的 root 的 RewriteRule 不起作用

我正在尝试使用文件创建一个缓存系统。我考虑使用 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]

从某种意义上说,这最终完成了我想要做的事情,效果很好。

我会再讨论这个问题一段时间,因为这仍然感觉像是一个“黑客”解决方案。不知道是否有更好的解决方案可以直接阻止这些子请求。

相关内容