Apache .htaccess set a header if Request URI does not exactly match a desired value

Goal: using a .htaccess file in /directory/, if request URI does NOT exactly match "/directory/" then set a header. For example, the header SHOULD be set if the request URI is "/directory/index.php", "/directory/?something", or "/directory/index.php?something", but should NOT be set if the request URL is exactly "/directory/"

Apache/2.4.41 so the IF directive is available.

Main two methodologies I've attempted:

<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

I've tried a number of variations, such as using "early" on the header, as well as trying to match just "/" based on past experience that when working in an .htaccess context it might not "see" the full URI.

All attempts result in either the header ALWAYS being set or NEVER being set.

(Yes, mod_header and mod_setenvif are enabled)

I rigged this up for testing, trying a few different methods at once with different headers:

<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

Regardless of the actual request URI, I always get test1, test2, test3b, and test4b.


Although I am inclined to never use .htaccess whenever possible and I also do not recommend it, I found you case interesting and wanted to test it.

I fired up a test server and define inside a documentroot a directory called test, inside that test directory I placed a file (test.file), so when I request the directory, I will get one header value and when I request a file I will get another header value as with the test you are trying.

I defined this in .htaccess:

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

And when I tested I got it working right away:

$ 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

Although, If I have DirectoryIndex enabled in this directory, that counts as you are loading a file (index.html by default):

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

So, if you are loading a directoryindex file you will probably have to exclude it from the first test for the directory with another condition. Such as:

<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>

And you will get the desired effect:

$ 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

Hope this helps.