From 2ce538ea8f637d91f0f8518925995c662a4b50c4 Mon Sep 17 00:00:00 2001 From: Dmitry Volyntsev Date: Thu, 28 Apr 2022 16:37:14 -0700 Subject: [PATCH] Modules: added additional directives for Fetch API. The following directives are added: * js_fetch_timeout * js_fetch_verify * js_fetch_buffer_size * js_fetch_max_response_buffer_size This closes #489 issue on Github. --- nginx/ngx_http_js_module.c | 105 +++++++++++++++++++++++++++++++++- nginx/ngx_js.h | 16 +++++- nginx/ngx_js_fetch.c | 8 ++- nginx/ngx_stream_js_module.c | 106 ++++++++++++++++++++++++++++++++++- ts/ngx_core.d.ts | 6 +- 5 files changed, 232 insertions(+), 9 deletions(-) diff --git a/nginx/ngx_http_js_module.c b/nginx/ngx_http_js_module.c index 84e5ae8e..1f7d4440 100644 --- a/nginx/ngx_http_js_module.c +++ b/nginx/ngx_http_js_module.c @@ -24,10 +24,16 @@ typedef struct { ngx_str_t header_filter; ngx_str_t body_filter; ngx_uint_t buffer_type; + + size_t buffer_size; + size_t max_response_body_size; + ngx_msec_t timeout; + #if (NGX_HTTP_SSL) ngx_ssl_t *ssl; ngx_str_t ssl_ciphers; ngx_uint_t ssl_protocols; + ngx_flag_t ssl_verify; ngx_int_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; #endif @@ -207,6 +213,11 @@ static ngx_resolver_t *ngx_http_js_resolver(njs_vm_t *vm, ngx_http_request_t *r); static ngx_msec_t ngx_http_js_resolver_timeout(njs_vm_t *vm, ngx_http_request_t *r); +static ngx_msec_t ngx_http_js_fetch_timeout(njs_vm_t *vm, + ngx_http_request_t *r); +static size_t ngx_http_js_buffer_size(njs_vm_t *vm, ngx_http_request_t *r); +static size_t ngx_http_js_max_response_buffer_size(njs_vm_t *vm, + ngx_http_request_t *r); static void ngx_http_js_handle_vm_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); static void ngx_http_js_handle_event(ngx_http_request_t *r, @@ -231,6 +242,7 @@ static char *ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent, static char * ngx_http_js_set_ssl(ngx_conf_t *cf, ngx_http_js_loc_conf_t *jlcf); #endif static ngx_ssl_t *ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r); +static ngx_flag_t ngx_http_js_ssl_verify(njs_vm_t *vm, ngx_http_request_t *r); #if (NGX_HTTP_SSL) @@ -295,6 +307,27 @@ static ngx_command_t ngx_http_js_commands[] = { 0, NULL }, + { ngx_string("js_fetch_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, buffer_size), + NULL }, + + { ngx_string("js_fetch_max_response_buffer_size"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, max_response_body_size), + NULL }, + + { ngx_string("js_fetch_timeout"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, timeout), + NULL }, + #if (NGX_HTTP_SSL) { ngx_string("js_fetch_ciphers"), @@ -311,6 +344,13 @@ static ngx_command_t ngx_http_js_commands[] = { offsetof(ngx_http_js_loc_conf_t, ssl_protocols), &ngx_http_js_ssl_protocols }, + { ngx_string("js_fetch_verify"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_js_loc_conf_t, ssl_verify), + NULL }, + { ngx_string("js_fetch_verify_depth"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -716,11 +756,15 @@ static uintptr_t ngx_http_js_uptr[] = { (uintptr_t) ngx_http_js_resolver_timeout, (uintptr_t) ngx_http_js_handle_event, (uintptr_t) ngx_http_js_ssl, + (uintptr_t) ngx_http_js_ssl_verify, + (uintptr_t) ngx_http_js_fetch_timeout, + (uintptr_t) ngx_http_js_buffer_size, + (uintptr_t) ngx_http_js_max_response_buffer_size, }; static njs_vm_meta_t ngx_http_js_metas = { - .size = 6, + .size = njs_nitems(ngx_http_js_uptr), .values = ngx_http_js_uptr }; @@ -3420,6 +3464,39 @@ ngx_http_js_resolver_timeout(njs_vm_t *vm, ngx_http_request_t *r) } +static ngx_msec_t +ngx_http_js_fetch_timeout(njs_vm_t *vm, ngx_http_request_t *r) +{ + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + return jlcf->timeout; +} + + +static size_t +ngx_http_js_buffer_size(njs_vm_t *vm, ngx_http_request_t *r) +{ + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + return jlcf->buffer_size; +} + + +static size_t +ngx_http_js_max_response_buffer_size(njs_vm_t *vm, ngx_http_request_t *r) +{ + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + return jlcf->max_response_body_size; +} + + static void ngx_http_js_handle_vm_event(ngx_http_request_t *r, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs) @@ -3952,7 +4029,12 @@ ngx_http_js_create_loc_conf(ngx_conf_t *cf) * conf->ssl_trusted_certificate = { 0, NULL }; */ + conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->max_response_body_size = NGX_CONF_UNSET_SIZE; + conf->timeout = NGX_CONF_UNSET_MSEC; + #if (NGX_HTTP_SSL) + conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET; #endif @@ -3972,6 +4054,11 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_uint_value(conf->buffer_type, prev->buffer_type, NGX_JS_STRING); + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); + ngx_conf_merge_size_value(conf->max_response_body_size, + prev->max_response_body_size, 1048576); + #if (NGX_HTTP_SSL) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); @@ -3979,6 +4066,7 @@ ngx_http_js_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + ngx_conf_merge_value(conf->ssl_verify, prev->ssl_verify, 1); ngx_conf_merge_value(conf->ssl_verify_depth, prev->ssl_verify_depth, 100); ngx_conf_merge_str_value(conf->ssl_trusted_certificate, @@ -4050,3 +4138,18 @@ ngx_http_js_ssl(njs_vm_t *vm, ngx_http_request_t *r) return NULL; #endif } + + +static ngx_flag_t +ngx_http_js_ssl_verify(njs_vm_t *vm, ngx_http_request_t *r) +{ +#if (NGX_HTTP_SSL) + ngx_http_js_loc_conf_t *jlcf; + + jlcf = ngx_http_get_module_loc_conf(r, ngx_http_js_module); + + return jlcf->ssl_verify; +#else + return 0; +#endif +} diff --git a/nginx/ngx_js.h b/nginx/ngx_js.h index 2a9bf856..e3287a5b 100644 --- a/nginx/ngx_js.h +++ b/nginx/ngx_js.h @@ -25,7 +25,11 @@ typedef void (*ngx_js_event_handler_pt)(njs_external_ptr_t e, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); typedef ngx_resolver_t *(*ngx_external_resolver_pt)(njs_vm_t *vm, njs_external_ptr_t e); -typedef ngx_msec_t (*ngx_external_resolver_timeout_pt)(njs_vm_t *vm, +typedef ngx_msec_t (*ngx_external_timeout_pt)(njs_vm_t *vm, + njs_external_ptr_t e); +typedef ngx_flag_t (*ngx_external_flag_pt)(njs_vm_t *vm, + njs_external_ptr_t e); +typedef ngx_flag_t (*ngx_external_size_pt)(njs_vm_t *vm, njs_external_ptr_t e); typedef ngx_ssl_t *(*ngx_external_ssl_pt)(njs_vm_t *vm, njs_external_ptr_t e); @@ -37,11 +41,19 @@ typedef ngx_ssl_t *(*ngx_external_ssl_pt)(njs_vm_t *vm, njs_external_ptr_t e); #define ngx_external_resolver(vm, e) \ ((ngx_external_resolver_pt) njs_vm_meta(vm, 2))(vm, e) #define ngx_external_resolver_timeout(vm, e) \ - ((ngx_external_resolver_timeout_pt) njs_vm_meta(vm, 3))(vm, e) + ((ngx_external_timeout_pt) njs_vm_meta(vm, 3))(vm, e) #define ngx_external_event_handler(vm, e) \ ((ngx_js_event_handler_pt) njs_vm_meta(vm, 4)) #define ngx_external_ssl(vm, e) \ ((ngx_external_ssl_pt) njs_vm_meta(vm, 5))(vm, e) +#define ngx_external_ssl_verify(vm, e) \ + ((ngx_external_flag_pt) njs_vm_meta(vm, 6))(vm, e) +#define ngx_external_fetch_timeout(vm, e) \ + ((ngx_external_timeout_pt) njs_vm_meta(vm, 7))(vm, e) +#define ngx_external_buffer_size(vm, e) \ + ((ngx_external_size_pt) njs_vm_meta(vm, 8))(vm, e) +#define ngx_external_max_response_buffer_size(vm, e) \ + ((ngx_external_size_pt) njs_vm_meta(vm, 9))(vm, e) #define ngx_js_prop(vm, type, value, start, len) \ diff --git a/nginx/ngx_js_fetch.c b/nginx/ngx_js_fetch.c index ba36f87c..a01b5895 100644 --- a/nginx/ngx_js_fetch.c +++ b/nginx/ngx_js_fetch.c @@ -376,9 +376,11 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, } http->external = external; + http->timeout = ngx_external_fetch_timeout(vm, external); http->event_handler = ngx_external_event_handler(vm, external); - http->buffer_size = 4096; - http->max_response_body_size = 32 * 1024; + http->buffer_size = ngx_external_buffer_size(vm, external); + http->max_response_body_size = + ngx_external_max_response_buffer_size(vm, external); ret = ngx_js_string(vm, njs_arg(args, nargs, 1), &http->url); if (ret != NJS_OK) { @@ -408,7 +410,7 @@ ngx_js_ext_fetch(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs, u.url.data += 8; u.default_port = 443; http->ssl = ngx_external_ssl(vm, external); - http->ssl_verify = 1; + http->ssl_verify = ngx_external_ssl_verify(vm, external); #endif } else { diff --git a/nginx/ngx_stream_js_module.c b/nginx/ngx_stream_js_module.c index ab3368da..8897b3ae 100644 --- a/nginx/ngx_stream_js_module.c +++ b/nginx/ngx_stream_js_module.c @@ -31,9 +31,15 @@ typedef struct { ngx_str_t access; ngx_str_t preread; ngx_str_t filter; + + size_t buffer_size; + size_t max_response_body_size; + ngx_msec_t timeout; + #if (NGX_STREAM_SSL) ngx_ssl_t *ssl; ngx_str_t ssl_ciphers; + ngx_flag_t ssl_verify; ngx_uint_t ssl_protocols; ngx_int_t ssl_verify_depth; ngx_str_t ssl_trusted_certificate; @@ -124,6 +130,11 @@ static ngx_resolver_t *ngx_stream_js_resolver(njs_vm_t *vm, ngx_stream_session_t *s); static ngx_msec_t ngx_stream_js_resolver_timeout(njs_vm_t *vm, ngx_stream_session_t *s); +static ngx_msec_t ngx_stream_js_fetch_timeout(njs_vm_t *vm, + ngx_stream_session_t *s); +static size_t ngx_stream_js_buffer_size(njs_vm_t *vm, ngx_stream_session_t *s); +static size_t ngx_stream_js_max_response_buffer_size(njs_vm_t *vm, + ngx_stream_session_t *s); static void ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs); @@ -145,6 +156,8 @@ static char * ngx_stream_js_set_ssl(ngx_conf_t *cf, ngx_stream_js_srv_conf_t *jscf); #endif static ngx_ssl_t *ngx_stream_js_ssl(njs_vm_t *vm, ngx_stream_session_t *s); +static ngx_flag_t ngx_stream_js_ssl_verify(njs_vm_t *vm, + ngx_stream_session_t *s); #if (NGX_STREAM_SSL) @@ -209,6 +222,27 @@ static ngx_command_t ngx_stream_js_commands[] = { offsetof(ngx_stream_js_srv_conf_t, filter), NULL }, + { ngx_string("js_fetch_buffer_size"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_js_srv_conf_t, buffer_size), + NULL }, + + { ngx_string("js_fetch_max_response_buffer_size"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_size_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_js_srv_conf_t, max_response_body_size), + NULL }, + + { ngx_string("js_fetch_timeout"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_js_srv_conf_t, timeout), + NULL }, + #if (NGX_STREAM_SSL) { ngx_string("js_fetch_ciphers"), @@ -225,6 +259,13 @@ static ngx_command_t ngx_stream_js_commands[] = { offsetof(ngx_stream_js_srv_conf_t, ssl_protocols), &ngx_stream_js_ssl_protocols }, + { ngx_string("js_fetch_verify"), + NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_STREAM_SRV_CONF_OFFSET, + offsetof(ngx_stream_js_srv_conf_t, ssl_verify), + NULL }, + { ngx_string("js_fetch_verify_depth"), NGX_STREAM_MAIN_CONF|NGX_STREAM_SRV_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -468,11 +509,15 @@ static uintptr_t ngx_stream_js_uptr[] = { (uintptr_t) ngx_stream_js_resolver_timeout, (uintptr_t) ngx_stream_js_handle_event, (uintptr_t) ngx_stream_js_ssl, + (uintptr_t) ngx_stream_js_ssl_verify, + (uintptr_t) ngx_stream_js_fetch_timeout, + (uintptr_t) ngx_stream_js_buffer_size, + (uintptr_t) ngx_stream_js_max_response_buffer_size, }; static njs_vm_meta_t ngx_stream_js_metas = { - .size = 6, + .size = njs_nitems(ngx_stream_js_uptr), .values = ngx_stream_js_uptr }; @@ -1456,6 +1501,39 @@ ngx_stream_js_resolver_timeout(njs_vm_t *vm, ngx_stream_session_t *s) } +static ngx_msec_t +ngx_stream_js_fetch_timeout(njs_vm_t *vm, ngx_stream_session_t *s) +{ + ngx_stream_core_srv_conf_t *cscf; + + cscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module); + + return cscf->resolver_timeout; +} + + +static size_t +ngx_stream_js_buffer_size(njs_vm_t *vm, ngx_stream_session_t *s) +{ + ngx_stream_js_srv_conf_t *jscf; + + jscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module); + + return jscf->buffer_size; +} + + +static size_t +ngx_stream_js_max_response_buffer_size(njs_vm_t *vm, ngx_stream_session_t *s) +{ + ngx_stream_js_srv_conf_t *jscf; + + jscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module); + + return jscf->max_response_body_size; +} + + static void ngx_stream_js_handle_event(ngx_stream_session_t *s, njs_vm_event_t vm_event, njs_value_t *args, njs_uint_t nargs) @@ -1898,7 +1976,12 @@ ngx_stream_js_create_srv_conf(ngx_conf_t *cf) * conf->ssl_trusted_certificate = { 0, NULL }; */ + conf->buffer_size = NGX_CONF_UNSET_SIZE; + conf->max_response_body_size = NGX_CONF_UNSET_SIZE; + conf->timeout = NGX_CONF_UNSET_MSEC; + #if (NGX_STREAM_SSL) + conf->ssl_verify = NGX_CONF_UNSET; conf->ssl_verify_depth = NGX_CONF_UNSET; #endif return conf; @@ -1915,6 +1998,11 @@ ngx_stream_js_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) ngx_conf_merge_str_value(conf->preread, prev->preread, ""); ngx_conf_merge_str_value(conf->filter, prev->filter, ""); + ngx_conf_merge_msec_value(conf->timeout, prev->timeout, 60000); + ngx_conf_merge_size_value(conf->buffer_size, prev->buffer_size, 16384); + ngx_conf_merge_size_value(conf->max_response_body_size, + prev->max_response_body_size, 1048576); + #if (NGX_STREAM_SSL) ngx_conf_merge_str_value(conf->ssl_ciphers, prev->ssl_ciphers, "DEFAULT"); @@ -1922,6 +2010,7 @@ ngx_stream_js_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) (NGX_CONF_BITMASK_SET|NGX_SSL_TLSv1 |NGX_SSL_TLSv1_1|NGX_SSL_TLSv1_2)); + ngx_conf_merge_value(conf->ssl_verify, prev->ssl_verify, 1); ngx_conf_merge_value(conf->ssl_verify_depth, prev->ssl_verify_depth, 100); ngx_conf_merge_str_value(conf->ssl_trusted_certificate, @@ -2022,3 +2111,18 @@ ngx_stream_js_ssl(njs_vm_t *vm, ngx_stream_session_t *s) return NULL; #endif } + + +static ngx_flag_t +ngx_stream_js_ssl_verify(njs_vm_t *vm, ngx_stream_session_t *s) +{ +#if (NGX_STREAM_SSL) + ngx_stream_js_srv_conf_t *jscf; + + jscf = ngx_stream_get_module_srv_conf(s, ngx_stream_js_module); + + return jscf->ssl_verify; +#else + return 0; +#endif +} diff --git a/ts/ngx_core.d.ts b/ts/ngx_core.d.ts index 4010eed3..042e6f25 100644 --- a/ts/ngx_core.d.ts +++ b/ts/ngx_core.d.ts @@ -78,8 +78,9 @@ interface NgxFetchOptions { */ body?: NjsStringLike, /** - * The buffer size for reading the response, by default is 4096. + * The buffer size for reading the response, by default is 16384 (4096 before 0.7.4). * Nginx specific. + * @deprecated Use `js_fetch_buffer_size` directive instead. */ buffer_size?: Number, /** @@ -87,8 +88,9 @@ interface NgxFetchOptions { */ headers?: Object, /** - * The maximum size of the response body in bytes, by default is 32768. + * The maximum size of the response body in bytes, by default is 1048576 (32768 before 0.7.4). * Nginx specific. + * @deprecated Use `js_fetch_max_response_buffer_size` directive instead. */ max_response_body_size?: Number, /** -- 2.47.3