Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

I have a blog. The blog is stored under the /blog/ prefix on my website. It has the usual URLs for a blog, so articles have URLs in the format /blog/:year/:month/:day/:title/.

First and foremost, I want to automatically redirect visitors to the www subdomain (in case they leave that off), and internally rewrite the root URL to /blog/, so that the front page of the blog appears on the front page of the site. I have accomplished that with the following set of rewrite rules in my .htaccess file:

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/               [L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml [L]

That works fine. The problem is that the front page of the blog now appears at two distinct URLs: / and /blog/. So I'd like to redirect the /blog/ URL to the root URL. Initially I tried to accomplish this with the following set of rewrite rules:

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/               [L]
RewriteRule ^blog/?$       /                    [R,L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml [L]

But that gave me an infinite redirect (maybe because of the preceding rule?). So then I tried this set:

RewriteEngine On

# Rewrite monkey-robot.com to www.monkey-robot.com
RewriteCond %{HTTP_HOST} ^monkey-robot\.com$
RewriteRule ^(.*)$ http://www.monkey-robot.com/$1 [R=301,L]

RewriteRule ^$             /blog/                       [L]
RewriteRule ^blog/?$       http://www.monkey-robot.com/ [R,L]
RewriteRule ^feeds/blog/?$ /feeds/blog/atom.xml         [L]

But I got a 500 Internal Server Error with the following log message:

Invalid command '[R,L]', perhaps misspelled or defined by a module not included in the server configuration

What gives? I don't think [R,L] is a syntax error.

share|improve this question
    
so... you want / to go to /blog/ and /blog/ to go to / ... i'm confused. –  cpbills May 18 '10 at 18:31
    
It's not clear either if you want only the root page rewritten (/blog/ to /) or everything under too? For instance, do you want to use /blog/archives/ or just /archives/? –  Karol Piczak May 18 '10 at 18:35
    
Just /blog/ should be redirected to the root, which should look (internally, not via a redirect) in the /blog/ subdirectory for its file. (Actually, now that I think about it, maybe rewriting to /blog/index.html solves the issue...hrm.) –  mipadi May 18 '10 at 20:00
    
It still seems like a loop. And I'm still not sure I understand it right. Maybe it will be easier to talk about URLs, not files for a moment. Externally, would an article be available through www.monkey-robot.com/:year/:month/:day/:title/ or www.monkey-robot.com/blog/:year/:month/:day/:title/? –  Karol Piczak May 18 '10 at 20:06
    
Articles would be at /blog/:year/:month/:day/:title/. Only /blog/ would be redirected to the root (to avoid having two URLs with the same content). I think a loop is created, so any suggestions to avoid that are fine (although the error message seems to allude to another problem). –  mipadi May 18 '10 at 21:45

2 Answers 2

up vote 1 down vote accepted

I suspect that you might be able to avoid the infinite loop in your second ruleset by putting the rewriting directives in the main virtual host configuration, not in an .htaccess file. That's generally good practice anyway, since rewriting runs a lot faster when you put it in the virtual host, and you can get further speed benefits if you can tell Apache to ignore .htaccess files altogether.

The logic behind this is explained in the mod_rewrite technical documentation. Here's the gist: as you know, rewrite rules can change which filename a given request corresponds to, and even which directory the resulting file is in. In fact, your

RewriteRule ^$ /blog/

is a perfect example, which changes the document root to the blog directory. But Apache needs to know the directory in order to figure out which .htaccess files to check for the request. Maybe you can see the problem here: by the time Apache reaches your .htaccess file, it has already determined the name of the file it should be accessing, which means it's too late for your rewriting rules to apply.

Apache internally solves this problem by creating a new subrequest, which starts processing over from the beginning, and injecting the rules from your .htaccess file into the processing stream so they will apply to the request. As a side effect of this, all applicable rewrite rules are applied again, and this means that the [L] flag is kind of a lie when you use it in a .htaccess file. So even though you put [L] on your rule to try to force it to be the last rule applied, it really isn't; all the rules are applied again when Apache processes its internal subrequest.

If you don't have access to the main server configuration, you might be able to do this:

RewriteRule ^/blog/?$    /           [R,L,NS]

The NS flag prevents the rule from being applied to subrequests.

share|improve this answer
    
I'll give the NS thing a try. Unfortunately, I'm on a shared host so I can't change the main host configuration file. :( –  mipadi May 19 '10 at 15:54

After reading through the comments, I think the most straightforward solution is to rewrite the root page to the actual file (index.html, I suppose?).

RewriteRule ^blog/$ / [R,L]
RewriteRule ^$ /blog/index.html [L]

This way looping can be avoided. One problem remains though - the /blog/index.html is still accessible externally. If that's not an option, I think your best bet is following David's advice and moving the configuration one level up.

Some alternatives that came to my mind:

  • Leave /blog/index.html accessible and use link canonical (not the best, but easy)
  • If server scripting (PHP probably) is accessible, redirect /blog/index.php to / at script level
share|improve this answer

Your Answer

 
discard

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.