inicenter logo
UniServer 3.4 logo
rule condition block diagram
 New Users - mod rewrite 1
uniform server logo

mod rewrite - introduction

Search the Internet for mod-rewrite and you will find a minimum of five million pages to choose from so why do I think another one is required? Well I don’t this quick start guide is all about finding the on-off switch and Apaches lack of morals, it can be made to lie effortlessly! Interested then read on.

Mode-rewrite is a standard Apache module, which takes an incoming page request and transforms it into a completely different one. A user requesting a page can be made aware of this transformation or it can be transparent and hidden, this is what makes mod-rewrite so powerful. To make Apache lie effortlessly like this requires practice in a safe environment. This is where Uniform Server comes into its own, just extract a copy to any folder and you are ready to explore and test before deploying to your real live server.

Test files

I personally find copying and pasting examples from the Internet tedious and prone to errors. The examples I wish to show I have resolved this tedium by including each test in a self-extracting archive.


Download

All these archives themselves have been archived into a single self-extracting archive. On your test server download and copy the file unicenter_mod_rewrite.exe (249K) to folder www, double click this file to run the self-extracting archive.

When run click extract (do not change the folder), when challenged to confirm file replace click “Yes to all”.


Extracted files

After unzipping unicenter_mod_rewrite.exe you will find seven files named test1.exe to test6.exe and uc_restore.exe these are self-extracting archives.

Move files test6.exe and uc_restore.exe to folder “Uniform Server” (the one containing the start and stop batch files) These are both used in example 6, uc_restore.exe reverts the server to its initial installation by overwriting the htaccess file in folder www and the Apache’s main configuration file httpd.conf located in folder *\Uniform Server\udrive\usr\local\apache2\conf


Examples

To follow each example in this tutorial run the appropriate self-extracting archive file by double clicking on it.

When run click extract (do not change the folder), when challenged to confirm file replace click “Yes to all”.

Each of these archives overwrites the .htaccess file and creates any sub-folders and files that each example requires.

Note: The files may be run in any order, no need to restart the servers when running test1.exe to test5.exe (Apache always checks .htaccess for each incoming request). However after running test6.exe and uc_restore.exe the server must be restarted for the changes to take place.


7-Zip - Open source

Open source is all about quality software like Uniform Server 7-Zip is ace. The above files were compressed using it, however each test file has an overhead of about 130K since they use the SFX feature (includes the program to extract the files). The result, well!

test1.exe 133,713 bytes test4.exe 142,821 bytes
test2.exe 132,992 bytes test5.exe 133,486 bytes
test3.exe 133,213 bytes test6.exe 53,714 bytes
uc_restore.exe 144,903 bytes    
Total 974,842 bytes    
unicenter_mod_rewrite.exe 255,825 bytes

7-Zip rips out the program from each file and only compresses one.

When decompressed each file has its program restored.

Well I digress back to the tutorial.

Ho! Did I mention there is a portable version of 7-Zip check it out.


Structure

I have included this to show you the structure of a mod-rewrite block. At this stage all you need is a general understanding what each line is for.

CODE
COMMENTS

< IfModule mod_rewrite.c>

