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;
}
}