1

I'm using the following in an .htaccess to remove the extension from .php files:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

It works great, but how can I write a conditional statement so that it only works if accessed from a given path?

I'm using pseudo code, but I'm looking for something like this:

if( path === '/my/path' || path === 'my/path/example.html' ) {
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([^\.]+)$ $1.php [NC,L]
}

The above code would only work if accessed from:

https://www.example.com/my/path

OR:

https://www.example.com/my/path/example.html
GTS Joe
  • 199
  • 2
  • 10

1 Answers1

0

You can add a condition that checks the requested URL-path.

For example:

RewriteEngine On

RewriteCond %{REQUEST_URI} ^/my/path
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]+)$ $1.php [L]

The above will only be processed if requesting a URL-path that starts /my/path, so will naturally include /my/path/foo and /my/path/bar etc.

Note that you mentioned /my/path/example.html, but the RewriteRule pattern (^([^.]+)$) already excludes any URL-path that includes a dot, so this path/file won't be included by this rule as it is currently written. This regex is integral to this rule in the way it is currently written, so you can't simply "allow dots".

The NC flag on the RewriteRule was superfluous and you don't need to backslash escape literal dots inside a character class.

To apply it to multiple paths, add multiple conditions (or use regex alternation). For example:

RewriteCond %{REQUEST_URI} ^/my/path1 [OR]
RewriteCond %{REQUEST_URI} ^/my/path2 [OR]
RewriteCond %{REQUEST_URI} ^/my/path3
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^.]+)$ $1.php [L]

You could use regex alternation instead if the paths are only short. eg. ^/(my/path1|my/path2|my/path3).


Aside:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^\.]+)$ $1.php [NC,L]

This rule appends a .php extension to the request simply based on whether the originally requested URL (without a dot) does not map to a file, regardless of whether the corresponding <url>.php file actually exists. This is "OK", but depending on how your 404 eror document is constructed, you could end up exposing <url>.php to the end user, as opposed to simply <url> (the URL they requested). This rule would also rewrite directories, which may or may not be an issue.

You could instead check that the corresponding .php file exists before rewriting, instead of checking that the requested URL does not map to a file.

For example:

RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]

The request is now only rewritten when the corresponding .php file exists.


UPDATE:

but how can I match paths exclusively? /my/path should NOT include /my/path/foo. The paths listed by RewriteCond should match those paths only.

In that case it sounds as if you just need a standard rewrite. (?) If you are just targeting specific URL-paths and not all files within a directory tree then there doesn't seem to be any need for the additional complexity of the above rule?

For example:

RewriteRule ^my/path1$ $0.php [L]
RewriteRule ^my/path2$ $0.php [L]
RewriteRule ^my/path3$ $0.php [L]

The $0 backreference simply saves repitition and contains the URL-path that is matched by the RewriteRule pattern.

MrWhite
  • 12,647
  • 4
  • 29
  • 41
  • It looks good, but how can I match paths exclusively? /my/path should NOT include /my/path/foo. The paths listed by RewriteCond should match those paths only. – GTS Joe Apr 07 '21 at 16:40
  • @GTSJoe If you only want to match specific URL-paths then it would seem to be just a regular rewrite and you don't need such a complex rule to begin with? eg. `RewriteRule ^my/path$ $0.php [L]` - this rewrites `/my/path` to `/my/path.php` - nothing else is required. (?) – MrWhite Apr 07 '21 at 17:20
  • @GTSJoe I've updated my answer. – MrWhite Apr 07 '21 at 18:20