如果请求 URI 与所需值不完全匹配,Apache .htaccess 将设置标头

如果请求 URI 与所需值不完全匹配,Apache .htaccess 将设置标头

目标:使用 /directory/ 中的 .htaccess 文件,如果请求 URI 与“/directory/”不完全匹配,则设置标头。例如,如果请求 URI 为“/directory/index.php”、“/directory/?something”或“/directory/index.php?something”,则应设置标头,但如果请求 URL 完全为“/directory/”,则不应设置标头

Apache/2.4.41,因此 IF 指令可用。

我尝试过的两种主要方法:

<If "%{REQUEST_URI} != '/directory/'">
 Header always set X-Robots-Tag "noindex"
</If>
SetEnvIf Request_URI "/directory/" isgood
Header always set X-Robots-Tag "noindex" env=!isgood

我尝试了多种变化,比如在标题上使用“early”,以及根据过去的经验尝试仅匹配“/”,即在 .htaccess 上下文中工作时可能无法“看到”完整的 URI。

所有尝试都会导致标题始终被设置或从不被设置。

(是的,mod_header 和 mod_setenvif 已启用)

我对其进行了测试,使用不同的标题同时尝试了几种不同的方法:

<If "%{REQUEST_URI} != '/'">
        Header always set X-Test1 "test1"
</If>

<If "%{REQUEST_URI} != '/files/crackypics/2005-January-alt/'">i
        Header always set X-Test2 "test2"
</If>

SetEnvIf Request_URI "/" test3
Header always set X-Test3a "test3a" env=!test3
Header always set X-Test3b "test3b" env=test3

SetEnvIf Request_URI "/files/crackypics/2005-January-alt/" test4
Header always set X-Test4a "test4a" env=!test4
Header always set X-Test4b "test4b" env=test4

无论实际请求 URI 是什么,我总是得到 test1、test2、test3b 和 test4b。

答案1

虽然我倾向于尽可能不使用 .htaccess,也不推荐它,但我发现您的案例很有趣,想测试一下。

我启动了一个测试服务器并在 documentroot 中定义一个名为 test 的目录我在测试目录中放置了一个文件(test.file),因此当我请求目录时,我将获得一个标头值,而当我请求文件时,我将获得另一个标头值,就像您正在尝试的测试一样。

我在.htaccess 中定义了它:

<If "%{REQUEST_URI} =~ m#^/test/$#">
        Header always set X-Test1 "testdir"
</If>
<Else>
        Header always set X-Test1 "testfile"
</Else>

当我测试时,它立即就工作了:

$ curl -Ik http://192.168.1.10:8090/test/file.html
HTTP/1.1 200 OK
Date: Fri, 18 Feb 2067 22:28:14 GMT
Server: Apache
X-Test1: testfile <----
Last-Modified: Mon, 17 May 2021 20:04:13 GMT
ETag: "a-5c28c18f65152"
Accept-Ranges: bytes
Content-Length: 10
Content-Type: text/html

curl -Ik http://192.168.1.10:8090/test/
HTTP/1.1 404 Not Found
Date: Fri, 25 Feb 2067 13:45:34 GMT
Server: Apache
X-Test1: testdir <---
Content-Type: text/html; charset=iso-8859-1

虽然,如果我在这个目录中启用了 DirectoryIndex,那就算你正在加载文件(默认情况下为 index.html)

curl -Ik http://192.168.1.10:8090/test/
HTTP/1.1 200 OK
Date: Tue, 22 Feb 2067 06:06:54 GMT
Server: Apache
X-Test1: testfile <---
Last-Modified: Mon, 17 May 2021 20:12:48 GMT
ETag: "9-5c28c37a406a4"
Accept-Ranges: bytes
Content-Length: 9
Content-Type: text/html

因此,如果您正在加载目录索引文件,则可能必须使用另一个条件将其从目录的第一次测试中排除。例如:

<If "%{REQUEST_URI} =~ m#^/test/$#">
        Header always set X-Test1 "testdir"
</If>
<ElseIf "%{REQUEST_URI} =~ m#^/test/index.html$#">
        Header always set X-Test1 "testdir"
</ElseIf>
<Else>
        Header always set X-Test1 "testfile"
</Else>

您将获得预期的效果:

$ curl -Ik http://192.168.1.10:8090/test/
HTTP/1.1 200 OK
Date: Fri, 11 Feb 2067 12:58:38 GMT
Server: Apache
X-Test1: testdir
Last-Modified: Mon, 17 May 2021 20:12:48 GMT
ETag: "9-5c28c37a406a4"
Accept-Ranges: bytes
Content-Length: 9
Content-Type: text/html

希望这可以帮助。

答案2

我已经非常接近我想要做的事情了。

使用 REQUEST_URI 是一个错误,因为它会被 mod_dir 隐形操纵

最好使用 THE_REQUEST 来保留原始请求并使用正则表达式来获取您真正想要的部分。

这就是我最终的选择:

Header always set X-Robots-Tag "noindex" "expr=%{THE_REQUEST} !~ m#/ HTTP#"

对于“好”的请求(我不想为其设置标头的请求),THE_REQUEST 看起来会像这样:

"GET /directory/ HTTP/2.0"

我的 RegEx 查找“/HTTP”,如果不匹配,则设置标头

如果请求以 / 以外的其他内容结尾(“/index.php”、“/?something” 等),那么它会设置标题。

相关内容