Apache Redirect to /index.php – How to handle direct requests for /index.php

d.lanza38 asked:

I’m not 100% sure if this should be on server fault or stack overflow, though I’m leaning towards server fault.

Most PHP frameworks utilize Apache redirects to funnel all request to /index.php and then the framework handles the routing from there. The issue I’m having is that our old site did not use this methodology and /index.php really was our home page. Now that we released a new site, we want to redirect all direct requests to /index.php to /home. The problem is that every other request is redirected to /index.php which would ultimately result in a double redirect to /home.

I feel like I remember there being a switch or something in Apache which only performs a redirect if the current request is not the result of another 301 redirect. I can’t seem to find anything like this though. Am I making this up? If I am, is there some way to handle this situation?

This is the bit from my Apache configuration file which performs this rewrite to /index.php:

## If I uncomment this, I get a redirection loop
## If left commented, I don't get a redirection loop, but direct requests to /index.php result in a 404 error
#RewriteRule ^/index.php$ /home [R=301,NC,L,QSA] 

#If the requested file does not exists, redirect to a custom 404 page
ErrorDocument 404 %{DOCUMENT_ROOT}/not_found
Rewritecond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule \.php$ %{DOCUMENT_ROOT}/not_found [R=302,L]

<Directory /www/www.domain.com/htdocs/public>
    DirectoryIndex index.php
    AllowOverride All
    Order allow,deny
    Allow from all

    RewriteEngine On
    # The following rule tells Apache that if the requested filename
    # exists, simply serve it.
    RewriteCond %{REQUEST_FILENAME} -s [OR]
    RewriteCond %{REQUEST_FILENAME} -l [OR]
    RewriteCond %{REQUEST_FILENAME} -d [OR] 
    #RewriteCond %{REQUEST_URI} !^/index.php$  #I tried something like this, but it doesn't seem to have any affect.
    RewriteRule ^.*$ - [NC,L]

    # The following rewrites all other queries to index.php. The
    # condition ensures that if you are using Apache aliases to do
    # mass virtual hosting, the base path will be prepended to
    # allow proper resolution of the index.php file; it will work
    # in non-aliased environments as well, providing a safe, one-size
    # fits all solution.
    RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
    RewriteRule ^(.*) - [E=BASE:%1]
    RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]

What is currently happening:

What I want to change is:

  • When a user goes to http://example.com/index.php they also end up on my homepage.
  • The problem, is that when I add the rule RewriteRule ^/index.php$
    /home [R=301,NC,L,QSA]
    an infinite loop occurs due to the rewrite
    shown above.

My answer:

Remember that the L flag indicates that no further rewrites will be performed to that request. So you can simply rewrite /index.php directly, before redirecting other URLs to it.

For example, to do an SEO-preserving 301 redirect:

RewriteRule ^/index.php /home [R=301,L]

View the full question and any other answers on Server Fault.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.