Optional: Code between <IfModule mod_rewrite.c> and </IfModule> executed only if mod-rewrite enabled. When the block is run on a server with mod-rewrite disabled will prevent a 500 internal server error.
  Options +FollowSymLinks Required: This is a security feature of the rewrite engine and must be set. It informs Apache to follow the newly created link names.
  Options +Indexes Optional, set it if you want to display a directory listing when no index page found (Uniform Server's default).
  RewriteEngine On Required: Turns the rewrite engine on and must be set.
  RewriteBase / Optional: Explicitly sets the base URL for your rewrites (Optional however always use it)
  RewriteCond STRING CONDITION Optional: Extends our rules
  RewriteRule PATTERN DESTINATION Required: Rewrites are done according to the rules you specify here.
< /IfModule>  

On a server with mod-rewrite and indexes enabled the above reduces to this:

CODE
COMMENTS
  Options +FollowSymLinks Required: This is a security feature of the rewrite engine and must be set. It informs Apache to follow the newly created link names.
  RewriteEngine On Required: Turns the rewrite engine on and must be set.
  RewriteBase / Optional: Explicitly sets the base URL for your rewrites (Optional however always use it)
  RewriteCond STRING CONDITION Optional: Extends our rules
  RewriteRule PATTERN DESTINATION Required: Rewrites are done according to the rules you specify here.

The above code can be placed in either an .htaccess file or inside Apache httpd.conf file. Throughout these examples, I am using the .htaccess file contained in the root folder www.

Important

With the rewrite engine switch on all page requests are passed to it for processing. To any incoming page requests the engine is brutal; it first chops off the host part and starting forward slash. Not content with this it then chops off any query string including the question mark, the resulting string is stored in a hidden variable. Lets call this variable resulting_string.

It’s important to understand this mutilation because the resulting_string variable is used in the RewriteRule suppose we have a request for this URL:

http://forum.uniformserver.com/dir/index.php?showforum=5

The following gets chopped off: http://forum.uniformserver.com/ and ?showforum=5

leaving dir/index.php this is stored in the variable resulting_string for use by the RewriteRule this is refered to the REQUEST_URI

Note: REQUEST_URI

Prior to Apache 2 the {REQUEST_URI} string starts with a / character. You can satisfy all Apache versions by making the leading slash in the PATTERN optional with the expression /? (? is a special character for zero or one of the preceding character this is covered later)

For example (taken from example 1 below) RewriteRule test1/page1.html test1/page1.php would look like this:

RewriteRule /?test1/page1.html test1/page1.php

I do not use this in any of the examples because you should not be using older versions of Apache! It’s shown for completeness.


RewriteRule

Rewrites are done according to the rules you specify. A rule is created using the follow syntax:

RewriteRule PATTERN DESTINATION
Incoming requests that match PATTERN will be rewritten to the new DESTINATION.
Note: PATTERN is compared to the hidden variable "resulting_string".
Note: RewriteBase / is added to the DESTINATION

Example 1 - Basic RewriteRule

Before looking at the example install test1 as explained above (double click on test1.zip). This creates a folder named test1, which contains a single file page1.php. Htaccess is overwritten and contains the following lines:

.htaccess
#=================== Test 1 ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test1/page1.html test1/page1.php

With the servers running type the following into your browser address bar: http://localhost/test1/page1.html and note the following:

  •  A page is displayed
  •  The browser address bar does not change it still displays http://localhost/test1/page1.html
  •  However the only page in folder test1 is page1.php

Explanation

After processing our incoming URL, the hidden variable now contains test1/page1.html this is compared to our test string test1/page1.html and matches.

On matching, the rewrite process is activated and the base URL is added to our destination string producing the following address http://localhost/test1/page1.php This page is served to a user, however since there are no flags after the destination string a user is not informed that a redirection occurred.

Proof positive that Apache has lied effortlessly, there is no such page as page1.html you have just observed the power of mode-rewrite in action.


Regex

The above appears to work however I purposely introduced an error into our PATTERN (test string). To see this inaction type the following into your browser address bar:

http://localhost/test1/page1bhtml

You can replace b with any valid single character and the page will display, clearly not the original intention only a full stop (dot) shall get matched.

A test pattern is not a combination of pure characters but a regular expression (regex) this is a special language used for pattern matching. There are a number of pre-defined characters that have a special function in a regex the full stop is one of these. It indicates a match for any single character, when you want to match a full stop it needs to be escaped by using a back slash \. The same applies to any of the pre-defined regex characters.

Edit htaccess and escape the full stop as shown, run the above test again:

.htaccess
#=================== Test 1 ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test1/page1\.html test1/page1.php

Example 2 - Multi RewriteRules

Before looking at this example install test2 (double click on test2.zip). This creates a folder named test2, which contains several files.
Htaccess is overwritten and contains the following lines:

.htaccess
#=================== Test 2 ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test2/page2\.html test2/page7.php
RewriteRule test2/page3\.html test2/page8.php
RewriteRule test2/page4\.html test2/page9.php

With the servers running type the following into your browser address bar: http://localhost/test2/page1.html and note the following:

  •  The main page is displayed. Click the three bottom links in turn.
  •  Each of these links are re-written to serve a php page however the browser address bar displays the html page.

Explanation

All page requests are passed to the rewrite engine; the main page does not have a rewrite rule and is passed through unchanged. The three links each have a rewrite rule that when matched the appropriate php page is served.

Remember that the test pattern is a regex we are looking to match a full stop so it needs to be escaped with a backslash.


Rewrite Flags

A standard RewriteRule is transparent to the user hence no change in their browser address bar. However you can use the R flag to send back a redirect status code (3xx) and the new location. This will update their address bar with the destination.

By default, R will send a 302 temporarily moved header, whereas R=301 will send a 301 permanently moved header. Note you probably will want to use R=301 if you have an existing site this will maintain search engine rankings.

Edit htaccess and add rewrite flags as shown, run the above tests again:

.htaccess
#=================== Test 2 ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test2/page2\.html test2/page7.php [R=301]
RewriteRule test2/page3\.html test2/page8.php [R]
RewriteRule test2/page4\.html test2/page9.php [R]

Note: Rewrite flags are contained in square brackets.

Efficiency

The rewrite engine processes all rules regardless of finding a match; if the first rule is matched all remaining rules are processed. To prevent this use the L flag, when a RewriteRule has been applied the rewrite engine will stop processing any remaining rules.

The htaccess file would look like this. I have included it to highlight the fact that flags are separated using a comma.

.htaccess
#=================== Test 2 ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test2/page2\.html test2/page7.php [R=301,L]
RewriteRule test2/page3\.html test2/page8.php [R,L]
RewriteRule test2/page4\.html test2/page9.php [R,L]

Example 3 - Split RewriteRules across htaccess files

I mentioned earlier you place your rewrite rules either in the Apache configuration file (httpd.conf) or (and) in the root (www) htaccess file. However you can use an htaccess file in a sub-folder to specifically target that area. I personally think its more cosmetic than practical. All rewrite rules will be executed regardless where they are located since they propagate up the chain of htaccess files.

Before looking at this example install test3 (double click on test3.zip). This creates a folder named test3, which contains two folders main and sub. These in turn contain several files. Folder sub contains an htaccess file that specifically targets that folder and all its sub-folder.

This htaccess contains the following lines:

.htaccess folder (www\test3\sub)
#=========== Test 3 Sub ===========
Options +FollowSymLinks
RewriteEngine On
RewriteBase /test3/sub/
RewriteRule sub_page2\.html sub_page7.php
RewriteRule sub_page3\.html sub_page8.php
RewriteRule sub_page4\.html sub_page9.php

The root htaccess is overwritten and contains the following lines:

.htaccess folder (www)
#==================== Test 3 Root ==================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule test3/main/main_page2\.html test3/main/main_page7.php
RewriteRule test3/main/main_page3\.html test3/main/main_page8.php
RewriteRule test3/main/main_page4\.html test3/main/main_page9.php

With the servers running type the following into your browser address bar: http://localhost/test3/main/main_page1.html and note the following:

  •  The main home page is displayed. Click the three bottom links in turn.
  •  Each of these links are re-written to serve a php page however the browser address bar displays the html page.
  •  All these rewrites are performed by the root htaccess file

Now type the following into your browser address bar: http://localhost/test3/sub/sub_page1.html and note the following:

  •  The sub home page is displayed. Click the three bottom links in turn.
  •  Each of these links are re-written to serve a php page however the browser address bar displays the html page.
  •  All these rewrites are performed by the sub folder htaccess file

Explanation

The root htaccess file requires no explanation however the sub folder’s htaccess file is more interesting.

RewriteBase

The RewriteBase is added to the beginning of the destination this pre-pending saves typing. For example these two htaccess files are identical in operation:

.htaccess folder (www\test3\sub)   .htaccess folder (www)
#=========== Test 3 Sub ===========
Options +FollowSymLinks
RewriteEngine On
RewriteBase /test3/sub/
RewriteRule sub_page2\.html sub_page7.php
RewriteRule sub_page3\.html sub_page8.php
RewriteRule sub_page4\.html sub_page9.php
  #================ Test 3 Sub ================
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteRule sub_page2\.html test3/sub/sub_page7.php
RewriteRule sub_page3\.html test3/sub/sub_page8.php
RewriteRule sub_page4\.html test3/sub/sub_page9.php

Regex

I mentioned the rewrite engine first chops off the host and the starting forward slash of any incoming requests. For example a request to the following page http://localhost/test3/sub/sub_page2.html would produce test3/sub/sub_page2.html this string is stored in the hidden variable.

If what I have said is true the following test string test3/sub/sub_page2\.html will match.

Edit sub htaccess as shown and run the above tests again:

.htaccess folder (www\test3\sub)
#================ Test 3 Sub ===============
Options +FollowSymLinks
RewriteEngine On
RewriteBase /test3/sub/
RewriteRule test3/sub/sub_page2\.html sub_page7.php
RewriteRule sub_page3\.html sub_page8.php
RewriteRule sub_page4\.html sub_page9.php

It clearly does not match because it produces 404 page not found error.

What gets chopped off is relative to the htaccess file; it’s the full path including the forward slash that leads to the location of htaccess, for example I have shown the path in bold:

http://localhost/test3/sub/.htaccess

hence for the above example this is what is stored in the hidden variable sub_page2.html

(I am looking for an exact match of the full string this is the reason I have not used the pre-defined regex characters ^ and $ to define the start and end of the string I will be covering these on the next page)

Summary

The above is not the best way to move or redirect pages it purpose to provide working examples allowing you to explore mod rewrite. I have illustrated several important points and concepts, the hidden variable that is taken for granted. What parts of the URL are removed and that the test string is a regex expression.

On the following pages these concepts are explored in more detail again I will provide working examples.

<< Mod Rewrite - Start :: Mode Rewrite 2 - Clean URLs >>

image top

• UniCenter Site Content Copyright © 2006-2008  Mike Gleaves  All Rights Reserved 25-1-2008 •

Copyright & Links

Copyright 2002-2007 The Uniform Server Development Team All rights reserved.

The Uniform Server: Home | Forum | Wiki | Blog