[BUG] "client_body_in_file_only on" no longer works with upstream modules in nginx 1.3.9+

Valentin V. Bartenev vbart at nginx.com
Mon Jan 28 17:06:43 UTC 2013


On Monday 28 January 2013 15:30:35 Maxim Dounin wrote:
> Hello!
> 
> On Sun, Jan 27, 2013 at 12:07:37AM -0800, agentzh wrote:
> > Hello!
> > 
> > I've noticed that for nginx 1.3.9+, "client_body_in_file_only on" no
> > longer always sets r->request_body->bufs, which makes upstream modules
> > like ngx_proxy send empty request bodies to the backend server.
> > 
> > Here's a minimal example that demonstrates the issue:
> >     location = /t {
> >     
> >         client_body_in_file_only on;
> >         proxy_pass http://127.0.0.1:1234;
> >     
> >     }
> > 
> > And run nc to listen on the local port 1234:
> >     $ nc -l 1234
> > 
> > Then issue a simple POST request to location = /t:
> >     $ curl -d 'hello world' localhost/t
> > 
> > When using nginx 1.3.9+, we get the raw HTTP request sent by ngx_proxy:
> >     $ nc -l 1234
> >     POST /t HTTP/1.0
> >     Host: 127.0.0.1:1234
> >     Connection: close
> >     Content-Length: 11
> >     User-Agent: curl/7.24.0 (x86_64-redhat-linux-gnu) libcurl/7.24.0 ...
> >     Accept: */*
> >     Content-Type: application/x-www-form-urlencoded
> > 
> > That is, when the request body is completely preread into the client
> > header buffer, the request body will only be hooked into
> > r->request_body->temp_file but not r->request_body->bufs.
> > 
> > But when the request body is big enough that it is not completely
> > preread into the client header buffer, then the a in-file buf will
> > still be properly inserted into r->request_body->bufs and we can get
> > the expected request body sent from ngx_proxy.
> 
> Thnx, the test for client_body_in_file_only actually checked file,
> so it wasn't noticed.  :)
> 
> The following patch should fix this:
> 
> # HG changeset patch
> # User Maxim Dounin <mdounin at mdounin.ru>
> # Date 1359372279 -14400
> # Node ID 1f6b73a7b7c9992d2e6853413a8f2c599c1e8ea8
> # Parent  153d131f0b7aa28fde12a94fd6a7e78a20743a3a
> Request body: fixed client_body_in_file_only.
> 
> Broken while introducing chunked request body reading support in 1.3.9.
> 

IMHO it's worth to specify that it was broken by r4931.

> diff --git a/src/http/ngx_http_request_body.c
> b/src/http/ngx_http_request_body.c --- a/src/http/ngx_http_request_body.c
> +++ b/src/http/ngx_http_request_body.c
> @@ -35,7 +35,8 @@ ngx_http_read_client_request_body(ngx_ht
>      size_t                     preread;
>      ssize_t                    size;
>      ngx_int_t                  rc;
> -    ngx_chain_t                out;
> +    ngx_buf_t                 *b;
> +    ngx_chain_t                out, *cl;
>      ngx_http_request_body_t   *rb;
>      ngx_http_core_loc_conf_t  *clcf;
> 
> @@ -128,6 +129,21 @@ ngx_http_read_client_request_body(ngx_ht
>                  rc = NGX_HTTP_INTERNAL_SERVER_ERROR;
>                  goto done;
>              }
> +
> +            cl = ngx_chain_get_free_buf(r->pool, &rb->free);
> +            if (cl == NULL) {
> +                return NGX_HTTP_INTERNAL_SERVER_ERROR;
> +            }
> +
> +            b = cl->buf;
> +
> +            ngx_memzero(b, sizeof(ngx_buf_t));
> +
> +            b->in_file = 1;
> +            b->file_last = rb->temp_file->file.offset;
> +            b->file = &rb->temp_file->file;
> +
> +            rb->bufs = cl;
>          }
> 
>          post_handler(r);

Looks good and works fine (according to your test).

  wbr, Valentin V. Bartenev

--
http://nginx.com/support.html
http://nginx.org/en/donation.html



More information about the nginx-devel mailing list