Rewrite file name to friendly name or page not found?

I know how to make this:

call up this page

That’s working fine. But is it possible ALSO to have it go to a “page not found” page when the visitor types in an actual file name like:


It’d be nice to not allow anyone to even see file names at all. But obviously if you have rules like this:

RewriteRule ^home/?$ index.php [NC,L]
RewriteRule ^index.php/?$ home [NC,L]

it doesn’t work.

Is there a way to do this?



You’re right. When you use those two rules together you’re code will end in an infinite loop of redirecting.

However, there is a trick to have your cake and eat it too!

First off you need to know that mod_rewrite works in rounds. When a request is made it will go through all the RewriteRules, see if any of them match, and if so process them. If the URL that goes in to the .htaccess was different than the URL that comes out of it, a new round will start. In Apache this second (and consecutive, if applicable) round is known as a sub-request.

The trick here is to use [NS] flag on the RewriteRule for index.php. That flag indicates that the rule must not match if the current request is a sub-request.

So, in your case:

RewriteEngine On
RewriteRule ^home/?$ index.php [NC,L]
RewriteRule ^index.php/?$ /home [NC,L[COLOR="Blue"],R=301,NS[/COLOR]]

If someone requests /home, it is rewritten to index.php and a new round will start (because of the [L] flag on that rule). In that round the first rule doesn’t match (obviously), and since it is a sub-request the second rule also doesn’t match.

Now, if someone were to request index.php the first rule wouldn’t match, but the second one would (since we’re requesting it directly it’s not a sub-request) and will redirect to /home using a 301 redirect (permanently moved).

Does that make sense?

I figured there had to be a way to do this. But I tried your code and it doesn’t work for me. I get “The page isn’t redirecting properly” when I enter either or in the address bar of my browser.

Wow, looks like I completely misunderstood [NS] :blush:

Anyway, you can still do this using %{THE_REQUEST}

RewriteEngine On

RewriteRule ^home/?$ index.php [L]

RewriteCond %{THE_REQUEST} ^(GET|HEAD|POST)\\ /index\\.php
RewriteRule ^index.php /home [L,R=301]