Fetch: added forward proxy support with HTTPS tunneling.
Supports Basic authentication via Proxy-Authorization header.
- js_fetch_proxy - configures forward proxy URL. It takes proxy URL
as a parameter. The URL may optionally contain user and password.
Parameter value can contain variables. If value is empty,
forward proxy is disabled.
Dmitry Volyntsev [Tue, 14 Oct 2025 00:37:11 +0000 (17:37 -0700)]
QuickJS: fixed r.subrequest() to a location with JS handler.
Previously, when a subrequest location had a JS handler, an object of a
subrequest JS context was provided as an argument to a parent contexts.
This may cause all sorts of problems due to incorrect reference
counting.
After this change in bellard/quickjs@42eb2795 the bug became apparent.
The issue was introduced in commit 04f6dfb (0.9.2) by moving VM
destruction from the pool cleanup handler to the http cleanup handler.
Moving VM destruction to the http cleanup handler broke js_set variable
usage during the log phase, because these variables are called after the
VM has been destroyed.
The fix is to move VM destruction back to the pool cleanup handler, but
use a temporary pool while njs.on('exit', ...) is executing.
build/src/njs_object.dep -MT build/src/njs_object.o \ src/njs_object.c
In file included from src/njs_main.h:18, from src/njs_object.c:8: In
function ‘njs_utf8_copy’, inlined from ‘njs_object_enumerate_string’ at
src/njs_object.c:769:21: src/njs_utf8.h:115:20: error: writing 1 byte
into a region of size 0 [-Werror=stringop-overflow=] 115 |
*dst++ = c; | ~~~~~~~^~~ src/njs_object.c: In function
‘njs_object_enumerate_string’: src/njs_object.c:719:24: note: at offset
4 into destination object ‘buf’ of size 4 719 | u_char
buf[4], *c; | ^~~ In function ‘njs_utf8_copy’,
inlined from ‘njs_object_enumerate_string’ at src/njs_object.c:769:21:
src/njs_utf8.h:115:20: error: writing 1 byte into a region of size 0
[-Werror=stringop-overflow=]
GCC-15 does not know that the loop in njs_utf8_copy() is bounded
because the input is a valid UTF-8 here.
Dmitry Volyntsev [Thu, 28 Aug 2025 22:20:31 +0000 (15:20 -0700)]
QuickJS: fixed potential heap-use-after-free.
Previously in QuickJS engine, fields allocated from memory pool linked
to QuickJS engine lifetime were stored in nginx data structs.
This causes a heap-use-after-free if QuickJS engine is destroyed
earlier than a last access from nginx. For example, it becomes
visible when moving NJS cleanup handler from pool->cleanup to
r->cleanup.
The fix is to only store references in nginx objects allocated from
nginx memory pool.
Dmitry Volyntsev [Mon, 11 Aug 2025 23:25:47 +0000 (16:25 -0700)]
Change: increasing the default stack size to 160k.
This change allows EarleyBoyer benchmark from
arewefastyet/benchmarks/v8-v7 to pass with default settings.
Previous commit 5e9a6d5 (v0.7.9) reduced the stack size to prevent stack
overflow when compiling with -O0 in computed goto mode, where native
stack frames for njs_vmcode_interpreter() consume ~80KB each. To address
this, we now set a lower maximum stack size specifically for unit tests.
After bellard/quickjs@458c34d2 modules are treated as GC objects and
tracked in rt->gc_obj_list. Intermediary module object loaded in
ngx_qjs_clone() using JS_ReadObject() needed to be freed for proper
ref_count accounting.
Dmitry Volyntsev [Tue, 10 Jun 2025 01:38:15 +0000 (18:38 -0700)]
Moving child function declaration instantiation to bytecode.
Children functions need to be hoisted and instantiated at the beginning
of a function call. Previously, it was done as a part of C code
that implements JS function call.
Now, each child function is instantiated by FUNCTION instruction at a
function prelude. This makes global and function code similar, which in
turn allows to get rid of FUNCTION COPY instruction which was only
needed for global code.
The Function constructor uses a `(function(<args>) {<body>})` template
to construct new functions. This approach was vulnerable to template
injection where malicious code could close the function body early.
Dmitry Volyntsev [Thu, 15 May 2025 01:16:15 +0000 (18:16 -0700)]
Modules: added state file for the shared dictionary.
A new optional state parameter is added for js_shared_dict_zone
directive. state parameter specifies a file that keeps the current state
of the shared dict in the JSON format and makes it persistent
across nginx restarts.
Fixed GCC 15 build with -Wunterminated-string-initialization.
In file included from src/njs_main.h:48,
from src/njs_diyfp.c:12:
src/njs_string.h: In function ‘njs_string_encode’:
src/njs_string.h:229:36: error: initializer-string for array of ‘unsigned char’
truncates NUL terminator but destination lacks ‘nonstring’ attribute (
17 chars into 16 available) [-Werror=unterminated-string-initialization]
229 | static const u_char hex[16] = "0123456789ABCDEF";
The 1496ed3f commit made visible a problem with the fragile filter tests
which depend on the exact sequence of data chunks. The fix is to use
perl http server to ensure the order.
In file included from src/njs_main.h:37,
from src/njs_diyfp.c:12:
src/njs_atom.h: In function ‘njs_atom_to_value’:
src/njs_atom.h:54:31: error: invalid use of incomplete typedef
‘njs_flathsh_descr_t’ {aka ‘struct njs_flathsh_descr_s’}
54 | njs_assert(atom_id < h->elts_count);
| ^~
src/njs_assert.h:14:15: note: in definition of macro ‘njs_assert’