[njs] HTTP: reading r.requestText or r.requestBuffer from a temp file.

Sergey A. Osokin osa at freebsd.org.ru
Sun Feb 2 14:50:02 UTC 2025


This is great!
Thank you!

-- 
Sergey A. Osokin

On Sat, Feb 01, 2025 at 01:57:02AM +0000, noreply at nginx.com wrote:
> details:   https://github.com/nginx/njs/commit/2d97e80486d7d2554e58cdaca4f2389b836600c8
> branches:  master
> commit:    2d97e80486d7d2554e58cdaca4f2389b836600c8
> user:      Dmitry Volyntsev <xeioex at nginx.com>
> date:      Tue, 28 Jan 2025 19:11:48 -0800
> description:
> HTTP: reading r.requestText or r.requestBuffer from a temp file.
> 
> Previously, an exception was thrown when accessing r.requestText or
> r.requestBuffer if a client request body size exceeded
> client_body_buffer_size.
> 
> ---
>  nginx/ngx_http_js_module.c | 60 +++++++++++++++++++++++++++++++++++++++-------
>  nginx/t/js_request_body.t  | 29 +++++++++++++++++++---
>  2 files changed, 77 insertions(+), 12 deletions(-)
> 
> diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c
> index 04d06fb2..66cb97c0 100644
> --- a/nginx/ngx_http_js_module.c
> +++ b/nginx/ngx_http_js_module.c
> @@ -2916,6 +2916,7 @@ ngx_http_js_ext_get_request_body(njs_vm_t *vm, njs_object_prop_t *prop,
>  {
>      u_char              *p, *body;
>      size_t               len;
> +    ssize_t              n;
>      uint32_t             buffer_type;
>      ngx_buf_t           *buf;
>      njs_int_t            ret;
> @@ -2948,14 +2949,35 @@ ngx_http_js_ext_get_request_body(njs_vm_t *vm, njs_object_prop_t *prop,
>          return NJS_DECLINED;
>      }
>  
> -    if (r->request_body->temp_file) {
> -        njs_vm_error(vm, "request body is in a file");
> -        return NJS_ERROR;
> -    }
> -
>      cl = r->request_body->bufs;
>      buf = cl->buf;
>  
> +    if (r->request_body->temp_file) {
> +        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
> +                      "http js reading request body from a temporary file");
> +
> +        if (buf == NULL || !buf->in_file) {
> +            njs_vm_internal_error(vm, "cannot find request body");
> +            return NJS_ERROR;
> +        }
> +
> +        len = buf->file_last - buf->file_pos;
> +
> +        body = ngx_pnalloc(r->pool, len);
> +        if (body == NULL) {
> +            njs_vm_memory_error(vm);
> +            return NJS_ERROR;
> +        }
> +
> +        n = ngx_read_file(buf->file, body, len, buf->file_pos);
> +        if (n != (ssize_t) len) {
> +            njs_vm_internal_error(vm, "failed to read request body");
> +            return NJS_ERROR;
> +        }
> +
> +        goto done;
> +    }
> +
>      if (cl->next == NULL) {
>          len = buf->last - buf->pos;
>          body = buf->pos;
> @@ -5259,6 +5281,7 @@ ngx_http_qjs_ext_request_body(JSContext *cx, JSValueConst this_val, int type)
>  {
>      u_char                  *p, *data;
>      size_t                   len;
> +    ssize_t                  n;
>      JSValue                  body;
>      uint32_t                 buffer_type;
>      ngx_buf_t               *buf;
> @@ -5287,13 +5310,32 @@ ngx_http_qjs_ext_request_body(JSContext *cx, JSValueConst this_val, int type)
>          return JS_UNDEFINED;
>      }
>  
> -    if (r->request_body->temp_file) {
> -        return JS_ThrowTypeError(cx, "request body is in a file");
> -    }
> -
>      cl = r->request_body->bufs;
>      buf = cl->buf;
>  
> +    if (r->request_body->temp_file) {
> +        ngx_log_error(NGX_LOG_WARN, r->connection->log, 0,
> +                      "http js reading request body from a temporary file");
> +
> +        if (buf == NULL || !buf->in_file) {
> +            return JS_ThrowInternalError(cx, "cannot find body file");
> +        }
> +
> +        len = buf->file_last - buf->file_pos;
> +
> +        data = ngx_pnalloc(r->pool, len);
> +        if (data == NULL) {
> +            return JS_ThrowOutOfMemory(cx);
> +        }
> +
> +        n = ngx_read_file(buf->file, data, len, buf->file_pos);
> +        if (n != (ssize_t) len) {
> +            return JS_ThrowInternalError(cx, "failed to read request body");
> +        }
> +
> +        goto done;
> +    }
> +
>      if (cl->next == NULL) {
>          len = buf->last - buf->pos;
>          data = buf->pos;
> diff --git a/nginx/t/js_request_body.t b/nginx/t/js_request_body.t
> index 360e4565..3980ea73 100644
> --- a/nginx/t/js_request_body.t
> +++ b/nginx/t/js_request_body.t
> @@ -47,11 +47,25 @@ http {
>              js_content test.body;
>          }
>  
> +        location /body_4k {
> +            client_body_buffer_size 4k;
> +            js_content test.body;
> +        }
> +
>          location /in_file {
> +            js_content test.body;
> +        }
> +
> +        location /in_file_on {
>              client_body_in_file_only on;
>              js_content test.body;
>          }
>  
> +        location /in_file_clean {
> +            client_body_in_file_only clean;
> +            js_content test.body;
> +        }
> +
>          location /read_body_from_temp_file {
>              client_body_in_file_only clean;
>              js_content test.read_body_from_temp_file;
> @@ -93,20 +107,29 @@ $t->write_file('test.js', <<EOF);
>  
>  EOF
>  
> -$t->try_run('no njs request body')->plan(5);
> +$t->try_run('no njs request body')->plan(9);
>  
>  ###############################################################################
>  
>  like(http_post('/body'), qr/REQ-BODY/, 'request body');
> -like(http_post('/in_file'), qr/request body is in a file/,
> -	'request body in file');
> +like(http_post('/in_file'), qr/REQ-BODY/, 'request body in a file');
> +like(http_post('/in_file_on'), qr/REQ-BODY/, 'request body in a file on');
> +like(http_post('/in_file_clean'), qr/REQ-BODY/, 'request body in a file clean');
>  like(http_post_big('/body'), qr/200.*^(1234567890){1024}$/ms,
>  		'request body big');
> +like(http_post_big('/body_4k'), qr/200.*^(1234567890){1024}$/ms,
> +		'request body big with 4k buffer');
>  like(http_post_big('/read_body_from_temp_file'),
>  	qr/200.*^(1234567890){1024}$/ms, 'request body big from temp file');
>  like(http_post('/request_body_cache'),
>  	qr/requestText:string requestBuffer:buffer$/s, 'request body cache');
>  
> +$t->stop();
> +
> +ok(index($t->read_file('error.log'),
> +	'http js reading request body from a temporary file') > 0,
> +	'http request body is in a file warning');
> +
>  ###############################################################################
>  
>  sub http_post {
> _______________________________________________
> nginx-devel mailing list
> nginx-devel at nginx.org
> https://mailman.nginx.org/mailman/listinfo/nginx-devel


More information about the nginx-devel mailing list