details: https://github.com/nginx/njs/commit/2d97e80486d7d2554e58cdaca4f2389b836600c8 branches: master commit: 2d97e80486d7d2554e58cdaca4f2389b836600c8 user: Dmitry Volyntsev <xei...@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@nginx.org https://mailman.nginx.org/mailman/listinfo/nginx-devel