7

Here is an example from the Apache documentation for enforcing canonical hostnames:

RewriteCond %{HTTP_HOST} !^www\.example\.com [NC]
RewriteCond %{HTTP_HOST} !^$
RewriteRule ^/?(.*) http://www.example.com/$1 [L,R,NE]

What I would like to know is why the /? is needed. I've tried removing it and everything appears to work the same. I was under the impression that the pattern part of the rewrite rule was compared against what comes after the slash.

4

The {REQUEST_URI} string starts with a / character. Apache changed regex engines when it changed versions, so Apache version 1 requires the leading slash while Apache 2 forbids it! We can satisfy both versions by making the leading slash optional with the expression ^/? (? is the metacharacter for zero or one of the preceding character).

Source: http://www.sitepoint.com/apache-mod_rewrite-examples/

A few more resources which talk about the leading slash

http://forum.modrewrite.com/viewtopic.php?f=4&t=4627

and http://net.tutsplus.com/tutorials/other/a-deeper-look-at-mod_rewrite-for-apache/

  • But the Apache 2.2 documentation has multiple examples with a leading ^/ . E.g. the RewriteCond section has: RewriteRule ^/$ /homepage.std.html [L]. Is that a documentation bug? – Matthew Flaschen May 2 '14 at 2:36
  • It turns out (as I just tested) that the leading / (^/) is required, at least in VirtualHost context. I did not test other contexts. – Matthew Flaschen May 2 '14 at 2:56
5

I recently happened across this issue myself. There is a difference between using RewriteRule in the VirtualHost and as part of an .htaccess file. The following rule will match (with a URL like this: example.com/fruit/apple) if it appears in a .htaccess file:

RewriteRule ^(fruit|fruits)/apple http://newfruitwebsite.com$1 [R=301,L]

but will not match in the VirtualHost context. If we check out the apache docs we can see that:

When using the rewrite engine in .htaccess files the per-directory prefix is automatically removed for the RewriteRule pattern matching and automatically added after any relative (not starting with a slash or protocol name) substitution encounters the end of a rule set.

...but what does this mean? The above rule would not match the same URL if it was placed into the VirtualHost because it doesn't allow a leading slash (/) to be at the start of the string. The apache docs go on to say:

The removed prefix always ends with a slash, meaning the matching occurs against a string which never has a leading slash. Therefore, a Pattern with ^/ never matches in per-directory context.

...so if we need a slash for .htaccess and no slash for VirtualHost, how do we modify the pattern? You guessed it. We need to add /? to add the following condition in our regex (where our question mark (?) is the quantifier):

  • Has between 0 and 1 / at the beginning of the string.

Now our URL (example.com/fruit/apple) string will match because we are handling the fact that if the rule is in the .htaccess file it will have 0 slashes and if it comes from the virtualHost it will have 1 slashes.


Related Reading:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.