[njs] HTTP: reading r.requestText or r.requestBuffer from a temp file.
noreply at nginx.com
noreply at nginx.com
Sat Feb 1 01:57:02 UTC 2025
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 {
More information about the nginx-devel
mailing list