mod_rewrite behavior I do not fully understand.. redirect request to a subdir


I’m trying to get my head around mod_rewrite and have a problem I could not fined the answer to on the net or in the book: “The Definitive Guide to Apache mod_rewrite”.

I have a the following dir and file setup:

Site root
 - .htaccess
 - Public
   - index.php

content of the “.htaccess” file:

RewriteEngine on

RewriteRule   ^$     Public/   [L]
RewriteRule   ^(.*)$ Public/$1 [L]

root URL is: localhost/mod_rewrite_test/ (for instant.)

If I hit “localhost/mod_rewrite_test/” in the browser i get a “500 Internal Server Error” on my screen.

The error log tells me:

Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

That tells me that I have a infinity loop of some kind.
Further information indicate that “/Public” is added on top of it self, like this:


However, if I put a “.htaccess” file in the “Public” folder with the following content it works as intended:

RewriteEngine on

And the rewrite log give the following information:

(2) init rewrite engine with requested uri /mod_rewrite_test/index.php
(1) pass through /mod_rewrite_test/index.php
(3) [perdir C:/xampp/htdocs/mod_rewrite_test/] strip per-dir prefix: C:/xampp/htdocs/mod_rewrite_test/index.php -> index.php
(3) [perdir C:/xampp/htdocs/mod_rewrite_test/] applying pattern '^$' to uri 'index.php'
(3) [perdir C:/xampp/htdocs/mod_rewrite_test/] strip per-dir prefix: C:/xampp/htdocs/mod_rewrite_test/index.php -> index.php
(3) [perdir C:/xampp/htdocs/mod_rewrite_test/] applying pattern '(.*)' to uri 'index.php'
(2) [perdir C:/xampp/htdocs/mod_rewrite_test/] rewrite 'index.php' -> 'Public/index.php'
(3) [perdir C:/xampp/htdocs/mod_rewrite_test/] add per-dir prefix: Public/index.php -> C:/xampp/htdocs/mod_rewrite_test/Public/index.php
(2) [perdir C:/xampp/htdocs/mod_rewrite_test/] strip document_root prefix: C:/xampp/htdocs/mod_rewrite_test/Public/index.php -> /mod_rewrite_test/Public/index.php
(1) [perdir C:/xampp/htdocs/mod_rewrite_test/] internal redirect with /mod_rewrite_test/Public/index.php [INTERNAL REDIRECT]
(2) init rewrite engine with requested uri /mod_rewrite_test/Public/index.php
(1) pass through /mod_rewrite_test/Public/index.php
(1) [perdir C:/xampp/htdocs/mod_rewrite_test/Public/] pass through C:/xampp/htdocs/mod_rewrite_test/Public/index.php

Way do it work now? I can’t figure it out.

I use ApacheFriends XAMPP version 1.7.7 on Windows 7.

Hope anybody have the time to help me understand this, it would be very much appreciated.


You’re “loopy.” If you were the server, RewriteRule ^(.*)$ Public/$1 [L] would redirect Public/{anything} to Public/{anything} repetitively. Provide an escape clause.

[rant #1][indent]The use of “lazy regex,” specifically the :kaioken: EVERYTHING :kaioken: atom, (.*), and its close relatives, is the NUMBER ONE coding error of newbies BECAUSE it is “greedy.” Unless you provide an “exit” from your redirection, you will ALWAYS end up in a loop![/indent][/rant #1]

You might benefit from reading the mod_rewrite tutorial linked in my signature as it contains explanations and sample code. It’s helped may members and should help you, too.



Hi DK,

Thank you for your reply.

Yes, I kinda understood that I was “loopy”. :blush:

Anyway that is fixed by adding a


to the rewrite equation like this:

RewriteEngine on

RewriteRule ^$ Public/ [L]
RewriteCond %{REQUEST_URI} !Public/
RewriteRule ^(.*)$ Public/$1 [L]

I just was to noob to get my head around to add it.

Nice rant DK, but the whole greedy noob stuff was intentional as I have no intention to filter anything out at this stage, only a simple adding of a directory in to the equation. “SORRY!! DK”. :D:blush:
I can not see any benefit of doing it not the greedy way at this stage as I will handle all filtering of the URL in the script to be run.

In the sub-folder “Public” I have planed to have the following “.htaccess” file to get what I want and to do the filtering in the php script, like interpretative the input.
“index.php” is only a start controller in a MVC framework.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?url=$1 [PT,L]

But, I’m open for any suggestion or good arguments to do this another way.
But primarily I do not want to edit the “.htaccess” files to every project the MVC is to be used, but all modification is done by a config file or related files.

Very nice tutorial you have made indeed DK. I got some good input.
However not every questions in her can be answered by directing them to your tutorial…

The forum here is so people with not the same level as you on the matter can get help and some good tips and hints or solution to the problem. :wink: Even if the questions are stupid, noobe and so on. :rofl::x

Since I’m not a noob programmer I kinda understand your attitude and way of giving a reply, but some indeed noobs would feel not very welcome.:lol::blush:

Thank you very much for your kind help DK!!:wink:

Hey TT!

I guess I was a Team Leader too long (and an instructor pilot in another life before that) so not all comments were directed at you. This forum is open to all members (and visitors) so I am intentionally pedantic (in the hope that every learns - I know I have with some of the questions I’ve fielded here). In short, unless I direct a barb at you personally (which I should NEVER do), please don’t take anything I have to say personally.

RewriteEngine on

RewriteRule ^$ Public/ [L]

RewriteCond %{REQUEST_URI} !Public/
RewriteRule ^(.*)$ Public/$1 [L]

Correct! The RewriteCond provides the required escape clause.

As for getting your head around it, that’s all in the learning process - I’ll bet you don’t make that mistake again (at least without recognizing it immediately)!

The point of the Standard Rant #1 was that (.) will generally cause a looping error (that’s the first thing to look for). There’s a reason to NEVER use (.) … EXCEPT when you actually want to capture EVERYTHING (or NOTHING) and know how to avoid the inherent problems. It’s a handy tool when you need it but noobies use it only because they don’t take the time to learn what it does nor what pitfalls are inherent in using it. With what you were doing, it’s the easy way but you needed the “reminder” to provide the escape clause to avoid the loopy pitfall.

RewriteEngine On

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)$ index.php?url=$1 [PT,L]

What? You don’t expect this to loop? Of course not … so long as index.php exists in that directory. :tup:

Thanks … as noted, it’s helped many members over the years. Of course, it’s TOO LONG so I hope that visitors can use the page’s menu system to get to the point that they need help with and skip the garbage (which should be treasure to others).

Too true as that’s why I still hang around here after all the years I’ve been here.

Sorry, that’s the problem with being pedantic … it doesn’t sit well with everyone. No offense intended, I can assure you!