Filtering I/O in Apache 2.0: Part 2 Page 2

By Ryan Bloom (Send Email)
Posted Oct 23, 2000


typedef struct hf_struct {
    int state;
} hf_struct; 

The only field in this structure is a state field. This tells our filter if it has already sent the configured headers or not. This filter is likely to be called multiple times for a single request, so we want to be sure that we don't send headers on any call other than the first call. The footers are managed completely differetly, but we will see that later. Most filters will also need a bucket_brigade in this structure if they want to save any of the data they are passed for use in later calls. In our case, this filter is a simple pass-through. Any data we are passed is passed on to the next filter without any modifications.

The next step declares the filter and some variables that we are going to need:


static int hf_filter(ap_filter_t *f, ap_bucket_brigade *bb)
{
    hf_struct *ctx = f->ctx;
    header_footer_rec *conf;
    ap_bucket *e;
    conf = (header_footer_rec *) ap_get_module_config(f->r->per_dir_config,
                                                      &hf_module);
 
    if (ctx == NULL) {
        f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
    }                                                                              

The first variable is an instance of the filter's ctx structure that we just defined. This is value is always stored in f->ctx, so we start by finding the ctx pointer from the previous call to this filter. If we have never been called before this field will be NULL and we will have to allocate memory for this structure. This is what we are doing in the last three lines of this section. The conf variable is the module specific configuration for this request. This is where we have stored the name of the header and footer files as well as the configured header and footer text. We will use this structure when we determine what to send. Finally, the variable e is a pointer to a bucket. Remember from last month that all of the data is stored in buckets. We will use this variable to create the text buckets to pass to the next filter, and to examine the data that we are sent.

The next step is to send the header information on the first call to this filter:

    if (ctx->state == 0) {
        ctx->state = 1;
        if (conf->headerf) {
            request_rec *rr;
 
            rr = ap_sub_req_lookup_uri(conf->headerf, f->r);
            if (rr->status == HTTP_OK) {
                ap_run_sub_req(rr);
            }
        }
        if (conf->headert) {
            e = ap_bucket_create_immortal(conf->headert, strlen(conf->headert));
            AP_BRIGADE_INSERT_HEAD(bb, e);
        }
    }                                                                              

The first if statement checks to ensure that we haven't already sent the headers. If we haven't already sent them, then we need to find the information to send and send it. If it is a file, then we want to use a sub-request. This takes advantage of Apache's request processing to send the file for us. This file will also be filtered if any filters are configured for it. The best way to think of a sub-request in Apache, is that it is the same as requesting the file through a browser. The ap_run_sub_req function will actually send the file to the client, so once we have called this function we do not need to do anything else to finish this portion of the request.

Page 2 of 4


Comment and Contribute

Your name/nickname

Your email

(Maximum characters: 1200). You have characters left.