Apache: Rewrite Index to Root


Hi everyone! Am trying to get my head back into my codebase after 2-3 years off, and it hurts!!

Can someone help me understand what this code found in my .htaccess file does…

RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /$1  [R=301,L]



It matches /index.php


And Rewrites to


Rewrite Tester

Edited to fix mistake.


My guess is that there is more to your htaccess file. Right?

Quite often rewrites are set up to remove the extension, the “.php” part of the filename.
It adds a slash at the end normally so that the URL looks more like a folder name instead of a filename.
The first line is the conditional check to look for the index.php name. The second does a rewrite.
And, then it returns a “301” which tells the user that it is a code that says that the page was moved to another one. The comments on a 301 rewrite is explained like this:

The HTTP response status code 301 Moved Permanently is used for permanent URL redirection, meaning current links or records using the URL that the response is received for should be updated. The new URL should be provided in the Location field included with the response.

Some robots like Google’s will use the 301 to record the change in location.in their records. If you move your site temporarily such as moving it to another server, you would use #302. There are many others.


Somehow we got two threads going about rewrites. Check the other thread as there is a lot of info I posted on that one about how this all works.


Sorry, but that is incorrect!!

After doing lots of reading on my own, I would say this…

In the first line…

RewriteCond %{THE_REQUEST} ^.*/index\.php

The TestString is %{THE_REQUEST} which provides the full HTTP request line sent by the browser (e.g. “GET /music/index.php HTTP/1.1”)

And the Condition is any character combination from 0 to many preceding “/index.php”. In my example, that would be “/music”.

(Originally, I was thinking that {THE_REQUEST} was the whole URL like: http://www.acme.com/music/index.php but it is not. Instead, it is whatever comes after the hostname, for example, “/music/index.php”)

In the second line…

RewriteRule ^(.*)index.php$ /$1  [R=301,L]

The Pattern is any character combination from 0 to many preceding “index.php”. In my example, that would be “/music”.

The Substitution is a slash / followed by whatever is found in the first grouping. In this case, that is (.*) which equates to “/music” in my example.

So the RewriteRule yields “/music”.

And so the original URL of:


Would be changed to by the mod_rewrite to:


So in summary, the mod_rewrite is simply chopping off the “/index.php” portion…

To be honest, this mod_rewrite should be tweaked a little, because I would never have an intermediary folder structure (e.g. “/music”) between the host name (“www.acme.com”) and any “index.php” file, but I guess that makes my current code more scalable!


You are right except the rewrite adds back a slash. I made a typo in the post (fixed), but the link to the online tester was and is correct. Your example does the same exact thing as I showed in the online tester, chops off the /index.php as you called it and replaces it with a slash.

You made slight mistake here

So in summary, the mod_rewrite is simply chopping off the “/index.php” portion…

Would be changed to by the mod_rewrite to:


It would actually rewrite to:


What that is actually doing is known as “Pretty Urls”. Nothing to do with being scalable.

Looks like you learned some things about mod_rewrite. Good going! :+1:



I am still a little stuck on the details… :persevere:

If the sample address is: http://www.acme.com/music/index.php

From a URL standpoint, it appears that %{THE_REQUEST} and %{REQUEST_URI} would be: /music/index.php


(Notice that the leading slash is included!!)

And the hostname would be: www.acme.com, without a trailing slash, right?

[quote=“SaranacLake, post:28, topic:27919, full:true”]
In the second line…

RewriteRule ^(.*)index.php$ /$1  [R=301,L]

The 1st Grouping would be 0 to many characters preceeding “index.php”.

And the Pattern would be 0 to many characters preceeding “index.php” and including “index.php”, so for example /music/index.php, right?

===> HOWEVER, it appears that leading “/” in NOT included in the Pattern.

Why do I say this?

Because the hostname is NOT supposed to include a trailing slash (i.e. “www.acme.com”).

And because in the RewriteRule we have a leadaing slash and then reference to the 1st Grouping /$1 which means that we are adding a slash ("/") before the Pattern, right?

So why does the leading slash appear in %{THE_REQUEST} and %{REQUEST_URI}, but NOT in the Pattern in the RewriteRule??

Inconsistencies like this drive me crazy!!!


The manual says:


The full HTTP request line sent by the browser to the server (e.g., “GET /index.html HTTP/1.1”). This does not include any additional headers sent by the browser. This value has not been unescaped (decoded), unlike most other variables below.


The resource requested in the HTTP request line. (In the example above, this would be “/index.html”.)

But, for the filename, you can use %{REQUEST_FILENAME}, although I am not sure if that helps…
Using the request, you have to decode it all to see if it is a post, get, etc… Using the url you get what
is after the server name. Using filename, you get the file itself. The url gives you the request minus
the query-string.

Also, there is a way to review what is happening in htaccess during the rewrites. You do it something like this:

RewriteLog "/some-log-folder/rewrite_logfile.log" 
RewriteLogLevel 3

I think that shows three levels, so $1, $2, $3 and you can add more if your folders go deep. This might help you to debug your rewrites.


@ErnieAlex , no that doesn’t really help.

What did help was going to the very nifty link that @benanamen posted, and changing the RewriteRule like this…


RewriteCond %{REQUEST_URI} ^.*/index\.php
RewriteRule ^(.*)index.php$ $1  [R=301,L]

Then I STILL get this…


That is consistent with the points I made above, and to me is says that the slash in the Substitution (i.e. /$1) is redundant…

(Apparently Apache just ignores the duplicate slash and produces the correct results of: “http://www.acme.com/music/”)

What do you think, Benanamen?


I’m not sure what the problem here is. It is working as it should to rewrite to a pretty URL.


Where did I say it isn’t working?

I asked a question trying to understand how things work…

I also pointed out that I think there is an extraneous slash in the RewriteRule…