Properly serving a 404 with lighttpd’s server.error-handler-404


Posted

in

, , ,

The other day I was looking in to why Django‘s verify_exists validator wasn’t working on a URLField. It turns out that the 404 handler that we were using to generate thumbnails with lighttpd on the media server was serving up 404 error pages with HTTP/1.1 200 OK as the status code. Django’s validator was seeing the 200 OK and (rightfully) not raising a validation error, even though there was nothing at that location.

It took more than the usual amount of digging to find the solution to this, so I’m making sure to write about it so that I can google for it again when it happens to me next year. The server.error-hadler-404 documentation metnions that to send a 404 response you will need to use server.errorfile-prefix. That doesn’t help me a lot since I needed to retain the dynamic 404 handler.

Amusingly enough, the solution is quite clear once you dig in to the source code. I dug through connections.c and found that if I sent back a Status: line, that would be forwarded on by lighttpd to the client (exactly what I wanted!)

Here’s the solution (in Python) but it should translate to any language that you’re using as a 404 handler:

print "Status: 404"
print "Content-type: text/html"
print
print # (X)HTML error response goes here

I hope this helps, as I’m sure it will help me again some time in the future.

Comments

One response to “Properly serving a 404 with lighttpd’s server.error-handler-404”

  1. Thomas Flud Avatar
    Thomas Flud

    Nice Fix Matt, I ran into similar problems for most of my cgi on Dreamhost, and using the Status also fixed it..

    Check out: Force Apache to output any HTTP Status Code with ErrorDocument

    I setup an automated system to view all 57 Apache Response codes and ErrorDocuments, saving the headers and returned content for future reference. Use this page as a reference when designing scripts that use headers. Ex: 404 Not Found, 200 OK, 304 Not-Modified, 506 Service Temporarily Unavailable, etc.

    When a Status code is encountered, Apache serves the header and the ErrorDocument for the error code. So if you can see any Header and ErrorDocument by causing that error on Apache.

    For instance, if you request a file that doesn’t exist, a 404 Not Found is issued and the corresponding ErrorDocument is served with the 404 Not Found Header. So we can see what Apache 404 Errors and Response Codes look like, but how do we cause errors for the 56 other Apache Response Codes?