Skip to content

Redirect and rewrite URLs using Apache modules

How to use Apache mod_rewrite and other modules to have neat URLs.

Rewriting URLs is useful for the following reasons

It will make URLs easier to remember. For example, you may have a URL

http://example.com/view/index.php?user=bob

It is possible to rewrite it as

http://example.com/~bob

This will allow Bob to easily share his page with others.

Some search engines dislike URLs with GET arguments placed in the URL. e.g. you may have the URL

http://example.com/article.php?type=apache&article_id=231

Some search engines may skip over this, but if we rewrite the URL to

http://example.com/articles/apache/231

then it is more likely to be indexed by the search engines.

If you want to restructure your website, you will need to redirect users from the old URL to the new page. Apache can do this for you, so you don’t need to use the refresh meta tag for this.

It is better to give the browser a HTTP redirect instead of having the meta tags do the redirection.

Read the official documentation. This will save lots of time in the long run.

If the web host has mod_rewrite enabled, it may allow you to upload a .htaccess file to configure the redirection. (See Apache Modules) to determine what is enabled on the server.

RewriteEngine on

The rewriting engine must be turned on.

Rules perform substitutions on URIs. The syntax is

RewriteRule Pattern Substitution [flags]

Multiple rules are applied in sequence, but there are flags that will stop further processing. e.g.

  • L or last indicates rewriting should stop.
  • R or redirect will send a redirect to the browser. This is useful when documents have moved.

- is a special substitution which lets the URI passthrough without any modification.

RewriteCond affects the RewriteRule immediately following. Subsequent RewriteRules are unaffected.

Hiding a parameter to make the URL easier to read

Section titled “Hiding a parameter to make the URL easier to read”

If you want to change this URL:

Terminal window
http://example.com/user/view.php?name=peter

to

Terminal window
http://exampleserver.com/~peter

Add a .htaccess file containing the following:

.htaccess
RewriteEngine on
RewriteRule ^~(.*) user/view.php?name=$1

This will allow the php script to run with the argument name equal to the given username.

A regular expression is used to do the substitution.

The ^ character is an anchor that matches the start of the line.

  • ~ is the literal ~ we are trying to match in the URL.
  • (.*) is broken up into three pieces.
  • . This means any character.
  • * This follows the . character, and means any number of them.
  • () This groups it as part of a match, so we can refer to it using $1 for the first match.

We’ve reorganised some pages on our website, so to preserve existing links to our site, we used the following rule

.htaccess
RewriteRule kb/app/tomcat/struts/(.*) /kb/prg/java/jsp/struts/$1 [R]

The second argument contains a leading /, because the files local path on the server was being added to the URL.

You can redirect traffic for example.com to www.example.com

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

The RewriteCond above ignores requests that already contain a subdomain.

Alternatively, you can redirect all www.* traffic to your normal domain.

.htaccess
RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]

To redirect any host that doesn’t match, you could use something like

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

This helps to get rid of the numeric IP being used as the host name.

You can also redirect traffic between domains

.htaccess
RewriteEngine On
RewriteRule old/pages/(.*) http://example.com/archive/$1 [R=301]

You can specify a new domain as part of the redirection.

301 means that it has been moved permanently.

If you use [R] instead of [R=301], then it defaults to sending a 302, which is moved temporarily.

Add the following to your .htaccess

.htaccess
# turn on mod_rewrite
RewriteEngine On
# check that it is https
RewriteCond %{HTTPS} =on
# redirect to the plain http site
RewriteRule ^(.*)$ http://magicmonster.com/$1 [R=301,L]

Instead of .htaccess you can also add this into the module conf file.

If you have mod_rewrit instead, it isn’t a typo, but an incomplete and undocumented version of mod_rewrite that is meant to be more secure. No support is provided for this.

From Version 2.4 turn on logging for the module using

LogLevel alert rewrite:trace3

For Version 2.2, if you have access to the apache configuration, then you can edit the httpd.conf apache configuration file and add logging to mod_rewrite.

RewriteLog /usr/local/apache/logs/mod_rewrite.log
RewriteLogLevel 9

9 is the highest level of logging, while 0 will turn it off. Make sure you turn it off once you’ve figured out the problem.

If you are using mod_userdir or another module that does not map the URL directly to a directory path, you may end up with an invalid path. e.g. We have placed our .htaccess into the directory /home/aelst/public_html on the dev server, so that the URL below

Terminal window
http://dev/~aelst/fish.html

actually maps to the file

Terminal window
http://dev/~aelst/whale.html

Normally you would use the following .htaccess file:

.htaccess
RewriteEngine on
RewriteRule fish\.html whale.html

However, because of the mod_userdir, we get the following error:

Terminal window
Not Found
The requested URL /home/aelst/public_html/whale.html was not found on this server.

We should be translating to the following URL instead

http://dev/~aelst/whale.html

To fix this you can either added the directory path to the rule

.htaccess
RewriteEngine on
RewriteRule fish\.html /~aelst/whale.html

or add another line into the .htaccess called RewriteBase

.htaccess
RewriteEngine on
RewriteBase /~aelst/
RewriteRule fish\.html whale.html