Apache mod_rewrite Tutorial

What are the mod_rewrite directives and how to use them

mod_rewrite is an Apache module that is used for redirecting content to another location on the same account or to an external URL, for any kind of URL remapping, for restricting access to content on your account, etc. You can specify different conditions that have to be met in order for the rewriting to be applied. The things that you can do with mod_rewrite are pretty much countless.

All HostKnox servers have mod_rewrite installed.

In this tutorial we'll briefly outline the mod_rewrite directives that you can use in your .htaccess files. The information here is by no means complete but it's intended to give some better understanding of the directives (if you don't know anything about it), to help you in constructing some not too complex rewrite rules yourself, and generally to give you a start in case you want to dig deeper into this matter.

We'll start with a simple example containing the different directives. We'll explain what each one means, what its syntax is and what it's used for.

RewriteEngine On
RewriteBase /folder/
RewriteCond %{HTTP_REFERER} domain\.com
RewriteRule ^index\.php$ index2.php [R,L]

What the above rules will do is to redirect requests for yourdomain.com/index.php to yourdomain.com/folder/index2.php. However, this will apply only to those requests that come from links on the site domain.com. Requests from other sites for yourdomain.com/index.php will not be redirected. The above rules are put in the .htaccess file that's in the public_html directory of the hosting account. This is the document root (the root web-accessible directory).

The RewriteEngine directive turns on and off the rewriting engine. When you put rewrite rules in your .htaccess files you should always put first the RewriteEngine directive and set it to On if you want the rules to be active. If you don't want the rules to be applied any more just set it to Off.

The RewriteBase directive sets the relative path for the Substitution argument of the RewriteRule directive (that's the second argument; in our example this is index2.php). This is not a required directive but it's useful. By default, the path to the content that's used for substitution is relative to the document root (e.g. public_html). So in the above example rules, if we remove the RewriteBase directive, we would have to change the RewriteRule directive to RewriteRule ^index\.php$ /folder/index2.php [R,L]. The base is set in relation to the public_html folder on the hosting account. So in our example the RewriteBase /folder/ directive points to public_html/folder.

The RewriteCond directive is used to impose conditions which have to be met in order for the rewrite rule to be applied. It's an optional directive. It has to be put before the actual RewriteRule directive. Many RewriteCond directives can be applied to one rewrite rule; just list them before the rewrite rule. If there's more than one condition, all have to be matched in order for the rewrite rule to be applied. The RewriteCond directive(s) will be valid only for the first rewrite rule that's listed after them. If there's another rewrite rule after the first one, the conditions will not apply to it. The RewriteCond directive has the following syntax:

RewriteCond TestString Condition [flags]

The TestString argument is used to describe some aspect of the request. It's usually a server variable. When a server variable is used it's enclosed in curly brackets and the percent symbol is put in front of the opening bracket. In our example it's %{HTTP_REFERER}; Referer is an HTTP header field that specifies the site from which a link was used to come to the requested site. The RewriteCond directive will be applied to the rewrite rule if the Condition argument matches the TestString. Perl compatible regular expressions are used for the Condition argument. In our example if the Referer is domain.com, then the condition will be fulfilled.

The [flags] argument is optional. It allows you to add more options; there are a few flags that can be used with the RewriteCond directive. The most frequently used flags are NC which stands for no case and it's used for case-insensitive matches. The OR flag is used in the occasion when you use more than one RewriteCond directive and you want any of the conditions instead of all to match in order for the rewrite rule to be applied. For example:

RewriteCond %{HTTP_REFERER} domain\.com [NC,OR]
RewriteCond %{HTTP_REFERER} anotherdomain\.com [NC]

If the Referer is either domain.com or anotherdomain.com, then the rewrite rule will be applied. Because of the NC flag the TestString and Condition arguments in both directives will be case-insensitive.

The RewriteRule directive is actually the one that performs the rewriting. If there are any conditions set before it with RewriteCond directive(s), the rewriting will be applied for those requests that meet the conditions. It has the syntax:

RewriteRule Pattern Substitution [flags]

Pattern is the argument that's used to match the path part of the URL address. In our example that would be the part that comes after yourdomain.com. This being said it should be kept in mind, however, that the Pattern is relative to the folder containing the .htaccess file with the rewrite rules. For instance, if our example directives are in the .htaccess file that's in the public_html folder on the hosting account, then the Pattern of the RewriteRule would match yourdomain.com/index.php. However, if we put the rule in an .htaccess file that's in public_html/folder, then the Pattern will match yourdomain.com/folder/index.php. Perl compatible regular expressions are used for the Pattern; that's why there are symbols such as ^ and $. Another useful thing to remember is not to put a forward slash at the beginning of the pattern (e.g. ^/index\.php$).

If the URL-path of the requested URL matches the pattern then it's substituted with whatever is specified by the Substitution argument of the directive. The Substitution argument can be a path on your hosting account (as in our example) or it can be a full URL address (e.g. http://somedomain.com).

In case the Substitution argument of the RewriteRule directive is a path on your account then it's in direct relation with the RewriteBase directive (if it's included at all). If you have set the base folder with the RewriteBase directive, then provided the file is in the same folder you only need to list it in the place of the Substitution argument (without a forward slash before it). If you list the path to the file with a forward slash in front of it, the path will be treated in relation to the public_html directory (the document root) even when the RewriteBase is set. For instance, if we change the Substitution argument in our example from index2.php to /index2.php, then the requests will be redirected to yourdomain.com/index2.php instead of to yourdomain.com/folder/index2.php, even though the RewritBase is set to /folder/.

Additional options can be used with the [flag] argument; it's not required. In our example links to yourdomain.com/index.php that come from a site called domain.com are redirected externally to yourdomain.com/folder/index2.php. The external redirection is specified by the R flag; flags are placed in square brackets and are separated with a comma. Another commonly used flag is L which stands for last. It's used when there are many RewriteRule directives one after the other. Without the L flag the result of the first rule is applied to the second, and so on.