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