htaccess not rewriting URL when directory without index.php is fetched

I have written an htaccess file to rewrite URLs. What it should do: when the user visits a URL for which there is no corresponding PHP file, it redirects to route.php.

It got a bit complicated for the case of directories; if there’s no index.php in the directory navigated to, it should rewrite to route.php too.

Here’s the code:

RewriteEngine On

# Check if it's a directory without an index.php
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule . route.php [L]

# Check if it's not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . route.php [L]

The problem is, when I nagivate to “https://stackoverflow.com/” where there is no index.php, it (unwantedly) shows a directory listing (or “Forbidden” if indexes are disabled).

What is going on? How can I make it rewrite requests to a directory for which there is no index.php?

It is almost correct but there is a dot in first RewriteRule which means at least one character has to be present in URI. However for landing page relative URI will be just an empty string.

This should work for you:

RewriteEngine On

# Check if it's a directory without an index.php
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_FILENAME}/index.php !-f
RewriteRule ^ route.php [L]

# Check if it's not a file or directory
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ route.php [L]

This got an answer that should work already, but for completeness sake I want to point out an alternative.

if there’s no index.php in the directory navigated to, it should rewrite to route.php too

You don’t necessarily need to use rewriting for that, you can specify this as an alternative in your DirectoryIndex directive:

DirectoryIndex index.php /route.php

Quote from the documentation,

Several URLs may be given, in which case the server will return the first one that it finds.

So it will first look for an index.php in the current directory, and if that does not exist, for the /route.php at the root level.

Leave a Comment