request_rec.unparsed_uri missing scheme and host. parsed_uri missing most fields

2019-05-14 Thread Paul Callahan
Hello,
I'm having trouble getting the full uri of a request from request_rec.
 The comment string for request_rec.unparsed_uri makes it sound like it
should have the entire url, e.g. http:://hostname/path?etc.

But it only has the path and the query parameters.

The parsed_uri struct is populated with port, path and query paramters.
 Everything else (scheme, hostname, username, password, etc) is null.

I set a breakpoint in "apr_uri_parse()" and verified the incoming *uri
field only has the path and query parameters.

Is this expected?How can I get the full URI?

Thanks


Re: How to read data in a request handler and then return DECLINED without consuming the data in the bucket brigade?

2018-06-04 Thread Paul Callahan
Thank you for your replies.

I did try with input filters.  The reason I'm trying to do this in a
handler is because I want to return 403 to the browser if the request body
has something unsavory in it.   With reverse proxied requests, it appears
the input filter fires too late and if I try to send a bucket with 403 in
it, it is ignored and a 400 goes back to the browser.   In the debugger, I
see the fixup call back being hit before my input filter.   If I could get
the input filter to trip sooner without consuming the request, I could go
with that.  If I call ap_get_brigade() in an earlier handler to trip the
input filter, it appears the request body is consumed.


btw, Nick I bought your book - it was a great help :)

On Mon, Jun 4, 2018 at 2:12 AM, Nick Kew  wrote:

>
> > On 4 Jun 2018, at 08:55, Sorin Manolache  wrote:
> >
> > 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.
>
> Why is that a handler?  An input filter could count the data and pass them
> straight down the chain, avoiding any such problem.  At a glance, your code
> would need very little modification to work as a filter.
>
> Exhortation: work with the server architecture, not against it!
>
> > Hello,
> >
> > As far as I know, there is no simple way to do that.
>
> This is true, in the sense that data get consumed.  To do otherwise would
> be
> monstrously inefficient, and turn a big request body straight into a DoS.
>
> This is why we have mod_request.  It provides an input filter you can use
> explicitly to buffer data which then remain available to the next module
> to read them.
> Use with caution: for example, if you fail to limit request size, you
> could find
> yourself trying to buffer gigabytes of request data.
>
>
> >> } while (!end && (status == APR_SUCCESS));
> >> if (status == APR_SUCCESS) {
> >> return DECLINED;
> >> } else {
> >> return HTTP_INTERNAL_SERVER_ERROR;
> >> }
> >> }
>
> Minor tip there: you're turning EAGAIN into a fatal error.
>
> --
> Nick Kew


How to read data in a request handler and then return DECLINED without consuming the data in the bucket brigade?

2018-06-04 Thread Paul Callahan
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.

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