10+ Mod_Rewrite Rules You Should Know
Mod_rewrite is an Apache-based rewrite engine for dynamically rewriting URLs. It's built into Apache servers natively, though not enabled by default.
It's capable of functions beyond simple rewrites, though, some of which are included below.
Internet's universe... photo by CLUC shared under Attribution-NonCommercial-NoDerivs 2.0 Generic (CC BY-NC-ND 2.0) licence
Internet's universe... photo by CLUC shared under Attribution-NonCommercial-NoDerivs 2.0 Generic (CC BY-NC-ND 2.0) licence
Turn Mod_Rewrite On
Mod_rewrite is used through your .htaccess file. Place the following code at the beginning of your .htaccess file to turn mod_rewrite on:RewriteEngine on(Don't forget that .htaccess commands are case-sensitive.) This code needs to be entered at the beginning of any .htaccess file using mod_rewrite.
The Basic Mod_Rewrite Layout
The basic format for a mod_rewrite command is:RewriteRule Pattern Substitution [Flag(s)]
URLs are Always Relative
The URL you redirect to is always relative to the directory in which your .htaccess file is placed. So if it's in the root directory, URLs are all in relation to the root directory; if it's in a sudirectory, URLs are in relation to that particular subdirectory.A Basic Redirect
If you just want to create a simple 301 redirect from one URL to another, then use the following code:RewriteRule ^fileone.html$ filetwo.htmlThis is a very basic rule that means any requests for fileone.html will be sent to filetwo.html.
Require no "www"
This bit of code will make it so visitors to your site don't need to type in the "www" bit of your website address.RewriteCond %{HTTP_HOST} !^domain.com$ [NC] RewriteRule ^(.*)$ http://domain.com/$1 [R=301,L]
Block a Specific IP Address
If you want to block someone coming from a specific IP address from accessing your website, you can use the following code:RewriteCond %{REMOTE_ADDR} ^(A.B.C.D)$ RewriteRule ^/* http://www.domain.com/sorry.html [L]Replace the A.B.C.D with the IP address you want to block (don't forget to leave the "" before each dot, which escapes the character).
Block Specific User Agents
If you want to block a group of IP addresses using the same User Agent (bot), the following code with do it:RewriteCond %{HTTP_USER_AGENT} UserAgent RewriteRule .* - [F,L]Just replace the "UserAgent" bit with whatever user agent you want to block. You can also block more than one at a time by replacing the top line in that code with something like this:
RewriteCond %{HTTP_USER_AGENT} UserAgentA [OR] RewriteCond %{HTTP_USER_AGENT} UserAgentBYou can put as many user agents in as you want, just make sure you end each line with [OR] (with the exception of the last line, of course).
Strip Query Strings
Let's say all the pages on your site other than your home page are formatted as follows, with query strings instead of page names: http://www.domain.com/home.html?example=12345abcd Those aren't very pretty, and on top of that, search engines will show a bunch of duplicated "home" pages. If you want to get rid of the query string in your page URLs, use the following code:RewriteCond %{QUERY_STRING} example= RewriteRule (.*) http://www.domain.com/$1? [R=301]This not only gets rid of the query string, but also the preceding question mark.
Set up a Default Image
Using a default, backup image in case of broken images can make your site look more professional. Use the following code to redirect to a default image for any image whose file cannot be found.RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^images/.*.jpg$ /images/default.jpg [L]Of course, you can change the ".jpg" bit to whatever file type you're using. Make sure you have an image called "default.jpg" or change that to whatever your default image filename is.
Prevent Hotlinking
The last thing most website owners want is other sites stealing their content or worse—hotlinking to their images and stealing their bandwidth. Here's a simple bit of code that prevents it:RewriteCond %{HTTP_REFERER} !^$ RewriteCond %{HTTP_REFERER} !^http://(www.)?domain.com/ .*$ [NC] RewriteRule .(gif|jpg|swf|flv|png)$ /feed/ [R=302,L]Make sure you change the "domain.com" bit to your own domain name.
Redirect to a Maintenance Page
If you need to take your entire site offline for a bit and redirect to a maintenance page (or some other page), use the following code:RedirectMatch 302 ^/ /maintenancepage.htmlChange the "maintenancepage.html" bit to wherever your maintenance page file is located.
Redirect Multiple Domains to a Single Domain
If you have multiple domains pointing to your site, it's possible you could take a hit in the search engines for having duplicate content. Use the following code to redirect visitors from two domains to just one:RewriteCond %{HTTP_HOST} ^www.domain.net$ [NC,OR] RewriteCond %{HTTP_HOST} ^domain.net$ [NC,OR] RewriteCond %{HTTP_HOST} ^www.domain.net$ [NC] RewriteRule ^(.*)$ http://domain.net/$1 [R=301,L]
Remember the Filesystem Always Takes Precedence
The filesystem on your server will always take precedence over the rewritten URL. For example, if you have a directory named "services" and within that directory is a file called "design.html", you can't have the URL redirect to "http://domain.com/services". What happens is that Apache goes into the "services" directory and doesn't see the rewrite instructions. To fix this, simply rename your directory (adding an underscore to the beginning or end is a simple way to do that).Remember:
- Because mod_rewrite works within the .htaccess file, commands are case sensitive.
- Always back up your .htaccess file before making any changes to it. This way, if there's a problem, you can easily restore your site.
More Resources:
- Modrewrite.com - This is a great site that offers a forum, a beginner's guide, and links to more information about mod_rewrite.
- Mod_Rewrite Tips and Tricks - A great article on the basics of mod_rewrite and some beginner and advanced techniques.
- Mod Rewrite Tips and Tricks - This site offers a few basic tips for mod_rewrite.
- Apache Mod_Rewrite Cheat Sheet - This cheat sheet offers information on the most-used items for building a mod_rewrite pattern.
- Learn Apache mod_rewrite: 13 Real-World Examples - This is a much more advanced article from SitePoint.
- Module mod_rewrite URL Rewriting Engine - The official documentation from Apache.
- .htaccess Rewrite Tips for Using RewriteRule and RewriteCond for .htaccess mod_rewrite - A great guide to a number of different mod_rewrite patterns.
- Tip for Configuring Apache's Mod_Rewrite - Five great tips for mod_rewrite configuration.
- Several Mod_Rewrite Tricks for a Better Web Application - Covers a number of basic and more advanced mod_rewrite tricks.
* URLs are Always Relative – FALSE. URLs are relative to the current directory only if no RewriteBase directive is used, in which case the URLs become relative to the specified path. (http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html#rewritebase) Also, you can use absolute URLs by specifyng the protocol to be used.
* …so visitors to your site don’t need to type in the “www” bit… – WRONG. That has nothing to do with making the “www” optional. It’s related to SEO, creating a single entry-point to your website by redirecting all your visitors (including search engines) to your “domain-name.tld”. This way, the search engines won’t index the same page twice, making it lose its strength.
This rule should be accompanied by a rule to remove file names such as “index.php”, “index.php5”, “index.asp”, “index.htm”, “index.html”, “default.html”, etc, which all point to the same page, the homepage. If a user can see the homepage on multiple different URLs, so can a search engine, which will index it as X different pages (X being the number of available URLs for the homepage)
You should be using something like this:
RewriteRule (index|home|default)\.([a-zA-Z0-9]{3,4})$ / [R=301,L]
Also, 302 is “Found” while 301 is “Permanently Moved”. They are both redirects but the second should be used for permanent rules. The second tells the crawler to “forget” this URLs as the resource associated with it has been moved to the new location and that is the URL that it should be using from now on. The first one just says: “Ok, for now, what you are looking for has been moved someplace else, but you should check this URL again in the future as the resource might become available again”
Also, I don’t agree with the statement that “a default image would make your site look more professional in case of a broken image URL”… You could say, at best, that it would make your site look less dilettantish, as a professional wouldn’t have broken links on any of his pages. :P
* Remember the Filesystem Always Takes Precedence – are you absolutely sure about that? ‘Cause I’m pretty sure that if I have this rule:
RewriteRule ^dir-name(.*)$ file-name.php [NC,L]
and I try to access http://my-domain.tld/dir-name/other-file.html, even though there is an other-file.html in a dir-name, I will get the contents of file-name.php
I’m sure about that because I use this in all of my projects and I always have to specify which folders I want to exclude from my rules. E.g: I redirect absolutely everything to the index.php file (which acts as a bootstrap file) and I use something like:
RewriteRule ^assets(.*)$ – [NC,L]
to allow users to access the contents of the “assets” folder, where I usually keep the image/css/javascript files…
These being said, I’ll give you the “thumbs up” for the initiative and, sadly, a “thumbs down” for the quality of the content… :(
I forgot this…
Let aside the fact that RedirectMatch is a mod_alias directive, not a mod_rewrite, there is no way your example would ever work, because any “maintenance” file name you would use, it would be matched by the given regex, resulting in a neverending redirect…
What you could use instead is:
RewriteCond %{REQUEST_URI} !maintenance.html$ [NC]
RewriteRule .* /maintenance.html [R=302,NC,L]
However, this would also block users to access the images or css files, so you will have to add more RewriteConds to that set, making it look something like:
RewriteCond %{REQUEST_URI} !^/css [NC]
RewriteCond %{REQUEST_URI} !^/images [NC]
RewriteCond %{REQUEST_URI} !^/js [NC]
RewriteCond %{REQUEST_URI} !^/maintenance.html$ [NC]
RewriteRule .* /maintenance.html [R=302,NC,L]
Thank you so much for this – exactly what I was looking for.
I’ve been searching for hours looking for how to allow the images to show on my outage page, realizing they were caught in a redirect loop.
Can I get a contact Mr. Prafuitu?
How about a mod_rewrite Fix for Controlling updated files and Caches:
RewriteCond %{THE_REQUEST} ^(GET|HEAD) /z/([a-z]+)/(.+)-([0-9]+).(js|css).* HTTP/ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .+ /z/%2/%3.%5 [NC,L]
or
Cache-Friendly File Names that allow you to update javascript and css files in my visitors cache’s simply by naming them differently in the html, on the server they stay the same name.
RewriteRule ^directory/(j|c)/([a-z]+)-([0-9]+).(js|css)$ /directory/$1/$2.$4 [L]
thank you so much for this post! I have been meaning to consolidate my .com and .me domains, and strip the www. prefix — you’ve helped me do exactly that, and also disable hotlinking and add in maintenance page references for future use. Thanks again!!
Thanks for the article. I’m a mod-rewrite newbie struggling with an issue…
I have a current directory path:
http://www.mysite.com/blah/page.php?specialcode=123456
I want to redirect all attempts to blah/ to http://www.mysite.com/new/index.php?page=new-page&specialcode=123456 and want to retain the special code included in the initial URL.
I’ve essentially re-written a complete section of the site in a mini-MVC model and need to convert traffic going to the old pages to the new model. I can do this in PHP, but want to completely get rid of blah/ and never look at it again.
Any help would be appreciated.
Thanks,
Nick
Thanks for the article. Im a mod-rewrite newbie struggling with an issue…
I have a current directory path:
http://www.mysite.com/blah/page.php?specialcode=123456
I want to redirect all attempts to blah/ to http://www.mysite.com/new/index.php?page=new-page&specialcode=123456 and want to retain the special code included in the initial URL.
I’ve essentially re-written a complete section of the site in a mini-MVC model and need to convert traffic going to the old pages to the new model. I can do this in PHP, but want to completely get rid of blah/ and never look at it again.
Any help would be appreciated.
So this one will Block IE6, right?
RewriteCond %{HTTP_USER_AGENT} ‘MSIE6’
RewriteRule .* – [F,L]
oupp yes now i know to block IE6 thanks
thanks for the post, really useful stuff :)
hi
it was a good tutorial
i have an old problem with htaccess and i wonder if you could help me whith it. please please please please help
i want to do this with my htaccess
the role :
1 – users request a url like : test.mysite.com
2- apache should know show mysite.com/test
BUT idont want the user to see the second url in his/her addressbar can you help me?
thanks
if you had any thing to say please mail me and let me know . thanks again
Thanks , Useful post
Hi,
suppose, there is a url
http://www.domain.com/asad
I want to redirect it to
http://www.domain.com/folder1/folder2/folder3/asad
Can any one help me, how is this possible,
Thanks
Asad