[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