You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Graham Leggett <mi...@sharp.fm> on 2010/11/04 17:33:25 UTC

NULL handler, NULL input and output filters

Hi all,

On a number of occasions I've had to "cap" the input or output filter  
stacks with a NULL filter that either discards buckets, or returns an  
empty brigade in response to a read. I have always had to be careful  
to name these duplicated filters carefully so they don't clash with  
one another, even though they all do the same thing.

I now face the need for a NULL handler - a simple handler that returns  
an empty document, and that's it, because the real work was being done  
by another module adding a header to the response. Sure, I can create  
an empty file to fudge this, but in this particular case the URL is  
likely to be hit often, and performance matters for us.

These things look like things the server should do out the box, and be  
available to any module that may want them. They are also simple,  
small, and entirely configuration free.

Would such filters and the handler fit into the core, or would they go  
into something like mod_request, or mod_null? Ideally, I'd like the  
filters to go into the core, and have the handler go into mod_null.  
Thoughts?

This is an example of the filters and handler code:

/**
  * NULL filter: Soak up all attempts to write.
  */
static apr_status_t null_filter(ap_filter_t *f, apr_bucket_brigade  
*bb) {

     apr_brigade_cleanup(bb);

     return OK;
}

/**
  * Cap the input filter stack, returning nothing.
  */
static apr_status_t null_in_filter(ap_filter_t *f, apr_bucket_brigade  
*bb,
         ap_input_mode_t mode, apr_read_type_e block, apr_off_t  
readbytes) {
     apr_bucket *e;

     /* all the null filter does is insert an EOS, and then return  
success. */
     e = apr_bucket_eos_create(f->c->bucket_alloc);
     APR_BRIGADE_INSERT_TAIL(bb, e);

     return APR_SUCCESS;
}

/**
  * NULL handler, return an empty document.
  */
static int null_handler(request_rec *r) {
     conn_rec *c = r->connection;
     apr_bucket_brigade *bb;
     apr_bucket *e;
     int errstatus;
     apr_status_t status;

     ap_allow_standard_methods(r, MERGE_ALLOW, M_GET, M_OPTIONS,  
M_POST, -1);

     if ((errstatus = ap_discard_request_body(r)) != OK) {
         return errstatus;
     }

     if (r->method_number == M_GET || r->method_number == M_POST) {

         ap_set_content_length(r, 0);

         bb = apr_brigade_create(r->pool, c->bucket_alloc);

         e = apr_bucket_eos_create(c->bucket_alloc);
         APR_BRIGADE_INSERT_TAIL(bb, e);

         status = ap_pass_brigade(r->output_filters, bb);
         if (status == APR_SUCCESS
             || r->status != HTTP_OK
             || c->aborted) {
             return OK;
         }
         else {
             /* no way to know what type of error occurred */
             ap_log_rerror(APLOG_MARK, APLOG_DEBUG, status, r,
                           "null_handler: ap_pass_brigade returned %i",
                           status);
             return HTTP_INTERNAL_SERVER_ERROR;
         }
     }
     else {              /* unusual method (not GET or POST) */
         if (r->method_number == M_INVALID) {
             /* See if this looks like an undecrypted SSL handshake  
attempt.
              * It's safe to look a couple bytes into the_request if  
it exists, as it's
              * always allocated at least MIN_LINE_ALLOC (80) bytes.
              */
             if (r->the_request
                 && r->the_request[0] == 0x16
                 && (r->the_request[1] == 0x2 || r->the_request[1] ==  
0x3)) {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                               "Invalid method in request %s -  
possible attempt to establish SSL connection on non-SSL port", r- 
 >the_request);
             } else {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                               "Invalid method in request %s", r- 
 >the_request);
             }
             return HTTP_NOT_IMPLEMENTED;
         }

         if (r->method_number == M_OPTIONS) {
             return ap_send_http_options(r);
         }
         return HTTP_METHOD_NOT_ALLOWED;
     }

}

Regards,
Graham
--


RE: NULL handler, NULL input and output filters

Posted by "Plüm, Rüdiger, VF-Group" <ru...@vodafone.com>.
 

> -----Original Message-----
> From: Graham Leggett 
> Sent: Donnerstag, 4. November 2010 17:33
> To: dev@httpd.apache.org
> Subject: NULL handler, NULL input and output filters
> 
> Hi all,
> 
> On a number of occasions I've had to "cap" the input or 
> output filter  
> stacks with a NULL filter that either discards buckets, or 
> returns an  
> empty brigade in response to a read. I have always had to be careful  
> to name these duplicated filters carefully so they don't clash with  
> one another, even though they all do the same thing.
> 
> I now face the need for a NULL handler - a simple handler 
> that returns  
> an empty document, and that's it, because the real work was 
> being done  
> by another module adding a header to the response. Sure, I 
> can create  
> an empty file to fudge this, but in this particular case the URL is  
> likely to be hit often, and performance matters for us.
> 
> These things look like things the server should do out the 
> box, and be  
> available to any module that may want them. They are also simple,  
> small, and entirely configuration free.
> 
> Would such filters and the handler fit into the core, or 
> would they go  
> into something like mod_request, or mod_null? Ideally, I'd like the  
> filters to go into the core, and have the handler go into mod_null.  
> Thoughts?

I would like to see them all (filters and handler) in a new mod (e.g. mod_null).

Regards

Rüdiger