httpd-modules-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Sorin Manolache <sor...@gmail.com>
Subject Re: How to read data in a request handler and then return DECLINED without consuming the data in the bucket brigade?
Date Mon, 04 Jun 2018 07:55:44 GMT
On 2018-06-04 08:27, Paul Callahan wrote:
> In apache modules, my understanding is if a handler declines a request, the
> request is passed on to the next suitable handler.   I'm finding though if
> I read the bucket_brigade/request body, and then decline the request, the
> subsequent handler doesn't get any data.  It is like the act of reading the
> bucket brigade consumes it.
> 
> I would like to have a request handler read the data, do some task (in this
> case just count bytes), and decline the request without consuming the data
> for the next handler.

Hello,

As far as I know, there is no simple way to do that.

Other handlers do something similar to what you've done, namely they 
call ap_get_brigade(r->input_filters, ...).

So in order for them to still read something, you'll have to

* write an input filter
* in your handler you read the request body and store it somewhere
* afterwards in your handler you add your input filter to the chain of 
input filters (ap_add_input_filter)
* your handler declines.

Then other handlers will call ap_get_brigade which will call your input 
filter. Your input filter will not call any other filters but will copy 
the stored body to the brigade passed in the call to your filter. Your 
filter will give the illusion to other handlers that they are reading 
from the network.

HTH,
Sorin

> 
> Thank you.
> 
>      int my_declining_handler(request_rec *r) {
>          apr_status_t status;
>          int end = 0;
>          apr_size_t bytes, count = 0;
>          const char *buf;
>          apr_bucket *b;
>          apr_bucket_brigade *temp_brigade;
> 
>          // here: header check for content-length/transfer encoding
> 
>          temp_brigade = apr_brigade_create(r->pool,
> r->connection->bucket_alloc);
>          do {
>              status = ap_get_brigade(r->input_filters, temp_brigade,
> AP_MODE_READBYTES, APR_BLOCK_READ, BUFLEN);
>              if (status == APR_SUCCESS) {/* Loop over the contents of
> temp_brigade */
>                  for (b = APR_BRIGADE_FIRST(temp_brigade);
>                       b != APR_BRIGADE_SENTINEL(temp_brigade);
>                       b = APR_BUCKET_NEXT(b)) {
>                      if (APR_BUCKET_IS_EOS(b)) {
>                          end = 1;
>                          break;
>                      }
>                      else if (APR_BUCKET_IS_METADATA(b)) {
>                          continue;
>                      }
>                      bytes = BUFLEN;
>                      status = apr_bucket_read(b, &buf, &bytes,
>                                               APR_BLOCK_READ);
>                      count += bytes;
> 
>                      apr_bucket_delete(b);
>                  }
>              }
>              apr_brigade_cleanup(temp_brigade);
>          } while (!end && (status == APR_SUCCESS));
>          if (status == APR_SUCCESS) {
>              return DECLINED;
>          } else {
>              return HTTP_INTERNAL_SERVER_ERROR;
>          }
>      }
> 


Mime
View raw message