Alyda

Just a Girl Weblog

Remembering Who I Really Am

mod_rewrite—Proof That God Exists

...and she has a Wicked Sense of Humor

Perhaps the most common use of mod_rewrite is to make URLs easier to type, easier to remember, and easier to tell someone over the phone. This can be accomplished very simply with a single RewriteRule. mod_rewrite isn't hard at all. Regular expressions appear—at first glance—to be diabolically difficult.

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Jamie Zawinski

mod_rewrite is built on top of the Perl Compatible Regular Expression (PCRE) vocabulary, and a basic grasp of regular expressions is essential when you compose your RewriteRule(s). Or you could spend a day and a half copying blindly—as I did—with literally no comprehension of the regex vocabulary.

  • <IfModule mod_rewrite.c>
  • # Set the name of the file used for logging
  • RewriteLog "/private/var/log/apache2/rewrite.log"
  • # Set the verbosity of the log file
  • # Remember to comment out when done debugging or set to 0
  • RewriteLogLevel 6
  • # Enable runtime rewriting engine
  • RewriteEngine On
  • # Define rule(s) for the rewriting engine
  • # Syntax: RewriteRule Pattern Substitution [Flags]
  • RewriteRule ^/gallery/(.*) /gallery.php?gal=$1 [NC,L]
  • </IfModule>

In hindsight, there were sevaral things I could have done to save a lot of time.

First: Absolute vs Relative Paths

If you're not targeting the default document set in the DirectoryIndex Directive (usually index[.php\.html]), you must use absolute paths to css, js, and image files (etc.) in your PHP/HTML document.

  • <!-- use '/css/' -->
  • <link rel="stylesheet" href="/css/gallery.css">
  • <!-- not 'css/' -->
  • <link rel="stylesheet" href="css/gallery.css">

If your images and stylesheets don't load but everything else seems fine, the path is likely your problem. For example:

  • incoming URL
  • justagirl.us/gallery/tour2013/
  • pattern match
  • /gallery/tour2013/
  • substitution
  • /gallery.php?gal=tour2013
  •  
  • if the path to your css file is relative, you'll also see something like this
  • pattern match
  • /gallery/tour2013/css/gallery.css
  • substitution
  • /gallery.php?gal=tour2013/css/gallery.css

Second: Context

What is the context (server config, virtual host, directory, .htaccess)? See 'What is matched?' in the RewriteRule Directive section of the mod_rewrite reference documentation. On my local machine the context is VirtualHost. In most of the examples I found (and copied) the context was Directory or .htaccess.

  • # context is VirtualHost, note slash preceeding '/gallery'
  • RewriteRule ^/gallery/(.*) /gallery.php?gal=$1 [NC,L]
  • # context is Directory, note absence of slash preceeding 'gallery'
  • RewriteRule ^gallery/(.*) gallery.php?gal=$1 [NC,L]

Third: Pattern, Substitution and Flags

Syntax of the RewriteRule directive
Syntax of the RewriteRule directive

Pattern

The pattern is a regular expression specifying which incoming URLs should be affected by the rule.

Regular Expression Vocabulary

 ^  Called an anchor, matches the beginning of the string
( ) Groups several characters into a single unit, and captures a match for use in a backreference
 .  Matches any single character
 *  Repeats the previous match zero or more times

Substitution

The substitution can contain backreferences to parts of the incoming URL‑path matched by the pattern. The value of the backreference is captured in a special variable, $1. Note: When using RewriteRule, the variables are prefixed with a dollar sign ($), but when using RewriteCond, they are prefixed with a percent sign (%).

Flags

Adding the No Case, or [NC], flag to any RewriteRule makes that rule case insensitive. The Last, or [L], flag indicates that the end of the rewriting process has been reached, and no further transitions should be applied to the requested URL.

Explanation of Solution

  • # incoming URL: justagirl.us/gallery/tour2013/
  • # RewriteRule: context is VirtualHost
  • RewriteRule ^/gallery/(.*) /gallery.php?gal=$1 [NC,L]

Pattern: ^/gallery/(.*)
Match a string that begins with /gallery/. Capture everything after /gallery/ and group it into a single unit (.*) for use as a backreference.

Substitution: /gallery.php?gal=$1
Anything appearing after /gallery/ as captured in the backreference $1 will be given as a query string argument ?gal= to gallery.php. Rewritten URL is justagirl.us/gallery.php?gal=tour2013

Flags: [NC,L]
Case-insensitive (NC) pattern matching will be slightly slower. The default behavior of the RewriteRule directive is to be case sensitive. The L flag is only useful when several rules are chained together in a single logical unit. It's good form to use this flag even when just a single rule is used; it's more of a reminder for you than for mod_rewrite.

Remember to restart Apache after making a change to the configuration file. On my local machine, the instruction is sudo apachectl restart. On the server I usually use sudo apachectl -k graceful.

Please…Take my Advice; I Rarely use It.

A little reading from the list below may result in a sudden, intuitive perception of, or insight into, the essential meaning of regular expressions. Yup, magic. From muggle to witch/wizard.

Where to Go for More Information

Filed under: , , , ,