Mod rewrite
From Deep Thought
Contents |
Debugging mod_rewrite
You can debug mod_rewrite rule process by adding these commands to your httpd.conf file:
RewriteLog /usr/local/apache/logs/lcleveland_rewrite.log RewriteLogLevel 3
Tips & Tricks
Catch All Short Circuit
Rewrite rules in a .htaccess file often use a "catch all" when a website uses an all-inclusive application to run the site such as a Content Management System. In a recent study, we have found that performance can be increased by writing an exception to short circuit the catch-all rewriting at the top of the file.
In our very short rewrite ruleset the "catch all short circuit" is more than twice as efficient, showing a total of 22 v. 46 "processes" occurring internally on mod-rewrite.
See #Case Study 001 for an example of the "before the short circuit" analysis.
See #Case Study 002 for an example of an "after the short circuit" analysis.
Existing Files Short Circuit
As a follow up to the #Catch All Short Circuit Trick noted above, you can further reduce mod_rewrite processing by testing for the existence of a file or directory at the top of the rewrite rules. The added benefit is that after the catch-all page is rendered any URLs it references within the program, such as a directly referenced CSS file, are not required to run through the entire mod_rewrite ruleset.
In our very short rewrite ruleset the "preexisting file short circuit" is nearly three times as efficient when looking up an existing file, showing a total of 4 v. 11 "processes" occurring internally on mod-rewrite.
See #Case Study 003 for an example of the "before the short circuit" analysis.
See #Case Study 004 for an example of an "after the short circuit" analysis.
Case Studies
Case Study 001 : Before The Short Circuit
The .htaccess
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Exceptions
#
RewriteCond %{REQUEST_URI} eyore/thankyou(.*)$
RewriteRule eyore/thankyou(.*)$ wiki/index.php/Eyore_Installation_Instructions [L]
RewriteCond %{REQUEST_URI} ^sitemap\.(.*)$
RewriteRule sitemap\.(.*)$ libraries/sitemap.php?format=$1 [L,QSA]
# The Catch All
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?wij_redirect=$1 [L,QSA]
</IfModule>
The rewrite process for http://www.cybersprocket.com/the_crew
(3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'the_crew' (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-f' => matched (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-d' => matched (2) [per-dir /home/cyberspr/public_html/] rewrite the_crew -> index.php?wij_redirect=the_crew (3) split uri=index.php?wij_redirect=the_crew -> uri=index.php, args=wij_redirect=the_crew (3) [per-dir /home/cyberspr/public_html/] add per-dir prefix: index.php -> /home/cyberspr/public_html/index.php (2) [per-dir /home/cyberspr/public_html/] trying to replace prefix /home/cyberspr/public_html/ with / (5) strip matching prefix: /home/cyberspr/public_html/index.php -> index.php (4) add subst prefix: index.php -> /index.php (1) [per-dir /home/cyberspr/public_html/] internal redirect with /index.php [INTERNAL REDIRECT] (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'index.php' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'index.php' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'index.php' (4) RewriteCond: input='/home/cyberspr/public_html/index.php' pattern='!-f' => not-matched (1) [per-dir /home/cyberspr/public_html/] pass through /home/cyberspr/public_html/index.php (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'the_crew' (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-f' => matched (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-d' => matched (2) [per-dir /home/cyberspr/public_html/] rewrite the_crew -> index.php?wij_redirect=the_crew (3) split uri=index.php?wij_redirect=the_crew -> uri=index.php, args=wij_redirect=the_crew (3) [per-dir /home/cyberspr/public_html/] add per-dir prefix: index.php -> /home/cyberspr/public_html/index.php (2) [per-dir /home/cyberspr/public_html/] trying to replace prefix /home/cyberspr/public_html/ with / (5) strip matching prefix: /home/cyberspr/public_html/index.php -> index.php (4) add subst prefix: index.php -> /index.php (1) [per-dir /home/cyberspr/public_html/] internal redirect with /index.php [INTERNAL REDIRECT] (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'index.php' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'index.php' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'index.php' (4) RewriteCond: input='/home/cyberspr/public_html/index.php' pattern='!-f' => not-matched (1) [per-dir /home/cyberspr/public_html/] pass through /home/cyberspr/public_html/index.php
Case Study 002: After The Short Circuit
The .htaccess:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Short circuit the "catch all"
#
RewriteCond %{REQUEST_URI} ^/index.php(.*)
RewriteRule (.*) - [L]
# Exceptions
#
RewriteCond %{REQUEST_URI} eyore/thankyou(.*)$
RewriteRule eyore/thankyou(.*)$ wiki/index.php/Eyore_Installation_Instructions [L]
RewriteCond %{REQUEST_URI} ^sitemap\.(.*)$
RewriteRule sitemap\.(.*)$ libraries/sitemap.php?format=$1 [L,QSA]
# The Catch All
#
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?wij_redirect=$1 [L,QSA]
</IfModule>
The rewrite process:
(3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'the_crew' (4) RewriteCond: input='/the_crew' pattern='^/index.php(.*)' => not-matched (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'the_crew' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/the_crew -> the_crew (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'the_crew' (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-f' => matched (4) RewriteCond: input='/home/cyberspr/public_html/the_crew' pattern='!-d' => matched (2) [per-dir /home/cyberspr/public_html/] rewrite the_crew -> index.php?wij_redirect=the_crew (3) split uri=index.php?wij_redirect=the_crew -> uri=index.php, args=wij_redirect=the_crew (3) [per-dir /home/cyberspr/public_html/] add per-dir prefix: index.php -> /home/cyberspr/public_html/index.php (2) [per-dir /home/cyberspr/public_html/] trying to replace prefix /home/cyberspr/public_html/ with / (5) strip matching prefix: /home/cyberspr/public_html/index.php -> index.php (4) add subst prefix: index.php -> /index.php (1) [per-dir /home/cyberspr/public_html/] internal redirect with /index.php [INTERNAL REDIRECT] (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/index.php -> index.php (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'index.php' (4) RewriteCond: input='/index.php' pattern='^/index.php(.*)' => matched (1) [per-dir /home/cyberspr/public_html/] pass through /home/cyberspr/public_html/index.php
Case Study 003: Before File/Directory Short Circuit
URL:http://cybersprocket.com/unauthorized.html
.htaccess file:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_URI} ^/index.php(.*)
RewriteRule (.*) - [L]
RewriteCond %{REQUEST_URI} eyore/thankyou(.*)$
RewriteRule eyore/thankyou(.*)$ wiki/index.php/Eyore_Installation_Instructions [L]
RewriteCond %{REQUEST_URI} ^sitemap\.(.*)$
RewriteRule sitemap\.(.*)$ libraries/sitemap.php?format=$1 [L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?wij_redirect=$1 [L,QSA]
</IfModule>
Rewrite Log:
(3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/unauthorized.html -> unauthorized.html (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'unauthorized.html' (4) RewriteCond: input='/unauthorized.html' pattern='^/index.php(.*)' => not-matched (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/unauthorized.html -> unauthorized.html (3) [per-dir /home/cyberspr/public_html/] applying pattern 'eyore/thankyou(.*)$' to uri 'unauthorized.html' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/unauthorized.html -> unauthorized.html (3) [per-dir /home/cyberspr/public_html/] applying pattern 'sitemap\.(.*)$' to uri 'unauthorized.html' (3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/unauthorized.html -> unauthorized.html (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'unauthorized.html' (4) RewriteCond: input='/home/cyberspr/public_html/unauthorized.html' pattern='!-f' => not-matched (1) [per-dir /home/cyberspr/public_html/] pass through /home/cyberspr/public_html/unauthorized.html
Case Study 004: After File/Directory Short Circuit
URL:http://cybersprocket.com/unauthorized.html
.htaccess:
Options -Indexes
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# If we are requesting a real file/directory
# we are done
#
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) - [L]
# Exceptions to catch-all
#
RewriteCond %{REQUEST_URI} eyore/thankyou(.*)$
RewriteRule eyore/thankyou(.*)$ wiki/index.php/Eyore_Installation_Instructions [L]
RewriteCond %{REQUEST_URI} ^sitemap\.(.*)$
RewriteRule sitemap\.(.*)$ libraries/sitemap.php?format=$1 [L,QSA]
# Catch-all
#
RewriteRule (.*) index.php?wij_redirect=$1 [L,QSA]
</IfModule>
Rewrite Log:
(3) [per-dir /home/cyberspr/public_html/] strip per-dir prefix: /home/cyberspr/public_html/unauthorized.html -> unauthorized.html (3) [per-dir /home/cyberspr/public_html/] applying pattern '(.*)' to uri 'unauthorized.html' (4) RewriteCond: input='/home/cyberspr/public_html/unauthorized.html' pattern='-f' => matched (1) [per-dir /home/cyberspr/public_html/] pass through /home/cyberspr/public_html/unauthorized.html
Issues Preventing Running of Mod_rewrite
We were having a problem with the site for a particular client, whose server is running Apache 2 on Ubuntu 6.06.2. While rewriting rules had been set in the .htaccess file, the rules were not being used. We found a 4 part solution to allow the .htaccess file to work.
1. Mod_rewrite does not have to be hard linked in Apache 2, rather it can be loaded on demanded. To enable this, set a link to the module:
$sudo a2enmod Which module would you like to enable? Your choices are: actions asis auth_anon auth_dbm auth_digest auth_ldap cache cern_meta cgid cgi dav_fs dav deflate disk_cache expires ext_filter file_cache headers imap include info ldap mem_cache mime_magic php5 proxy_connect proxy_ftp proxy_http proxy rewrite speling ssl suexec unique_id userdir usertrack vhost_alias Module name? mime_magic Module mime_magic installed; run /etc/init.d/apache2 force-reload to enable.
2. Edit /etc/apache2/sites-available/apache2.conf to set AllowOverride to FileInfo:
<Directory /var/www/anchor> Options Indexes FollowSymLinks MultiViews AllowOverride FileInfo UseCanonicalName Off Order allow,deny allow from all # Uncomment this directive is you want to see apache2's # default start page (in /apache2-default) when you go to / #RedirectMatch ^/$ /apache2-default/ </Directory>
3. Comment out the IfModule statements in the .htaccess file:
#<IfModule mod_rewrite.c>
ErrorDocument 404 ./ouch.html
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule (.*) - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) index.php?wij_redirect=$1 [L,QSA]
#</IfModule>
4. Restart Apache.
