This’s where you’ll work the magic to get the URL structure you want in the most optimized way possible. Some of the most common used rewrite usage are to shorten long URLs to short-friendly, protect your self against hotlinking, transforming dynamic ?page=title§ion=foo to friendly /title/foo/ or redirecting missing pages and much much more.
The mod_rewrite support is installed on most webhotels that are running Apache. If you are new to writing rules it can be a pain in the ass to get it working as you want, I spent hours and hours to get some of this working so here are some quick examples how to get some basic stuff working. I’ll try and explain what each rule are doing as well.
Starting point
Before starting entering rewrite rules you need to make sure that the rewrite engine is on and that Apache is following the links correctly. You do this by entering this 2 lines at the top of your .htaccess file
Options +FollowSymlinks RewriteEngine on
Options +FollowSymlinks: It specifies whether or not Apache should follow a simbolic link while looking for a file. Without this none of your rules will be working.
RewriteEngine on: Basically turns the rewrite engine on
Remove www or add it
For SEO purpose you only want one host to your website, so you have to decide to have www or not. Anyhow it good to make a rule so that the other way redirects to the one you want.
From http://domain.com -> http://www.domain.com
RewriteCond %{HTTP_HOST} ^domain.com$ [NC] RewriteRule ^(.*)$ http://www.domain.com/$1 [L,R=301]
RewriteCond %{HTTP_HOST} ^domain.com$ [NC]: RewriteCond set ups the rules, in this case matches with the host. ^ means that it has to start with “domain.com” for it to be true. It will not match if any subdomain or www is entered as host. [NC] = no case
RewriteRule ^(.*)$ http://www.domain.com/$1 [L,R=301] RewriteRule is the actual rule that will be executed it the condition is correct. What we do here is that everything at the beginning will be redirected with a 301 (aka, “MOVED PERMENENTLY”) to www.domain.com. http://domain.com/category/page.html will be redirected to http://www.domain.com/category/page.html
To reverse it:
RewriteCond %{HTTP_HOST} ^www.domain.com$ [NC] RewriteRule ^(.*)$ http://domain.com/$1 [L,R=301]
Redirect all subdomains
If you changed your website’s structure or took over an old site that had a lot of sub domains, not to loose any traffic is good to redirect all them to your current site.
RewriteCond %{HTTP_HOST} !^domain.com$ [NC] RewriteRule ^(.*)$ http://domain.com/$1 [L,R=301]
!^domain.com$: If the current URL does NOT match this pattern (domain.com)
Find out what more server variables you can use in your conditions
Hide URL GET variables
Lets say you have a zip archive and want to hide “the real” URL, /download.php?section=bar&filename=foo.zip is an ugly URL. We’ll make a rule so that the URL will be /files/bar/foo.zip.
RewriteRule ^files/([^/]+)/([^/]+).zip /download.php?section=$1&filename=$2 [NC]^files/([^/]+)/([^/]+).zip /download.php?section=$1&filename=$2: Condition for all URI that starts with “files”, first match between / will be $1, second $2. Read more about how regexp works
Show a different homepage on different agents
Different browsers have different support, modern browsers are pretty good nowadays but smartphones and browsers like Lynx might need a more simple homepage or if you have a optimized page for a specific browser.
RewriteCond %{HTTP_USER_AGENT} ^Chrome RewriteRule ^/$ /homepage.chrome.html [L] RewriteCond %{HTTP_USER_AGENT} ^Lynx [OR] RewriteCond %{HTTP_USER_AGENT} ^Android RewriteRule ^/$ /homepage.min.html [L] RewriteRule ^/$ /homepage.std.html [L]
So here we display a special homepage for Chrome browsers, and a simple page for Lynx and Android smartphones, the rest will get homepage.std.html.
Change all htm to php pages
RewriteRule ^(.+)\.htm$ http://www.domain.com/$1.php [R,NC][R]: Tells Apache to redirect, if no status code defined a 302 (aka MOVED TEMPORARILY) will be executed, [R=301] will make a 301 etc.
Basics of regexp
From the Apache documentation:
Escaping:
\char escape that particular char
For instance to specify special characters.. [].()\ etc.
Text:
. Any single character (on its own = the entire URI)
[chars] Character class: One of following chars
[^chars] Character class: None of following chars
text1|text2 Alternative: text1 or text2 (i.e. “or”)e.g. [^/] matches any character except /
(foo|bar)\.html matches foo.html and bar.htmlQuantifiers:
? 0 or 1 of the preceding text
* 0 or N of the preceding text (hungry)
+ 1 or N of the preceding texte.g. (.+)\.html? matches foo.htm and foo.html
(foo)?bar\.html matches bar.html and foobar.htmlGrouping:
(text) Grouping of text
Either to set the borders of an alternative or
for making backreferences where the nthe group can
be used on the target of a RewriteRule with $ne.g. ^(.*)\.html foo.php?bar=$1
Anchors:
^ Start of line anchor
$ End of line anchorAn anchor explicitly states that the character right next to it MUST
be either the very first character (“^”), or the very last character (“$”)
of the URI string to match against the pattern, e.g..^foo(.*) matches foo and foobar but not eggfoo
(.*)l$ matches fool and cool, but not foo
Server variables
All these can be used in your conditions %SERVER_VAR%
HTTP headers:
HTTP_USER_AGENT
HTTP_REFERER
HTTP_COOKIE
HTTP_FORWARDED
HTTP_HOST
HTTP_PROXY_CONNECTION
HTTP_ACCEPTconnection & request:
REMOTE_ADDR
REMOTE_HOST
REMOTE_PORT
REMOTE_USER
REMOTE_IDENT
REQUEST_METHOD
SCRIPT_FILENAME
PATH_INFO
QUERY_STRING
AUTH_TYPEserver internals:
DOCUMENT_ROOT
SERVER_ADMIN
SERVER_NAME
SERVER_ADDR
SERVER_PORT
SERVER_PROTOCOL
SERVER_SOFTWAREdate and time:
TIME_YEAR
TIME_MON
TIME_DAY
TIME_HOUR
TIME_MIN
TIME_SEC
TIME_WDAY
TIMEspecials:
API_VERSION
THE_REQUEST
REQUEST_URI
REQUEST_FILENAME
IS_SUBREQ
HTTPS
Setting up a web server
Learn how to configure a web server from home, read more