<IfModule mod_rewrite.c>
No need for the <IfModule>
wrapper. See this question on the Webmasters stack:
https://webmasters.stackexchange.com/questions/112600/is-checking-for-mod-write-really-necessary
#1 If the requested file is not url-mapper.php (to avoid .htaccess loop)
RewriteCond %{REQUEST_FILENAME} (?<!url-mapper\.php)$
There's no need for the negative lookbehind ((?<!
). It would be preferable to simply have a negated regex. ie. with a !
prefix. For example: !^/url-mapper\.php$
(ie. not "/url-mapper.php") And check against REQUEST_URI
(full URL-path) instead of REQUEST_FILENAME
(absolute filesystem path).
However, you state that "this file will always be at the root of the domain", but you are rewriting to /seo-urls/url-mapper.php
- which is not at the root of the domain.
So, this should strictly be written like this instead:
RewriteCond %{REQUEST_URI} !^/seo-urls/url-mapper\.php$
Unless you are confident there is only one url-mapper.php
file on your system then the regex could be reduced to !/url-mapper\.php$
.
Alternatively, check this in the RewriteRule
pattern instead (since you aren't doing anything else with the RewriteRule
pattern currently). This would be marginally more efficient.
#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.(.*) [OR]
RewriteCond %{REQUEST_URI} \.php.*$ [NC]
The first condition is too general - it catches any URL that simply contains a dot anywhere in the URL-path, not simply the file extension. There's also no need for the capturing subpattern. Assuming a file extension is between 2 and 4 characters then a pattern like !\.\w{2,4}$
would more accurately catch file extensions only.
Regex should generally be as restrictive as possible. The second condition that matches .php
extension(s) could be made more restrictive, it currently matches .php
anywhere in the URL-path. For example: \.php\d{0,4}$
- although realistically, you probably only have at most 1 digit after .php
, so \.php\d?$
would probably be better.
I'd also question whether the NC
(case-insensitive) flag is really required here. Do you really need to match .PHP
or .PhP
?
#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)(/.*)?$
Ok, but the trailing (/.*)?$
is superfluous. You are matching anything that simply starts /seo-urls/excluded1
etc. Also, no need to backslash-escape slashes (curious that you've escaped the middle slash, but not the other two).
#Then serve the URI via the mapper
RewriteRule .* /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]
Ok, although the regex .*
(that matches everything) could be simplified to ^
- which is successful for everything, but doesn't actually match anything - which is all that you require.
However, I mentioned at the top about performing the url-mapper.php
check in the RewriteRule
pattern instead. So, this would be written:
RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [L,QSA]
The RewriteRule
pattern is processed first, before any of the conditions, so it's always preferable to do what you can in the RewriteRule
directive, rather than separating it into another condition.
Summary
Bringing the above points together, we have:
RewriteEgnine On
#2 If the requested URI does not end with an extension OR if the URI ends with .php*
RewriteCond %{REQUEST_URI} !\.\w{2,4}$ [OR]
RewriteCond %{REQUEST_URI} \.php\d?$
#3 If the requested URI is not in an excluded location
RewriteCond %{REQUEST_URI} !^/seo-urls\/(excluded1|excluded2)
#Then serve the URI via the mapper
RewriteRule !^seo-urls/url-mapper\.php$ /seo-urls/url-mapper.php?uri=%{REQUEST_URI} [QSA,L]