httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Graham Leggett <>
Subject NULL handler, NULL input and output filters
Date Thu, 04 Nov 2010 16:33:25 GMT
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.  

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) {


     return OK;

  * Cap the input filter stack, returning nothing.
static apr_status_t null_in_filter(ap_filter_t *f, apr_bucket_brigade  
         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);

     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",
             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  
              * 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- 
             } else {
                 ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
                               "Invalid method in request %s", r- 
             return HTTP_NOT_IMPLEMENTED;

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



View raw message