1

Hi I am trying to get htaccess to rewrite only if a file, symlink, or a directory is not present with that name. Which I have successfully done with this right here:

RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*)$ index\.php?var=$1 [QSA,L]

Works perfectly, however, I only want this to occur in the root directory, not in any subdirectories. How can I accomplish this in a generic way (meaning I don't want to explicitly state the URL in the .htaccess file)?

tony
  • 133
  • 5

1 Answers1

1

To prevent any mod_rewrite directives being processed for requests outside of the document root then place the following rule at the top of the file:

# Prevent further processing if the request is outside the root directory
RewriteRule / - [L]

The above basically states that for any requested URL-path that contains a slash then stop here. (This will also catch requests that end in a slash - is that an issue?)


Alternatively, you can make the regex on the existing two rules more specific so that it only applies to requests in the root directory.

For example:

# Only apply rules to requests in the root directory
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^[^/]+$ - [L]
RewriteRule ^([^/]*)$ index.php?var=$1 [QSA,L]

The PT flag on the first rule is not required. And the capturing group in the first rule is not required either. Literal dots in the substitution string do not need to be backslash-escaped.

NB: This will also fail to process requests that end with a slash.


However, if these are your only rules that are related to this then you don't need two rules, only one is required, providing it is OK for requests to the document root itself being absent the var URL parameter. For example:

DirectoryIndex index.php

RewriteCond %{REQUEST_FILENAME} !-s
RewriteCond %{REQUEST_FILENAME} !-l
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ index.php?var=$1 [QSA,L]

Note that the logic of the conditions is reversed.

As mentioned, requests for the root directory itself will just drop through to index.php (by mod_dir), not index.php?var=.

MrWhite
  • 12,647
  • 4
  • 29
  • 41
  • Great answer, thank you for the detailed response. Follow up question: what if I wanted to also process requests that do end in a slash, as long as that directory doesn't exist. is that possible? – tony Mar 24 '22 at 21:32