Your Daily Source for Apache News and Information  
Breaking News Preferences Contribute Triggers Link Us Search About
Filtering I/O in Apache 2.0
(Sep 20th, 16:26:33 )

By Ryan Bloom

One of the holy grails of the Apache developers has always been filtered or layered I/O, the ability for one module to modify the data that was generated by an earlier module. This ability was originally slated for inclusion in Apache 2.0, but when work began in earnest on 2.0, this feature was pushed aside, and marked for inclusion in 2.1 or 3.0. Two months ago however, the Apache developers had a small meeting, and designed filtered I/O for Apache 2.0. The work has been started, and there have been some filters written. Over the next few months, I will explain how this feature works, and how your modules can take advantage of it.

The general premise of the filtered I/O design in Apache 2.0 is that all data served by a web server can be broken into chunks. Each chunk of data comes from the same place either a file, a CGI program, or it is generated by a module. We also knew that all of the data could always be represented as a string of characters, although that string may not be human-readable. Armed with that knowledge, we sat down to design the filtering system. One of our overriding goals, was that the filtering logic needed to be performance aware. It didn't matter if filters chose to ignore performance issues, but it did matter if the design hindered filters from knowing about performance issues. This meant that we needed to know more about that data than just what the data was, we also needed to know where the data comes from, and what it's lifetime is.

This meta-data is important when actually writing the response to the network. For example, if we have a very simple request that is just a page from disk, then we want to use sendfile (sendfile is provided by APR, and is available on all platforms, it the platform doesn't have a native sendfile, then APR loops reading the file and writing to the network.) If we take this example a step further, and make the whole response an SSI page, where one element is a file from disk, and the rest is generated, such as date strings, then we want to use a single sendfile call if possible. APR's sendfile provides an opportunity to include both header and trailer information with the file, which are sent using writev. In this example, we can send the HTTP headers, the full file, and the date string with one APR call (The number of system calls will differ depending on platform). Keeping the meta-data accessable is obviously a good idea.

In order to keep the meta-data available, the Apache developers needed to find some way to pass everything from one filter to the next. The data structure that was designed to do this is being called a bucket_brigade. Each bucket brigade is composed of multiple buckets. The buckets contain the data that we are sending to the client. And the type of bucket used makes up the meta-data.

Currently, we have a small number of bucket types, but the bucket API was designed to be extendable. The current bucket types are:

All buckets include pointers to their accessor functions. The details of what these functions do is specific to each bucket type, but we can explain them generally.

There are just a few more concepts that we need to cover in this overview of filtering. The first is registering a filter with the server. This is done with ap_register_filter.

void ap_register_filter(const char *name, ap_filter_func filter_func, ap_filter_type ftype);

The first argument is a name for the filter. This name is used throughout the server to reference that filter fuction. The second is the filter function we are registering. The final argument is the type of filter. There are currently two filter types, content and connection. Content filters are any filter that modifies the data being sent. Connection filters refer to filters that dictate how the data is sent over the network. For example, a SSI filter is a content filter while an SSL filter is a connection filter.

Once the filter has been registered, it must be added to the current request's filter stack before it will actually be called. This is done by calling ap_add_filter.

void ap_add_filter(const char *name, void *ctx, request_rec *r);

The first argument is the name of the filter to add. This should be the name that was registered for the desired filter. The second is a pointer to a structure that should be passed to the filter whenever it is called. This provides with a location to store any data that they may need to save between calls. The final argument is the request_rec to pass to the filter when it is called.

There are two more functions prototypes that must be discussed. The first is the prototype for filters themselves.

apr_status_t ap_filter_func(ap_filter_t *f, ap_bucket_brigade *b);

The first argument is a pointer to the current filter structure. This is where the ctx passed to ap_add_filter is stored, as well as a pointer to the next filter on the stack. The second is the current bucket brigade to filter.

The second function is ap_pass_brigade. This function passes bucket brigades from the current filter to the next filter. The prototype is:

apr_status_t ap_pass_brigade(ap_filter_t *filter, ap_bucket_brigade *bucket);

The first argument is a pointer to the next filter to call, and the second is the bucket brigade to pass to that filter.

That covers all of the basic concepts for writing filters. In next month's article we will actually write a filter that can be inserted into an Apache 2.0 server.

Related Stories:
Apache 2.0 Server Up and Running(Aug 19, 2000)
Apache 2.0alpha6 Released(Aug 19, 2000)
Apache 2.0alpha5 Released(Aug 05, 2000)
Building and Installing Apache 2.0(Jul 26, 2000)
ApacheWeek: Issue 206 7th July 2000(Jul 07, 2000)
Looking at Apache 2.0 Alpha 4 (Jun 30, 2000)
Apache 2.0 Alpha 4 Released(Jun 07, 2000)
An Introduction to Apache 2.0(May 28, 2000)

Printed from Apache Today (

About Triggers Media Kit Security Triggers Login

All times are recorded in UTC.
Linux is a trademark of Linus Torvalds.
Powered by Linux 2.4, Apache 1.3, and PHP 4
Copyright 2002 INT Media Group, Incorporated All Rights Reserved.
Legal Notices,  Licensing, Reprints, & Permissions,  Privacy Policy.