From c6b18e63a089a3b0b393375c4ae86f9293f1fcd0 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Mon, 9 Apr 2018 21:02:11 +0300 Subject: [PATCH] HTTP request body getter. Returns the client request body. --- nginx/ngx_http_js_module.c | 102 +++++++++++++++++++++++++++++++++++-- njs/njs_vm.c | 7 +++ njs/njscript.h | 4 ++ 3 files changed, 109 insertions(+), 4 deletions(-) diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 3f08dd7e..fa7a03d6 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -34,6 +34,7 @@ typedef struct { njs_opaque_value_t args[2]; ngx_uint_t done; ngx_int_t status; + njs_opaque_value_t request_body; } ngx_http_js_ctx_t; @@ -106,6 +107,8 @@ static njs_ret_t ngx_http_js_ext_get_http_version(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); +static njs_ret_t ngx_http_js_ext_get_request_body(njs_vm_t *vm, + njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); static njs_ret_t ngx_http_js_ext_foreach_header_in(njs_vm_t *vm, void *obj, @@ -129,8 +132,8 @@ static ngx_int_t ngx_http_js_subrequest_done(ngx_http_request_t *r, void *data, ngx_int_t rc); static njs_ret_t ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data); -static njs_ret_t ngx_http_js_ext_get_body(njs_vm_t *vm, njs_value_t *value, - void *obj, uintptr_t data); +static njs_ret_t ngx_http_js_ext_get_reply_body(njs_vm_t *vm, + njs_value_t *value, void *obj, uintptr_t data); static njs_host_event_t ngx_http_js_set_timer(njs_external_ptr_t external, uint64_t delay, njs_vm_event_t vm_event); @@ -358,6 +361,18 @@ static njs_external_t ngx_http_js_ext_request[] = { NULL, 0 }, + { nxt_string("body"), + NJS_EXTERN_PROPERTY, + NULL, + 0, + ngx_http_js_ext_get_request_body, + NULL, + NULL, + NULL, + NULL, + NULL, + 0 }, + { nxt_string("headers"), NJS_EXTERN_OBJECT, NULL, @@ -546,7 +561,7 @@ static njs_external_t ngx_http_js_ext_reply[] = { NJS_EXTERN_PROPERTY, NULL, 0, - ngx_http_js_ext_get_body, + ngx_http_js_ext_get_reply_body, NULL, NULL, NULL, @@ -1435,6 +1450,85 @@ ngx_http_js_ext_get_remote_address(njs_vm_t *vm, njs_value_t *value, void *obj, } +static njs_ret_t +ngx_http_js_ext_get_request_body(njs_vm_t *vm, njs_value_t *value, void *obj, + uintptr_t data) +{ + u_char *p, *body; + size_t len; + ngx_buf_t *buf; + njs_ret_t ret; + njs_value_t *request_body; + ngx_chain_t *cl; + ngx_http_js_ctx_t *ctx; + ngx_http_request_t *r; + + r = (ngx_http_request_t *) obj; + + ctx = ngx_http_get_module_ctx(r, ngx_http_js_module); + request_body = (njs_value_t *) &ctx->request_body; + + if (!njs_value_is_null(request_body)) { + njs_value_assign(value, request_body); + return NJS_OK; + } + + if (r->request_body == NULL || r->request_body->bufs == NULL) { + njs_vm_error(vm, "request body is unavailable"); + return NJS_ERROR; + } + + 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 (cl->next == NULL) { + len = buf->last - buf->pos; + body = buf->pos; + + goto done; + } + + len = buf->last - buf->pos; + cl = cl->next; + + for ( /* void */ ; cl; cl = cl->next) { + buf = cl->buf; + len += buf->last - buf->pos; + } + + p = ngx_pnalloc(r->pool, len); + if (p == NULL) { + njs_vm_memory_error(vm); + return NJS_ERROR; + } + + body = p; + cl = r->request_body->bufs; + + for ( /* void */ ; cl; cl = cl->next) { + buf = cl->buf; + p = ngx_cpymem(p, buf->pos, buf->last - buf->pos); + } + +done: + + ret = njs_string_create(vm, request_body, body, len, 0); + + if (ret != NXT_OK) { + return NJS_ERROR; + } + + njs_value_assign(value, request_body); + + return NJS_OK; +} + + static njs_ret_t ngx_http_js_ext_get_header_in(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) @@ -1939,7 +2033,7 @@ ngx_http_js_ext_get_parent(njs_vm_t *vm, njs_value_t *value, void *obj, static njs_ret_t -ngx_http_js_ext_get_body(njs_vm_t *vm, njs_value_t *value, void *obj, +ngx_http_js_ext_get_reply_body(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { size_t len; diff --git a/njs/njs_vm.c b/njs/njs_vm.c index 7d6df941..14f0e00f 100644 --- a/njs/njs_vm.c +++ b/njs/njs_vm.c @@ -3729,6 +3729,13 @@ njs_value_function(njs_value_t *value) } +nxt_noinline nxt_int_t +njs_value_is_null(njs_value_t *value) +{ + return njs_is_null(value); +} + + nxt_noinline nxt_int_t njs_value_is_void(njs_value_t *value) { diff --git a/njs/njscript.h b/njs/njscript.h index 4ec94da3..d6fa7b50 100644 --- a/njs/njscript.h +++ b/njs/njscript.h @@ -29,6 +29,9 @@ typedef struct { #define njs_argument(args, n) \ (njs_value_t *) ((u_char *) args + n * 16) +#define njs_value_assign(dst, src) \ + *((njs_opaque_value_t *) dst) = *((njs_opaque_value_t *) src); + #define njs_vm_error(vm, fmt, ...) \ njs_value_error_set(vm, njs_vm_retval(vm), fmt, ##__VA_ARGS__) @@ -193,6 +196,7 @@ NXT_EXPORT double njs_value_number(njs_value_t *value); NXT_EXPORT void *njs_value_data(njs_value_t *value); NXT_EXPORT njs_function_t *njs_value_function(njs_value_t *value); +NXT_EXPORT nxt_int_t njs_value_is_null(njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_void(njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_boolean(njs_value_t *value); NXT_EXPORT nxt_int_t njs_value_is_number(njs_value_t *value); -- 2.47.3