Date: Fri, 14 Apr 2000 13:46:50 -0700 (PDT) From: Greg Stein To: new-httpd@apache.org Subject: Re: I/O filtering in 2.0 In-Reply-To: Message-ID: 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/