目标:使用 /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” 等),那么它会设置标题。