26 February 2010

A simple way to understand mod rewrite

The world of mod rewrite has too many people getting a fish for a day and not enough people learning to fish. Despite mod_rewrite’s quirky and weird syntax, it’s pretty easy to understand if you look at it the right way. My previous post showed how to remove www and index.html with mod rewrite. Here’s a similar script followed by the same exact logic written in pseudo-code, which should be much easier to understand:

# mod_rewrite script
RewriteCond %{REQUEST_URI} ^/media/
RewriteCond %{HTTP_HOST} ^www\.mrcoles\.com [OR]
RewriteCond %{REQUEST_URI} /index\.html$
RewriteRule (.*?)(index\.html)?$ http://mrcoles.com$1 [NE,R=301,L]

# pseudo-code of that script
if (path starts with "/media/") {
    if (host begins with "www.mrcoles.com" or path ends with "/index.html") {
        redirect to "http://mrcoles.com" + the path excluding "index.html"
    }
}

Key ideas:

  1. RewriteCond’s are if-statements
  2. A RewriteCond creates a code block that doesn’t get closed until we reach a RewriteRule with an [L] flag
  3. Multiple RewriteCond if-statement’s, in a row, wrap around each other (AND’ed together), but if you use an [OR] flag, it OR’s the next RewriteCond with the current one
  4. Since this forms one code block, you can put separate mod_rewrite scripts before or after it
  5. You have to understand regular expressions (out of the scope of this post)

Now that you have built some intuition on how a mod rewrite script gets executed, go out, cast your nets, and become fishers of urls (that are in need of rewriting). On the contrary, if you still don’t have the intuition, sorry… maybe go read up on regular expressions.

For further reading on what the variables are, what the flags do, how the regular expressions work, etc., here’s a pretty comprehensive mod rewrite cheat sheet.

Update:

I originally didn’t think to include the simplest syntax, which is a single RewriteRule—or just one if-statement. So, here’s a script and pseudo code example that removes “index.html” from urls with a 301 redirect:

# mod_rewrite script
RewriteRule (.*?/)(index\.html)$ $1 [NE,R=301,L]

# psuedo-code of that script
if (path ends with "/index.html") {
    redirect to the path without "index.html"
}

Comments (9)

1. David ap Bryan wrote:

Thanks for linking to my cheat sheet. Your certainly right that there are not many devs that known how to use mod_rewrit or reg ex.

Posted on 26 March 2010 at 2:03 PM  |  permalink

2. peter wrote:

Np, nice work making it! My favorite part is that it has examples for everything—especially the variables.

Posted on 26 March 2010 at 5:03 PM  |  permalink

3. Lars wrote:

good idea! makes it much more simple to understand, thx!

Posted on 16 April 2010 at 4:04 PM  |  permalink

4. Hannes wrote:

i like the fishing analogy ;) good post!

Posted on 18 April 2010 at 4:04 AM  |  permalink

5. peter wrote:

Thanks, hopefully this post will lead to more fishers :)

Posted on 19 April 2010 at 1:04 PM  |  permalink

6. James wrote:

Would the mod rewrite be appropriate to prevent the same page being found on two slightly different urls? My home page shows up for .com and .com/index.php

Posted on 27 July 2010 at 7:07 AM  |  permalink

7. peter wrote:

Hey James, yes—check out my prior post, which covers this exact problem: http://mrcoles.com/blog/mod-rewrite-indexhtml-and-www/

Posted on 27 July 2010 at 12:07 PM  |  permalink

8. cruncher wrote:

brilliant. thinking about mod rewrite as a collection of if statements has made it look completely obvious to me now!! I will be using this technique the next time I am reading an htaccess file for sure!!

Posted on 16 December 2010 at 6:12 PM  |  permalink

9. Claudio wrote:

Hi, Thanks! Your method is simple yet effective. Claudio.

Posted on 14 September 2011 at 5:09 AM  |  permalink

Peter Coles

Peter Coles

is a software engineer who lives in NYC, worked at Hunch/eBayNYC, and blogs here.
More about Peter »

@lethys · github · rss

It’s time to get big money out of politics. Join the kick-started campaign to put government back in the hands of the people. Pledge mayday.us now