Rewriting URLs using mod_rewrite

Every so often as a web developer, you might have to write a redirect of some URLs to some other ones to an .htaccess file. If you remember these tips here, you will probably have most of the stuff you need:

Redirect a specific URL to another URL

Redirect 301 "/old-page.html" "/new-page.html"

301 here means it is a permanent redirect. Over time Google and other search engines will then replace the old URL with the new one in their index. 302 would be used for a temporary redirect - note that you should prefer to test with 302 first if you are unsure, as 301 redirects get cached aggressively in the browser, so if you made a mistake, you would have a hard time recovering. Trust me, I experienced this first hand ;)

Redirecting several URLs

If you need to redirect several URLs, you generally want to follow the scheme of having a condition (on what to match) and a rule (how to redirect):

RewriteCond %{HTTP_HOST} ^www.example.com
RewriteRule (.*) https://example.com/$1 [R=301,L]

The condition RewriteCond ensures, this is only for the website www.example.com. The RewriteRule takes everything (.*) following the domain name and adds it ($1) to https://example.com/. In this case, the www part is removed from the URL.

R=301 indicates a permanent redirect again, so you could use R=302 instead which is recommended for testing.

L means that this is the last rule to be executed, so the processing of the .htaccess file stops here if the rule is triggered.

Important: Relativity matters!

Keep in mind that the .htaccess file is always executed relative to the folder in which it resides.

Example for relativity

Assume the URL www.example.com which is served from the folder root/. Further, let’s say there is a subdirectory root/wiki/, which we serve from www.example.com/wiki. If we have an .htaccess file in root/wiki/.htaccess, then everything will be relative to that folder.

If we called the URL www.example.com/wiki/test.php and used this rule:

# .htaccess file in root/wiki/.htaccess
RewriteRule (.*) https://www.another-domain.com/$1

we would be forwarded to https://www.another-domain.com/test.php. Note that we lost the /wiki/ part, because (.*) matches relative to root/wiki/! If you need that /wiki/ part, your Rule should be in the root/ folder in the root/.htaccess file! Another option is to use the %{REQUEST_URI} variable which contains the full path.

Rewrite a domain to another one

RewriteCond %{HTTP­_HOST} ^www.domain.com$ [NC]
RewriteRule ^(.*)$ http://www.domain2.com/$1 [R=301,L]

NC here means case insensitivity.

RewriteBase

When you are using relative URLs in your rules, then RewriteBase makes sure to append an absolute path before the relative URL. This can be useful if you want to be staying in the relative folder. Let’s go back to that wiki example and we want to redirect a specific URL within the wiki folder:

RewriteBase /wiki/
RewriteRule ^foo$ bar.php [L]

This will redirect www.example.com/wiki/foò to www.example.com/wiki/bar.php. If we omitted the RewriteBase, then we would instead be redirected to www.example.com/bar.php.

Redirect your domain from http:// to https://

Nowadays, it is standard practice to encrypt your website using SSL. Often, your site can still be accessed using http:// in an unencrypted manner. To make sure that you are always serving the encrypted version, you can use this configuration in your .htaccess file. It consists of two conditions - one for your host name and one which triggers when HTTPS is turned off, so the site is accessed unencrypted. We then simply rewrite it to https:// and keep both the host and the request URI:

RewriteCond %{HTTP_HOST} ^www.paepper\.com [NC]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI}

A note on testing .htaccess rules

You obviously want to test first on your development machine before putting the information to your live site. So to properly test it, I would recommend to set up the same folder structure (which you should already have on your development machine anyways) and create an Apache configuration to serve your live URL locally, then change the DNS IP routing of your domain to your localhost 127.0.0.1 in the file /etc/hosts on Linux. With this setup, you can test the exact redirects as they would happen on your live site and get no surprises down the road. Beware, though, as mentioned before, that 301 rules get cached aggresively by your browser.

Awesome cheat sheet for mod_rewrite / .htaccess rules

Have a look here: https://www.cheatography.com/davechild/cheat-sheets/mod-rewrite/