lighttpd patchday
When I started to write this article, I thought that I could publish a few more things. But most changes are part of my framework, so they would be pointless to be published particular, because they are not common usable and to generalize these changes it lacks on time.
Nevertheless, there are still a few changes, that may be useful.
mod_simple_vhost.c
I taught mod_simple_vhost a new config option, which allows to use the same document-root for domains with and without the leading www. Sure, you could use a symlink and allow symlink following by server.follow-symlink, but this new config option is more flexible even if it's not as clean as a permanent redirection. In my special case, I had to handle this redirection in the backend, and so I've added those few lines.
mod_accesslog.c
This patch is really small. It only offers the possebility to write unix timestamps instead of the RFC850 date fields to the access log. This is useful to analyse the time value of the record without parsing by strtotime() in PHP or something else that consumes a lot more time.
buffer.c
lighttpd's internal buffer datatype has different functions in order to write data into the char array behind the scenes. One of them is buffer_append_long() which is as the name suggests, a function to append an integer to the buffer by using the internal function LI_ltostr(). The patch changes the calculation a bit to be able to deliver the result faster. I've made quite a few benchmarks for this as I needed a similar function in another program. And this little change improves the performance by a few percent - why should we give it away?
stat_cache.c
lighttpd uses the caching purpose of splay trees to cache stat(2) calls for a second to reduce the lame hard drive access. The idea is good, but why should we cache only for a second? The patch allows us to set the TTL for our cache entry at compile time. On production systems, there are not so many file changes that we need to constantly invoke new stat(2) calls (Besides there are many file changes - but then it is generally advisable to turn stat-cache completely off).
settings.h
The patch for settings.h simply doubles the size of the constant BUFFER_MAX_REUSE_SIZE. This constant serves to set a limit to the buffer data type when it grows too much. I know only mod_accesslog which makes use of this upper limit to flush to the drive when the buffer is full. To speed this module up, we try to hold the stream a little longer in the memory and then write a larger chunk at all.
mod_fastcgi.c
mod_fastcgi is such a thing, that I've changed under the view of handling requests faster by interacting with my framework on a more optimized way. I don't want to post all changes, but rather the change of the X-Sendfile handling. I added the possebility, to optional add the file size to the header value after a comma:
X-Sendfile: /var/www/file.gif,3373
This is useful to save the stat(2) on the first run and even to save the stat-cache handling, when we already know the size. With this change, you give the maintenance entirely in the hands of the backend, which needs more sanity checks in the backend, but opens a few more capabilities, especially, when you want to truncate the file.
response.c
I think this patch is hard on the border of universality. Actually, the patch only changes the order of the response headers to enable a smoother running and to have an output that is more similar to the Apache response. I don't know if it was just an attempt to look a little different, but the patch enables a chance of obfuscation. The most dramatic change is, that the server will not check the presence of a Date and Server header, because this is not necessairy in the most cases and even it costs a lot of time. So the server will send these headers immediately even if they are sent by the backend or another module. Attention: These headers will be send twice in the worst case! For this reason, I do not assume that this patch gets into the stable tree, but I want to share the idea with you.
mod_rewrite.c
The config syntax of lighttpd's rewrite rules are more like associative arrays in PHP then the rewrite syntax of Apache webserver. Thus, a migration from Apache to lighttpd is not really trivial with a certain number of rules. Felt after the 10,000th rule I made a copying error, so that in simple terms the config looked like this:
url.rewrite-once = ( ... "^/foo" => "$0", "^/(.*)" => "/handler/$1$", ... )
At some point of lighttpd's development there was an optimization in the handling of the pattern, so that this config mistake triggers a segfault. My little patch closes the error.
mod_reshape.c
mod_reshape is not an official lighttpd module but a module developed by me, with the united capabilities of mod_rewrite, mod_dir, mod_redirect and mod_simple_vhost. Another benefit of this module is the virtual document root for backends, so that files processed by the backend - for example PHP - don't have to lie in the public document root. So you might never access a index.php file via the browser - except if there is accidentally a file with that name in the public document root.
But let's digg a little deeper. As I already said, the module unifies the behavior of a few other modules. So there is a optimized redirection strategy, to handle subdomains with two levels, handle leading www. (like the simple_vhost patch, but in mod_reshape it will redirected), handling trailing slashes, handling a virtual folder layout for search engine friendly URL's without regexes and internal handles all unknown domains with a configurable domain-handler. To give a few examples of the redirection engine:
example.com/abc -> www.example.com/abc/ sub.example.com/xxx/ -> [backend_handler] www.sub.example.com/xxx -> sub.example.com/xxx/ web2.0ig.de -> [domain_handler] www.example.com/abc/ -> [backend_handler]
I do not publish this module, because it's too specialized but if there are interested parties, I'll generalize it for a common use. To show you the "specialization" I want to share the new config options so that you can visualize what I meant:
reshape.root = "/srv/hidden" # hidden document root for the backend reshape.execute = "/index.php" # backend handler reshape.token = "example" # token to search in the domain

February 7th, 2010
server.stat-cache-engine = "fam"
??