2

我想让我网站上的所有 URL 都由一个脚本处理。所以我输入了这样的重写规则:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /myscript.php?p=$1 [L]

但我不想允许在其中实际包含“myscript.php”的 URL 上访问我的脚本,所以我想将它们重定向回主站点:

Redirect 301 /myscript.php http://example.com/

问题是,如果我将这两个规则都放入我的 .htaccess 文件中,则会导致无限循环。如何让它们同时工作?

我还希望能够重定向以下内容:

/myscript.php?p=foo -> /foo
4

2 回答 2

4

你可以设置一个环境变量

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !myscript\.php
RewriteRule (.*) /myscript.php?p=$1 [L,E=LOOP:1]

并在您的第二条规则中进行测试

RewriteCond %{ENV:REDIRECT_LOOP} !1
RewriteRule ^myscript\.php$ / [R,L]

永远不要在启用的情况下进行测试,有关详细信息301,请参阅此答案提示调试 .htaccess 重写规则

于 2013-03-11T14:27:37.613 回答
1

使用环境变量是完全可以的,但是,您不需要自己手动设置此环境变量。Apache 提供了可用于此目的的REDIRECT_STATUS 环境变量。

REDIRECT_STATUS在初始请求中为空(或未设置)。它设置为200在第一次(成功)内部重写时。或者出现错误时的其他一些 HTTP 状态代码(404等)。

因此,我们可以简单地检查 that is empty 而不是检查 that REDIRECT_LOOPis not ,以确保我们正在测试初始请求而不是重写请求。例如:1REDIRECT_STATUS

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^myscript\.php$ / [R,L]

(请注意,它只是REDIRECT_STATUS,请求开始时没有STATUS变量。)


RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !myscript\.php
RewriteRule (.*) /test/myscript.php?p=$1 [L,E=LOOP:1]

旁白:RewriteCond检查的指令REQUEST_URI在这里并没有真正做任何事情。如果第一个条件为真(即它不是文件),那么这个条件也必须为真。但是,可以通过首先包含此条件来优化它。这将避免对每个请求(包括重写的请求)进行文件检查。例如:

RewriteCond %{REQUEST_URI} !^/test/myscript\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /test/myscript.php?p=$1 [L]

或者,您可以在此规则之前包含一个预检查(异常),而不是在myscript.php请求时停止处理:

RewriteRule ^test/myscript\.php$ - [L]

但是,如果您这样做,那么上述规范重定向必须出现这些规则之前,否则它们将永远不会被处理。(无论如何,通常最好将规范重定向放在首位。)

于 2017-06-12T21:59:50.110 回答