Getting Started: Apache mod_rewrite Methods

Apache’s mod_rewrite module appears to be the one area of Apache administration that generates the most questions. I seem to be a perpetual beginner when it comes to url rewriting, and I continue to dream up impossible wishes on a regular basis.

I also bother my own peers for their best rewrite hacks to build up my arsenal. However, having seen numerous queries on this powerful module, I thought sharing some of my own favorite (and basic) rewriting usage would contribute to those seeking answers.

In addition, I am sure we have some hidden rewriting ninjas hanging around the SitePoint community that will add in some missing magic we all could leverage.

As a final aside – my knowledge of rewriting has come almost exclusively from reading and re-reading (and re-reading!) the Apache HTTP docs and some serious Googling on the topic over the years. Regular expressions can be both your friend and your enemy! ;>)

These are generally added into either your httpd.conf file or into an .htaccess file. For some excellent advice on htaccess if you are using that route – see this.

Re-directing a sub-domain to a domain:


RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*).mydomain.com$
RewriteCond %{HTTP_HOST} !^www.mydomain.com$
RewriteRule (.*) http://mydomain.com/%1$1 [P]

Or if you want to force www.mydomain.com — even if visitors use mydomain.com to get to your site:


RewriteEngine On
RewriteCond %{HTTP_HOST} !^www.mydomain.com$ [NC]
RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R,L]

Perhaps you have a directory you need to point visitors toward within the DocumentRoot that contains your entry pages (like a beta test site):


RewriteEngine On
RewriteCond %{HTTP_HOST} ^www.betadomain.com$
RewriteCond %{REQUEST_URI} !^/beta/
RewriteRule ^(.*)$ /beta/$1

Re-directing users (and search engines) permanently to a new domain from an old domain during a migration (and letting them get to the page they wanted instead of just the new site’s root index page).


RewriteEngine on
RewriteCond %{HTTP_HOST} ^olddomain.com$
RewriteRule ^(.*)$ http://newdomain.com$1 [R=301,L]
RewriteCond %{HTTP_HOST} ^www.olddomain.com$
RewriteRule ^(.*)$ http://newdomain.com$1 [R=301,L]

And finally — I see many questions about search engine friendly url’s and dynamic pages. I have used this simple rewrite I learned from a friend – however – this is where some contribution would be great as I see these questions over and over in the forums. By all means add your best rewrite methods for working with dynamic pages. I do not use this last tactic too often and it is quite rudimentary.


Allows www.domain.com/newsid5.php to rewrite to www.domain.com/news.php?id=5

