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: Is it safe to stop reading a bucket brigade in an input filter before the end?
Date Sun, 19 May 2019 11:11:17 GMT
On 16/05/2019 00.26, Paul Callahan wrote:
> I have an apache body filter that copies off data from the incoming
> request.   But I terminate the reading of the data if the size of the
> accumulated data is over some limit.
> 
> This is my function, it just breaks  out of the loop when the max is read.
>   It seems to work ok.   Do I need to do any additional cleanup or anything
> because I did not go to the end?

Hello,

I suppose your code is ok.

Keep in mind that apache must clear the request body in order to be able 
to parse and serve a new request that arrives on same, reused TCP 
connection.

So towards the end of the processing of the current request, apache 
calls a function, I think it's called ap_discard_request_body. This 
function will read data from the network socket and pass it to the 
filter chain. So your input filter will be called again (unless you 
called ap_remove_input_filter somewhere), after you've already sent the 
response to the client.

Best regards,
Sorin


> 
> Thank you
> 
> // returns 0 after desired length is read
> int my_append_data(const char *data, apr_size_t len, void *request_ctx);
> void my_body_read_done(void *request_ctx);
> 
> apr_status_t my_body_input_filter(ap_filter_t *f, apr_bucket_brigade *out_bb,
>                                       ap_input_mode_t mode,
> apr_read_type_e block, apr_off_t nbytes,
>                                      void *request_ctx) {
>      request_rec *r = f->r;
>      conn_rec *c = r->connection;
> 
>      apr_bucket_brigade *tmp_bb;
>      int ret;
> 
>      tmp_bb = apr_brigade_create(r->pool, c->bucket_alloc);
>      if (APR_BRIGADE_EMPTY(tmp_bb)) {
>          ret = ap_get_brigade(f->next, tmp_bb, mode, block, nbytes);
> 
>          if (mode == AP_MODE_EATCRLF || ret != APR_SUCCESS)
>              return ret;
>      }
> 
>      while (!APR_BRIGADE_EMPTY(tmp_bb)) {
>          apr_bucket *in_bucket = APR_BRIGADE_FIRST(tmp_bb);
>          apr_bucket *out_bucket;
>          const char *data;
>          apr_size_t len;
> 
>          if (APR_BUCKET_IS_EOS(in_bucket)) {
>              APR_BUCKET_REMOVE(in_bucket);
>              APR_BRIGADE_INSERT_TAIL(out_bb, in_bucket);
>              my_body_read_done(request_ctx);
>              break;
>          }
> 
>          ret = apr_bucket_read(in_bucket, &data, &len, block);
>          if (ret != APR_SUCCESS) {
>              return ret;
>          }
> 
> 
>          // copy read data up to a limit of 1mb, then stop.
>          if (!my_append_data(data, len, request_ctx)) {
>              apr_bucket_delete(in_bucket);
>              break;
>          }
> 
>          out_bucket = apr_bucket_heap_create(data, len, 0, c->bucket_alloc);
>          APR_BRIGADE_INSERT_TAIL(out_bb, out_bucket);
>          apr_bucket_delete(in_bucket);
>      }
>      return APR_SUCCESS;
> }
> 


Mime
View raw message