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

<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

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).

  • You looked in the log of php? Jun 30 '11 at 22:01
  • I can't seem to even get my php log up. You can see my php.ini file here: gist.github.com/1057384
    – neezer
    Jun 30 '11 at 22:04
  • I think that you get this error, when write yourdomain.com ? What happens when you try to Referring to yourdomain.com/index.php ? Jun 30 '11 at 22:06
  • Same thing when trying anything on the site, even /index.php.
    – neezer
    Jun 30 '11 at 22:31

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:

Rewrite Log

When using the powerful and complex features of mod_rewrite, it is almost always necessary to use the RewriteLog to help in debugging. This log file produces a detailed analysis of how the rewriting engine transforms requests. The level of detail is controlled by the RewriteLogLevel directive.

  • 1
    Ok, it was trying to load index.php//index.php, and that was the issue. I've since change the rule to read RewriteRule ^\/(.*)$ index.php/$1 [L,QSA] at it works as expected. Thanks.
    – neezer
    Jun 30 '11 at 22:49

Your substitution in <virtualhost> context uses a non-absolute URL. You can't do this outside of Directory/htaccess context.

  • Thanks this was my issue: RewriteRule ~/(.+) something.php/$1 -> RewriteRule ~/(.+) /something.php/$1 fixed it
    – SeanDowney
    Feb 15 '17 at 17:40
  • that was it for me too. Moved things from directory context into general context and had to change the rewrite rule on both sides
    – Flion
    Feb 1 '21 at 23:11

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, à la RewriteCond %{REQUEST_URI} ^/(index\.php|resources|robots\.txt).

Next issue: these two lines:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

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 its Included 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 like RewriteRule ^/?(.*)$ 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.

  • +1 Thanks. I had just copy/pasted this in the heat of the moment, but I'll definitely go back and revisit these rules as you suggested.
    – neezer
    Jul 1 '11 at 3:15

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.