ossp-pkg/sio/BRAINSTORM/doc_greg_filters.txt
Date: Fri, 14 Apr 2000 13:46:50 -0700 (PDT)
From: Greg Stein <gstein@lyra.org>
To: new-httpd@apache.org
Subject: Re: I/O filtering in 2.0
In-Reply-To: <Pine.LNX.4.21.0004141156120.25805-100000@koj.rkbloom.net>
Message-ID: <Pine.LNX.4.10.10004141314030.13301-100000@nebula.lyra.org>
On Fri, 14 Apr 2000 rbb@covalent.net wrote:
> I am not calling this I/O Layering, because this is really output
> filtering. The patch I am submitting allows modules to edit data after a
> handler has finished with it. This is basically Greg's approach.
I'll detail my approach here, as your patch has some pieces, but it is
quite different.
All of this is obviously IMO...
*) we definitely want multiple output filters. each filter is recorded in
a linked list in the request_rec.
*) a filter has a name and is implemented by a module. this mapping is set
up similarly to handler maps in the 'module' structure.
*) output from normal modules is identical to today. they use ap_rputs,
ap_rwrite, etc. Filtering occurs under the covers.
*) Apache defines ap_lwrite(ap_layer *next_layer,
const void *buf, size_t len,
request_rec *r)
and possibly some similar ones for printf, puts, etc
*) struct ap_layer_s {
const char *layer_name;
layer_func_t *func;
struct ap_layer_s *next;
}
/* filters implement function with this type: */
typedef ap_status_t (*layer_func_t)(ap_layer *next_layer,
const void *buf, size_t len,
request_rec *r);
/* ### dunno about that return type */
/* looks remarkably similar to ap_lwrite(), eh? */
*) ap_status_t ap_lwrite(ap_layer *layer, const void *buf,
size_t len, request_rec *r)
{
if (layer == NULL) {
ap_bwrite(r->connection->client, buf, len, &amt);
return OK;
}
return (*layer->func)(layer->next, buf, len, r);
}
*) a new Apache directive can detail the sequence of filters and install
them into the request_rec.
*) ap_rwrite() and friends calls ap_lwrite(r->first_layer, ...). this will
perform actual output filtering, or go off to the BUFF stuff.
*) a new hook is added: install_filters. it is called right before
invoke_handlers and is responsible for setting r->first_layer and/or
elements along the list.
*) a new, small module can implement a directive which responds to
install_filters and sets up a sequence of filters based on their names.
for example:
SetFilters PHP SSI
*) content handlers (e.g. during invoke_handler processing) have a new
function to call: ap_set_content_type(r, const char *type). when the
type is changed, such as during CGI processing, this function is called
and an opportunity (somehow? haven't thought on this part) is provided
for new output layers to be inserted.
[ this provides for a CGI output'ing application/x-httpd-php3 ]
ap_set_content_type() should probably know where it is during the
request processing so that it can be used any time. maybe it should be
allowed to set up layers at any time?
That's it. :-)
Helper functions to set up a pipe and a sub-thread would be handy. That
would allow some modules to keep their "read from an fd" approach, rather
than switching to a stateful parser approach. As Dean stated before,
output filtering is necessarily asynchronous: a sub thread or a state
machine thingy is required.
[ flipping things around, you could say that the initial content can be
generated asynchronously (where the first filter demands the next chunk
of output). this would be incredibly difficult for things like
mod_autoindex. at some point, somebody is pulling content and shoving it
down the BUFF. the above form is "everybody shoves content" ]
Cheers,
-g
--
Greg Stein, http://www.lyra.org/