What does %{REQUEST_FILENAME}.ext mean? Why the extra .ext ending?

The %{REQUEST_FILENAME} contains a string like this:

/web/webroot/index.php

I see a lot of people recommend testing if a file exists and has a .php extension like this:

RewriteCond %{REQUEST_FILENAME}.php -f

Isn't the .php after %{REQUEST_FILENAME} redundant? The variable should already contain the .php, right?

Seems like adding .php after %{REQUEST_FILENAME} would make the TestString check add an extra .php, like this:

/web/webroot/index.php.php

I'm missing something simple, I'm sure of it, but I just don't know what it is.

The context is this:

RewriteCond %{THE_REQUEST} ^.*?\.php [NC]
RewriteRule ^ - [R=404,NE,L]

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_FILENAME}.php [L]

Solution 1:

Isn't the .php after %{REQUEST_FILENAME} redundant? The variable should already contain the .php, right?

Well, yes and no, it depends what you are trying to do.

RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^ %{REQUEST_FILENAME}.php [L]

This rule allows you to request extensionless URLs. eg. /index or /foo and this internally rewrites the request to /index.php and /foo.php respectively.

In this instance, REQUEST_FILENAME is a string of the form /web/webroot/index. So, it's testing that /web/webroot/index.php exists before rewriting to the same. If you were to request /index.php then the condition fails and no rewrite occurs (which is correct).

However, this rule isn't strictly correct and could cause a rewrite-loop under certain conditions. See the following related question:

  • Using Apache rewrite rules in .htaccess to remove .html causing a 500 error