You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by fi...@locus.apache.org on 2000/07/13 10:03:21 UTC

cvs commit: apache-2.0/src/lib/apr/buckets doc_greg_filters.txt

fielding    00/07/13 01:03:21

  Added:       src/lib/apr/buckets doc_greg_filters.txt
  Log:
  Record Greg's filter approach rationale.  This is probably
  documented in the code as well (or should be).
  
  Submitted by:	Greg Stein
  
  Revision  Changes    Path
  1.1                  apache-2.0/src/lib/apr/buckets/doc_greg_filters.txt
  
  Index: doc_greg_filters.txt
  ===================================================================
  Date: Fri, 14 Apr 2000 13:46:50 -0700 (PDT)
  From: Greg Stein <gs...@lyra.org>
  To: new-httpd@apache.org
  Subject: Re: I/O filtering in 2.0
  In-Reply-To: <Pi...@koj.rkbloom.net>
  Message-ID: <Pi...@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/