This is driving me nuts.
Background: I'm using the built-in Apache2 & PHP that comes with Mac OS X 10.6
I have a vhost setup as follows:
NameVirtualHost *:81
<Directory "/Users/neezer/Sites/">
Options Indexes MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<VirtualHost *:81>
ServerName lobster.dev
ServerAlias *.lobster.dev
DocumentRoot /Users/neezer/Sites/lobster/www
RewriteEngine On
RewriteCond $1 !^(index\.php|resources|robots\.txt)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L,QSA]
LogLevel debug
ErrorLog /private/var/log/apache2/lobster_error
</VirtualHost>
This is in /private/etc/apache2/users/neezer.conf
.
My code in the lobster project
is PHP with the CodeIgniter framework. Trying to load http://lobster.dev:81/ gives me:
400 Bad Request
Normally, I'd go check my logs to see what caused it, yet my logs are empty! I looked in both /private/var/log/apache2/error_log
and /private/var/log/apache2/lobster_error
, and neither records ANY message relating to the 400. I have LogLevel
set to debug
in /private/etc/apache2/http.conf
.
Removing the rewrite rules gets rid of the error, but these same rules work on my MAMP host. I've double-checked and rewrite_module
is loaded in my default Apache installation. My http.conf
can be found here: https://gist.github.com/1057091
What gives? Let me know if you need any additional info.
NOTE: I do NOT want to add the rewrite rules to .htaccess
in the project directory (it's checked into a git repo and I don't want to touch it).
For complicated mod_rewrite rules, it's a good idea to log the sequence of events to see what's happening. Do this using RewriteLog, and crank up the RewriteLogLevel to see the details.
mod_rewrite is very flexible and one can do many things with the rewrite rules, and is also quite complicated. An outsider will have trouble debugging your rules without seeing the broader context. The best thing you can do debug it on your own. Watch the logs in one window while you experiment with configuration changes in a second window. Make a small change, save the file, reload apache and hit the URL again. Repeat.
Here's a good description of RewriteLog from the Apache manual:
Your substitution in
<virtualhost>
context uses a non-absolute URL. You can't do this outside of Directory/htaccess context.A few other notes, which became a bit too large to be contained in a mere comment:
RewriteCond $1
works, but it's quite dangerous and brittle. In particular, you could easily have rewritten the RewriteRule so as to disable the functionality of that RewriteCond altogether, and you'd never know you had. The use of%{REQUEST_URI}
is recommended as a solution, à laRewriteCond %{REQUEST_URI} ^/(index\.php|resources|robots\.txt)
.Next issue: these two lines:
are not functional as presented. They either need to be placed inside a
<Directory>
stanza, or modified to use the look-ahead macros (e.g.RewriteCond %{LA-U:REQUEST_FILENAME} !-f
).The actual cause of you needing to remove the
/
is that.htaccess
strips off the leading/
from the first argument of RewriteRule, whereas it's delivered with/
intact to RewriteRules in httpd.conf (or itsInclude
d files), which is something important to remember in case you ever try to move this rule back into a .htaccess. You can rework the Rule to be .htaccess/httpd.conf-agnostic by doing something likeRewriteRule ^/?(.*)$ index.php/$1 [L,QSA]
.One last note: as you can see in the rule, above, you don't need to escape the
/
with a backslash.