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: output filter needs to redirect to 503 error status
Date Thu, 16 Oct 2014 22:22:34 GMT
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:sorinm@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
>>
>>
>
>


Mime
View raw message