RewriteEngine on
RewriteBase /articles
RewriteRule ^news([^.]+).php$ news.php?id=$1

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.devboxforums.com Chroder

    Nice, I’ll have to try a few of those out.

    I tried a while ago to get mydomain.com (with or without www.) to point to mydomain.com/somedir. Reason being, I’ve got a bunch of addon domains on my hosting account and I wanted my home directory to be organized ;) Didn’t work out too well though. (With cPanel, your “main” domain name is usually your public_html directory, and all addon domains are subdirectories of that.)

    I think I’ll try again, modifying some of those examples.

  • http://www.anblik.com/ WebCrawler

    Hi Blane:

    Excellent Article. Need some clarification before I impliment the code you have written for our website.

    What is 302 redirection and is it the one which you have posted here ? Sometime back I heard that business.com penalized by google due to wrong redirection of business.com to http://www.business.com and I have seen that business.com PR goes ’0′ for atleast 1 month, though recently they recover back the lost PR.

    Is their any advantages of redirecting domain.com to http://www.domain.com ?

  • http://www.practicalapplications.net bwarrene

    I actually do not do that anymore on my domains – however – it remains popular. And I did not cease to use it for any particular reason – just did not see the need for my own domains.

    A 302 is a Moved “Temporarily” browser status code.

  • Stewart Vardaman

    Webcrawler,

    I think there is. I’ve noticed that having a mix of www and no-www links can fragment your inbound links. It seems to make a difference with things like Daypop:

    http://www.vardaman.org/archive/2003/11/26

  • pippo

    I think I spent about last year and half here at sitepoint trying to support mod_rewrite’s questions. :rolleyes:
    So if you will feel that mr google and other resources won’t satisfy your questions you can take a look at the posts at our Apache forum.

  • http://www.dvd-software.info hurricane_sh

    Thanks for the great article, mod_rewrite is always very confusing to me, never been able to write a new rule without asking :-(

  • http://glouglou.net/ oniryx

    Good examples Blane !

    Here is some RewriteEngine lines used to create sub-domain ‘on-the-fly’ (using wildcards on the DNS as well). To have xxx.domain.com to work, just create a directory called xxx in /var/www_vhosts

    Hope it helps.


    RewriteEngine On

    # a ServerName derived from a Host: header may be any case at all
    RewriteMap lowercase int:tolower

    ## deal with normal documents first:
    # allow Alias /icons/ to work - repeat for other aliases
    RewriteCond %{REQUEST_URI} !^/icons/

    # check the hostname is right so that the RewriteRule works
    RewriteCond ${lowercase:%{SERVER_NAME}} ^[a-z-]+.domain.com$

    # concatenate the virtual host name onto the start of the URI
    # the [C] means do the next rewrite on the result of this one
    RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]

    # now create the real file name
    RewriteRule ^([a-z-]+).domain.com/(.*) /var/www_vhosts/$1/$2

  • pippo

    Blane,
    based on my experience I’d say that

    > RewriteEngine on
    > RewriteCond %{HTTP_HOST} ^(.*).mydomain.com$
    > RewriteCond %{HTTP_HOST} !^www.mydomain.com$
    > RewriteRule (.*) http://mydomain.com/%1$1 [P]

    This won’t work under .htaccess

    If you access sub.example.com/image.gif you will be proxied to example.com/subimage.gif and not example.com/sub/image.gif

    ( why not use example.com as suggested by http://www.rfc-editor.org/rfc/rfc2606.txt ? )

    The reason is that under .htaccess, i.e. under a per-directory context so within a directory of httpd.conf too,
    the / will be “stripped” from the front.
    So using within .htaccess or a directory block within httpd.conf
    (supposing .htaccess is under document root dir)

    RewriteRule (.*) etc$1

    with /image.gif $1 will be image.gif
    with /path/to/image.gif $1 will be path/to/image.gif

    > RewriteEngine On
    > RewriteCond %{HTTP_HOST} !^www.mydomain.com$ [NC]
    > RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R,L]
    it’s always good to escape dots as you did before so
    RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
    would be more correct from a syntax point of view

    > RewriteRule ^news([^.]+).php$ news.php?id=$1
    same here, escaping the dot is more correct
    RewriteRule ^news([^.]+).php$ news.php?id=$1

  • http://www.practicalapplications.net bwarrene

    You are correct. As I do not use htaccess for anything – I absolutely directed readers to review Apache’s own guidance on the use of htaccess prior to pushing off from the dock. These do however work with direct httpd.conf edits.

    I should have been more clear on that – thanks for pointing that out and clearing it up Pippo.

  • http://www.brothercake.com/ brothercake

    Here’s a rewrite directive for making “clean URLs” – it turns a URL like “www.domain.com/site/first/second/third/” into “www.domain.com?c=first&s=second&z=third”


    RewriteRule ^site/([a-zA-Z0-9]+)[/]?([a-zA-Z0-9]+)?[/]?([a-zA-Z0-9]+)?[/]?([a-zA-Z0-9=&]+)? /?c=$1&s=$2&z=$3&$4 [QSA]

    Only “site” and the first value is required – the second two values are optional.

    Using the ‘magic’ QSA directive allows query string data appended to the end of a URL to be added seamlessly to the GET data – so you could go “www.domain.com/site/something/?SID=3gfgf834f” without having to parse the query string specially.

  • Richard

    One reason to standardize on either http://www.example.com or example.com is to match an SSL certificate. A certificate issued to one name will not work with the other. (That’s my crude understanding and may be subject to exceptions; please correct me as necessary.)

  • DCF

    Suppose I want to force everything to mydomain.com, even if the person visits http://www.mydomain.com. Could I just tweak the above example like this…

    RewriteEngine On
    RewriteCond %{HTTP_HOST} !^mydomain.com$ [NC]
    RewriteRule ^(.*)$ http://mydomain.com/$1 [R,L]

  • http://www.igeek.info asp_funda

    Blane, I tried your code


    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*).mydomain.com$
    RewriteCond %{HTTP_HOST} !^www.mydomain.com$
    RewriteRule (.*) http://mydomain.com/%1$1 [P]

    on my domain but it doesn’t work.
    I also tried to use a modified version


    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^(.*).igeek.info$
    RewriteCond %{HTTP_HOST} !^www.igeek.info$
    RewriteRule (.*) http://www.igeek.info/%1$1 [P]

    but it doesn’t work either. I have code above in the root of my domain http://www.igeek.info but calling http://search.igeek.info doesn’t work, you can try yourself. Ideally, as per the code, it should call the file http://www.igeek.info/search/ but it doesn’t. Any tips?

  • http://www.igeek.info asp_funda

    Sorry, the code present in my .htaccess file is


    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^search.igeek.info$
    RewriteCond %{HTTP_HOST} !^www.igeek.info$
    RewriteRule (.*) http://www.igeek.info/%1$1 [P]

    but it doesn’t work.

  • pippo

    @asp_funda

    1)
    Was your DNS configured to accept subdomains other than “www” and “empty” ?
    I don’t think so, orr at least it doesn’t seem so, because doing an “host search.igeek.info” it cannot be resolved.

    2)
    RewriteEngine on
    RewriteCond %{HTTP_HOST} ^search.igeek.info$ [NC]
    RewriteRule ^.*$ http://www.igeek.info%{REQUEST_URI} [P,L]

    should be enough.

    Remember that mod_proxy module needs to be loaded from your httpd.conf

  • http://www.igeek.info asp_funda

    Well pippo, to be honest, my host allows only 5 subdomains on my package & I create them through cPanel provided to me. So I thought that by doing this, I may be able to create extra sub-domains. ;) Too bad it didn’t work. :(

  • Anonymous

    what exactly is that slash in front of $1 for?
    RewriteRule ^(.*)$ http://www.mydomain.com/$1 [R,L]

    when i do that, http://dom.de/index.php gets http://www.dom.de//index.php

    i removed the slash in the rewrite rule and now it works without doubling the /

    ??

  • Shashank Pundir

    Hi,
    Can anyone please help me in creating subdomain as i am having xxx.com and i want if any user(yy) have made registration then a subdomain will be created as yy.xxx.com for that

    Please help me in that
    Thanks in advance

  • http://www.WAPages.net WAPages

    Wow! Thanks so much!
    I didn’t know .htaccess file was this important!

    I was finally able to make http://WAPages.net redirect to http://www.WAPages.net

    This was a problem because… half of my goggle rank was counting toward each URL.

    Thank you!

    ;]

  • pragya

    Hi,

    Can you please solve a problem related to url rewriting.
    i have a server withapache 2.0.52 running on Red Hat Enterprise Linux.

    I have written url rewrite script in .htaccess file but the script is not working.
    Here is the script –

    Options +FollowSymLinks
    RewriteEngine on
    RewriteOptions MaxRedirects=10

    RewriteRule ^(.*)_(.*)_([0-9]*)_([0-9]*).html accessories-brand.php?BrandId=$3&CatId=$4

    RewriteRule ^(.*)_([0-9]+).html accessories-brand.php?By=BRAND&BrandId=$2

    RewriteRule ^(.*)_(.*)_([0-9]+)_p.html products.php?ItemId=$3

    What should be done so that the server reads the script and it works.
    Should i have to do some server settings for it.
    Please reply me soon.

    Thanks n Regards,
    Pragya