Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Sure I'm just missing something obvious here, but I have this:

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ $1_$2 [N]
RewriteRule ^(.*)$ $1.php [QSA,L]

Which I would like to rewrite /shop/basket to /shop_basket.php. Instead if I go to / I get and internal server error, and if I go to /shop/basket it gets stuck in an infinite loop.

Any ideas?

share|improve this question
up vote 3 down vote accepted

Take IV: No, Really, This Is It!

It turned out be easier than I thought to get rid of [DPI]. The final set:

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ $1_$2 [L]

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ $1.php

Now is this acceptable? :-)

Take III: The (Not-So) Final Solution

Ok, after much testing and banging-head-on keyboard, I finally came up with something satisfactory. I'm definitely keeping this one in case I ever switch back to Apache for some reason.

The lightbulb went off in my head when I broke the problem up into two parts: replace / with _; then, add .php at the very end. Here's what I finally came up with:

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteRule ^(.*)/(.*)$ $1_$2 [DPI,N]

RewriteCond %{SCRIPT_FILENAME} !-f
RewriteCond %{SCRIPT_FILENAME} !-d
RewriteCond %{REQUEST_URI} !\.php$
RewriteRule ^(.*)$ $1.php [QSA]

Now, as I mentioned above, the biggest thing was to split the two operations up. Once I did that, everything became much easier. The two RewriteConds are really neat, because they allow you to access files by their usual names, even with all of this other rewriting going on.

I noticed that I was getting infinite path redirection (which Apache couldn't detect), like shop/basket_checkout/basket_checkout/basket/checkout; that's when I realized Apache itself was appending paths to the end of the replaced path! Thus [DPI] fixes that.

The extra RewriteCond in the second block should be obvious: it prevents infinite redirection (ie if foo.php is unavailable, no point in trying foo.php.php, etc).

Let us know how this works for you.

Take II: Nice try, but no dice

Whoops, even simpler than I first thought. Change [N] to [C] and you're good to go. As the documentation for [N] says:

Be careful not to create an infinite loop!

Which is exactly what happened here. ;-)
I nearly took down my test VM on the first try -- that was fun!

It does strange things, though, when the php file doesn't actually exist. I'll test some more.

share|improve this answer
Ah, thank you! However the DPI flag was only added in Apache 2.2.12 (, and I cant get all the servers this needs to work on updated to that version. Any other possible workaround? – Jack Sleight Feb 27 '10 at 11:13
Haha! In the voice of Adam Sandler in The Wedding Singer: "…things that could've been brought to my attention yesterday!" ;-) Please update your original question with the minimum version number I can use, and any other surprises you might have for me, and I'll see what I can do! – fission Feb 27 '10 at 20:32
Well I think I got it – please let me know if the fourth iteration works… :-) – fission Feb 28 '10 at 10:40
Ha, sorry for not mentioning that, honestly didn't even occur to me. Anyway, solution IV works perfectly, thank you so much! Really appreciate your help. – Jack Sleight Feb 28 '10 at 17:45
You're most welcome! I'm glad it's working for you. – fission Feb 28 '10 at 20:31

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.