On 2014-10-16 22:35, Eric Johanson wrote:
Thank you for the suggestion. I did try that, but the order in which you
set f->r->status and call ap_pass_brigade doesn't seem to really make a
difference.
Basically what happens is that the browsers don't like the format of the
HTTP response packet. They complain that there is "extra unexpected data
after the end of the response." Oddly, when I use the Linux "wget" command,
it doesn't complain. I may just write a handler hook specifically for
returning error codes. Then when the filter modules has an error, it can
call ap_internal_redirect to a special page whose exclusive purpose is to be
captured by my error handler to return an HTTP status code.
Any other suggestions?
This "expected data" message may be caused by a response body that has a
different (bigger) length than what is announced in the Content-Length
output header.
If possible, try to not pass any data down the filter chain to the
network when you want to set a 503 error. Set f->r->status = 503 and
then pass a brigade that contains only an EOS bucket.
I don't know if it is possible to send an empty body with a correct
Content-Length (i.e. equal to zero) once your filter has already passed
some data down the filter chain.
I found some old code of mine that sends a 5xx code with an empty body
when it detects an error. However my filter buffers all the data sent by
a backend before it passes the filtered response in a single brigade
down the filter chain. I.e. my filter returns APR_SUCCESS without
invoking ap_pass_brigade whenever the brigade passed to my filter does
not contain an EOS bucket. When the brigade contains an EOS bucket my
filter passes the entire filtered response down the filter chain. So in
my case, no data has reached any downstream filters before I detect an
error.
// nominal part
...
// error-handling
request_rec *r = f->r;
r->status = HTTP_INTERNAL_SERVER_ERROR;
ap_remove_output_filter(f);
f->ctx = 0;
r->eos_sent = 0;
apr_table_t *tmp = r->headers_out;
ap_add_output_filter("error_filter", 0, r, r->connection);
r->headers_out = r->err_headers_out;
r->err_headers_out = tmp;
apr_table_clear(r->err_headers_out);
return ap_pass_brigade(r->output_filters, bb);
Apparently I remove the "useful" filter when I detect an error
(ap_remove_output_filter(f)) and I replace it with another filter
(ap_add_output_filter), that produces the error response. I suppose you
don't have to do this, I suppose that the effect can be achieved in the
same filter.
I do not really remember why I swap the error and output headers. I
suppose I clear the error headers in order to get rid of a previously
computed Content-Length header.
Also I do not remember why I reset the eos_sent flag, but I think this
is important.
And I'm quite surprised that I pass to the head of the output filter
chain (ap_pass_brigade(r->output_filters, bb) and not f->next).
I'm sorry that my explanations are incomplete, it's really an old code
and I do not remember the details. But it's still in production and does
what you want: it sends an empty-bodied response with a 5xx http status
code.
Sorin
Thanks, -Eric
-----Original Message-----
From: Sorin Manolache [mailto:sor...@gmail.com]
Sent: Thursday, October 16, 2014 12:59 PM
To: modules-dev@httpd.apache.org
Subject: Re: output filter needs to redirect to 503 error status
On 2014-10-16 15:36, Eric Johanson wrote:
Hi,
I have an output filter module which is working just fine, but I need
to add a feature so that when certain error conditions occur during
processing, the output filter hook function redirects the whole
request to a 503 error status (service unavailable). Obviously for a
"handler" module this is trivial to accomplish, but it is not clear
how to do this in an output filter module.
My output filter hooked function is defined as follows:
apr_status_t mts_out_filter(ap_filter_t *f,apr_bucket_brigade
*bb)
I need this function to "do something" that causes the whole request
to be redirected such that the client sees a 503 error status with no
body/content.
Things that I've tried so far:
* Returning HTTP_SERVICE_UNAVAILABLE from the output filter function
after calling "ap_pass_brigade(f->next,bb)"
* Setting f->r->status to HTTP_SERVICE_UNAVAILABLE after calling
"ap_pass_brigade(f->next,bb)"
Try setting f->r->status _before_ calling ap_pass_brigade.
If you get the 503 but you get the default 503 error response body that is
automatically set by apache then replace it by using the ErrorDocument
directive http://httpd.apache.org/docs/2.2/mod/core.html#errordocument (or
http://httpd.apache.org/docs/2.4/mod/core.html#errordocument).
Sorin
* calling "ap_send_error_response(f->r,HTTP_SERVICE_UNAVAILABLE)"
None of these really seem to behave properly. I just want the client
to receive a 503 error status with no content body. There must be a
way to achieve this behavior from within an output filter hook?
Any advice is appreciated.
Thanks, -Eric