Reading body during the REWRITE phase ?

Maxim Dounin mdounin at mdounin.ru
Fri Jan 15 15:53:04 UTC 2016


Hello!

On Fri, Jan 15, 2016 at 03:01:06PM +0100, Thibault Koechlin wrote:

> Hi,
> 
> I have a module (naxsi) that reads the body during the REWRITE phase, in
> the exact same way that ngx_form_input does :
> https://github.com/calio/form-input-nginx-module.
> 
> When used with auth_request (or maybe other modules, but that's the
> first time I encounter this issue within a few years of usage), there is
> no request made to the upstream if the request is made using POST/PUT
> and the body is bigger than client_body_buffer_size.
> 
> For the simplicity of the example, we'll assume I'm talking about
> ngx_form_input (behaviour is the same, except code is way shorter).
> 
> The user reporting me the bug opened a ticket :
> https://trac.nginx.org/nginx/ticket/801. It is possible to replace naxsi
> with ngx_for_input and obtain the same results.
> 
> From Maxim's reply, it seems I failed to properly restore request
> handlers after reading body.
> 
> What would be (if there is any) the proper way to read body within
> REWRITE phase ? Is there any example/existing module that does such so I
> can understand what am I doing wrong ? (In the past, I always thought
> ngx_form_input was the reference one).

No modules in nginx itself attempt to read body before it knows 
it'll handle the request.  So I don't think there are examples of 
doing this correctly.

The problem as seen from debug logs is that reading body will 
reset request handlers, including r->write_event_handler, which is 
used to continue processing of request phases.  That is, as a 
minimum you'll have to do something like:

    r->write_event_handler = ngx_http_core_run_phases;
    ngx_http_core_run_phases(r);

when you restart processing of phases after the request body is 
read.  As of now your code seems to call ngx_http_core_run_phases() 
without restoring the r->write_event_handler.

Similar code can be seen in ngx_http_finalize_request() when 
processing of phases is restared after a content handler returned 
NGX_DECLINED, see src/http/ngx_http_request.c:

    if (rc == NGX_DECLINED) {
        r->content_handler = NULL;
        r->write_event_handler = ngx_http_core_run_phases;
        ngx_http_core_run_phases(r);
        return;
    }

Hope this helps.

-- 
Maxim Dounin
http://nginx.org/



More information about the nginx-devel mailing list