2

I have a LAMP stack. I'm using the following .htaccess file to automatically map requests to .php files:

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

So if I browse to http://example.com/asdf the "asdf.php" file will be loaded.

However, if I create a .css file with the same name (i.e. "asdf.css"), then the server returns the css file instead of the PHP file when browsing to the name without extension. Also seems to happen for .txt file extensions, and probably any other three-character extension (although does NOT happen for .js files).

I can't understand why this is happening. My understanding of the rewrite ruleset is this: 1) if the file being requested doesn't exist THEN 2) if the filename does NOT contain a period, redirect the request to [filename].php

How can this ever return a .txt or .css file, especially when the matching .php file exists? What am I missing here?

Thanks!

2

If you have multiple files with the same basename, then it sounds like you may have a conflict with MultiViews. Try disabling this in your .htaccess file (or server config):

Options -MultiViews

MultiViews (part of mod_negotiation) does the same sort of thing you are trying to do with mod_rewrite and I suspect is "winning". When you request /asdf and asdf maps to a file basename then MultiViews attempts to serve an appropriate file that would match the intended mime-type (which may explain why .js files get missed).

My understanding of the rewrite ruleset is this: 1) if the file being requested doesn't exist THEN 2) if the filename does NOT contain a period, redirect the request to [filename].php

Otherwise, your understanding of the mod_rewrite directives is pretty much correct, except the order is the other way round (the RewriteRule pattern is processed first)...

  1. If the URL (the entire URL that is) does not contain a period.
  2. And the request does not map to a valid file (unlikely if all your files have file extensions - so this condition could perhaps be omitted).
  3. Internally rewrite the request by appending a .php extension.
RewriteRule ^([^\.]+)$ $1.php [NC,L]

There's no need to escape a literal period in a character class, and the NC flag is superfluous here.

  • 1
    You were absolutely correct - the "Options -MultiViews" directive cleared up the issue. Wasn't aware of Multiviews - thanks! – Ryan Griggs May 26 '17 at 19:36
  • MultiViews is not enabled in a default Apache install. However, several distros (and shared server environments) do appear to enable it for some reason. – MrWhite May 27 '17 at 0:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.