Apache does not log HTTP status set with PHP header when using mod_rewrite in .htaccess files
Posted April 5th, 2009 in Apache and PHP (Updated April 6th, 2009)
I discovered something rather annoying the other day relating to setting HTTP response codes with PHP's header() function, Apache's mod_rewrite and associated webserver logging. If anyone knows of a solution to the issue I have discovered below I'd love to know it.
A regular PHP script
If you use header() to make the page a 404 using PHP like so:
header("HTTP/1.0 404 Not Found");
then requesting the web page should result in a 404 which is logged in Apache as such.
In the following example a request is made using the lynx command line web browser for the log.php script and a 404 results. This is logged correctly in the Apache log file where I have highlighted the 404 response code in red.
Lynx command:
lynx -head -dump http://www.testing.local/log.php
Lynx Output
HTTP/1.0 404 Not Found Date: Fri, 03 Apr 2009 00:09:20 GMT Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch X-Powered-By: PHP/5.2.6-1+lenny2 Vary: Accept-Encoding Connection: close Content-Type: text/html
Apache Log Line:
192.168.1.15 - - [03/Apr/2009:13:09:20 +1300] "HEAD /log.php HTTP/1.0" 404 - "-" "Lynx/2.8.7dev.9 libwww-FM/2.14 SSL-MM/1.4.1"
Using mod_rewrite in the Apache config
The second example has a rewrite rule in the Apache config to rewrite /log to /log.php. Again this works as expected, logging a 404 to the Apache log file.
Rewrite rule
The following rewrite rule is what I used when writing this post. This is in the Apache config in a <virtualhost> block.
RewriteEngine On RewriteRule ^/log$ /log.php
Lynx command
lynx -head -dump http://www.testing.local/log
Lynx Output
HTTP/1.0 404 Not Found Date: Fri, 03 Apr 2009 00:10:44 GMT Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch X-Powered-By: PHP/5.2.6-1+lenny2 Vary: Accept-Encoding Connection: close Content-Type: text/html
Apache Log Line
192.168.1.15 - - [03/Apr/2009:13:10:44 +1300] "HEAD /log HTTP/1.0" 404 - "-" "Lynx/2.8.7dev.9 libwww-FM/2.14 SSL-MM/1.4.1"
Using mod_rewrite in .htaccess
However, if the rewrite rule is done in an .htaccess file then it doesn't log the request as a 404 but instead as a regular 200. This means any stats software you run (such as AWStats) won't show the request a a file not found.
Rewrite rule:
This is the rewrite rule in the .htaccess file used for writing this post, although the error (not writing the correct error code out to the Apache log file) occured for any rewrite rule where I was remapping URLs to a PHP script:
RewriteEngine On RewriteRule ^log$ /log.php
Another example from a production website:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule !\.(css|gif|ico|jpg|js|php|png|swf|txt)$ index.php
Lynx Command:
lynx -head -dump http://www.testing.local/log
Lynx Output:
HTTP/1.0 404 Not Found Date: Fri, 03 Apr 2009 00:08:38 GMT Server: Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny2 with Suhosin-Patch X-Powered-By: PHP/5.2.6-1+lenny2 Vary: Accept-Encoding Connection: close Content-Type: text/html
Apache Log Line:
192.168.1.15 - - [03/Apr/2009:13:08:38 +1300] "HEAD /log HTTP/1.0" 200 - "-" "Lynx/2.8.7dev.9 libwww-FM/2.14 SSL-MM/1.4.1"
Conclusion
In each instance the request is reported by the web server to the web browser as a 404, which can clearly be seen from the output from the Lynx command. However, when doing a PHP header() as a 404 (or 301, 302, 410 etc) with a rewrite rule in an .htaccess file it's not actually logged in the Apache log file as such, whereas it is when it's a regular PHP script or the rewrite rule is in the Apache config.
This is a bit of a nuisance and means if you can't put the rewrite rules into the main Apache config then you'll need to log the 404s yourself if you need to keep track of them.
If anyone knows of a way to make sure they are logged correctly when using mod rewrite and .htaccess then I'd love to know and can update this post accordingly.
Related posts:
- Set the content encoding type with PHP headers (Saturday, December 13th 2008)
- 404 Page not found with PHP (Wednesday, October 29th 2008)
- 303 redirect with PHP (Thursday, July 31st 2008)
- Image headers with PHP (Tuesday, July 22nd 2008)
- 301 redirect with PHP (Saturday, March 15th 2008)

Comments
blog comments powered by Disqus