1

For removing just .php from my urls, I currently have the following

# Remove trailing slashes
RewriteRule ^(.*)\/$ $1 [NC,L,R=301] 

# Remove trailing .php extensions
RewriteCond %{THE_REQUEST} (\S*?)/(.*?)\.php [NC]
RewriteRule ^ %1/%2 [L,R=301]

# Add .php extension for final internal redirect
RewriteCond %{REQUEST_URI} ^(.*)$
RewriteRule !\.php$ %1.php [NC,L]

But these rules do not work for bare example.com as it ends up as example.com/.php. So how can I fix that?

Patrick Mevzek
  • 9,921
  • 7
  • 32
  • 43
  • _Aside:_ Presumably you removed the `.php` extension in the application itself? – MrWhite Mar 11 '18 at 10:00
  • Possible duplicate of [Redirect, Change URLs or Redirect HTTP to HTTPS in Apache - Everything You Ever Wanted to Know About Mod\_Rewrite Rules but Were Afraid to Ask](https://serverfault.com/questions/214512/redirect-change-urls-or-redirect-http-to-https-in-apache-everything-you-ever) – MadHatter Mar 11 '18 at 14:42

1 Answers1

1

You need to either:

  • Check that the destination file (with the .php extension) exists before internally rewriting to it
  • Avoid rewriting directories (for which the document root is one).
  • Avoid rewriting the document root only (as in your example).

For example, to avoid rewriting the document root only, as in your specific example, you can modify the existing RewriteCond directive:

# Add .php extension for final internal redirect
RewriteCond %{REQUEST_URI} ^(.*)$

to read:

RewriteCond %{REQUEST_URI} ^(/.+)$

/.+ matches a slash followed by something, which would exclude the document root, since the document root is naturally a slash by itself.


To avoid rewriting all directories (of which the document root is one), you can add an additional condition to avoid rewriting URLs that map to a physical directory. For example:

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

However, if you have directories that are accessible then you should modify your existing rule that removes trailing slashes, otherwise, you will likely get a redirect loop when requesting a directory (since mod_dir will append a slash by default). For example:

# Remove trailing slashes
RewriteRule ^(.*)\/$ $1 [NC,L,R=301]

Should be modified to include the same condition as above:

# Remove trailing slashes, unless the request maps to a directory
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ $1 [L,R=301]

Also, no need for the NC flag here. And there is no need to escape the slash in the RewriteRule pattern.

I assume you must also have a RewriteBase directive defined elsewhere in you file, otherwise, this will likely result in an invalid redirect in .htaccess.

MrWhite
  • 12,647
  • 4
  • 29
  • 41
  • It works as expected, but before I accept the answers I'd like to ask a few more questions if you don't mind. 1. Why the file check if the server generates a not found automatically? 2. For avoiding directories, I presume I should add a flag to the trailing slash remover? –  Mar 11 '18 at 11:24
  • 1. Yes, that is possibly unnecessary, although it does avoid a meaningless rewrite and corresponding access log entry. But, importantly, it would solve your current problem of rewriting to `/.php`, which is why I've included that here. 2. I've updated my answer. – MrWhite Mar 11 '18 at 14:45