]> git.kaiwu.me - njs.git/commitdiff
Modules: fixed loading of the built-in "crypto" module.
authorDmitry Volyntsev <xeioex@nginx.com>
Wed, 22 Apr 2026 22:56:18 +0000 (15:56 -0700)
committerDmitry Volyntsev <xeioexception@gmail.com>
Thu, 23 Apr 2026 15:05:12 +0000 (08:05 -0700)
Since 3185ce81 (0.9.7), njs_crypto_module has been registered
conditionally in auto/modules under NJS_HAVE_OPENSSL.  libnjs.a is
built for the nginx module via nginx/config.make with
"./configure --no-openssl ...", so libnjs.a's njs_modules[] no
longer contains the crypto module.  The nginx addon lists
(njs_http_js_addon_modules[] and njs_stream_js_addon_modules[],
plus the qjs variants) were not updated accordingly, making
"import cr from 'crypto'" fail at nginx -t with ENOENT.

Added &njs_crypto_module and &qjs_crypto_module to the shared addon
list under the existing NJS_HAVE_OPENSSL guard, next to the webcrypto
entries.

While here, the near-identical addon arrays were factored into
shared macros in a new header nginx/ngx_js_modules.h, so adding a
future conditional addon needs a single edit instead of four.

This closes #1049 issue on Github.

nginx/config
nginx/ngx_http_js_module.c
nginx/ngx_js.h
nginx/ngx_js_modules.h [new file with mode: 0644]
nginx/ngx_stream_js_module.c
nginx/t/js_crypto.t [new file with mode: 0644]
nginx/t/stream_js_crypto.t [new file with mode: 0644]

index 0d91ae12415ba0129893405765c989c5265edaa3..5bc93a3abd74c936afd8e90b85762e5a52f85716 100644 (file)
@@ -8,6 +8,7 @@ NJS_QUICKJS=${NJS_QUICKJS:-YES}
 NJS_DEPS="$ngx_addon_dir/ngx_js.h \
     $ngx_addon_dir/ngx_js_http.h \
     $ngx_addon_dir/ngx_js_fetch.h \
+    $ngx_addon_dir/ngx_js_modules.h \
     $ngx_addon_dir/ngx_js_shared_dict.h"
 NJS_SRCS="$ngx_addon_dir/ngx_js.c \
     $ngx_addon_dir/ngx_js_http.c \
index 20308a815432dc482be2ccc4e4ebc07ee0b5a833..d1908ff496588841537a49e31cd24fe20e43b7a0 100644 (file)
@@ -10,6 +10,7 @@
 #include <ngx_core.h>
 #include <ngx_http.h>
 #include "ngx_js.h"
+#include "ngx_js_modules.h"
 
 
 typedef struct {
@@ -1072,22 +1073,7 @@ njs_module_t  ngx_js_http_module = {
 
 
 njs_module_t *njs_http_js_addon_modules[] = {
-    /*
-     * Shared addons should be in the same order and the same positions
-     * in all nginx modules.
-     */
-    &ngx_js_ngx_module,
-    &ngx_js_fetch_module,
-    &ngx_js_shared_dict_module,
-#ifdef NJS_HAVE_OPENSSL
-    &njs_webcrypto_module,
-#endif
-#ifdef NJS_HAVE_XML
-    &njs_xml_module,
-#endif
-#ifdef NJS_HAVE_ZLIB
-    &njs_zlib_module,
-#endif
+    NGX_JS_NJS_ADDON_MODULES
     &ngx_js_http_module,
     NULL,
 };
@@ -1217,24 +1203,7 @@ static JSClassDef ngx_http_qjs_headers_out_class = {
 
 
 qjs_module_t *njs_http_qjs_addon_modules[] = {
-    &ngx_qjs_ngx_module,
-    &ngx_qjs_ngx_shared_dict_module,
-#ifdef NJS_HAVE_QUICKJS
-    &ngx_qjs_ngx_fetch_module,
-#endif
-    /*
-     * Shared addons should be in the same order and the same positions
-     * in all nginx modules.
-     */
-#ifdef NJS_HAVE_OPENSSL
-    &qjs_webcrypto_module,
-#endif
-#ifdef NJS_HAVE_XML
-    &qjs_xml_module,
-#endif
-#ifdef NJS_HAVE_ZLIB
-    &qjs_zlib_module,
-#endif
+    NGX_JS_QJS_ADDON_MODULES
     NULL,
 };
 
index 8d923c25f1043e737b7fd779d223e7dafa75d508..6012e7fd9489c1545dd145109243f5a668b937ec 100644 (file)
@@ -434,9 +434,6 @@ JSValue ngx_qjs_ext_fetch(JSContext *cx, JSValueConst this_val, int argc,
 #define ngx_qjs_main_conf(cx)                                                \
     ((ngx_js_main_conf_t *) ngx_qjs_meta(cx, NGX_JS_EXTERNAL_MAIN_CONF))
 
-extern qjs_module_t  qjs_webcrypto_module;
-extern qjs_module_t  qjs_xml_module;
-extern qjs_module_t  qjs_zlib_module;
 extern qjs_module_t  ngx_qjs_ngx_module;
 extern qjs_module_t  ngx_qjs_ngx_shared_dict_module;
 extern qjs_module_t  ngx_qjs_ngx_fetch_module;
@@ -491,9 +488,6 @@ void *ngx_js_queue_pop(ngx_js_queue_t *queue);
 
 
 extern njs_module_t  ngx_js_ngx_module;
-extern njs_module_t  njs_webcrypto_module;
-extern njs_module_t  njs_xml_module;
-extern njs_module_t  njs_zlib_module;
 
 
 #include "ngx_js_fetch.h"
diff --git a/nginx/ngx_js_modules.h b/nginx/ngx_js_modules.h
new file mode 100644 (file)
index 0000000..772821a
--- /dev/null
@@ -0,0 +1,88 @@
+
+/*
+ * Copyright (C) Dmitry Volyntsev
+ * Copyright (C) F5, Inc.
+ */
+
+
+#ifndef _NGX_JS_MODULES_H_INCLUDED_
+#define _NGX_JS_MODULES_H_INCLUDED_
+
+
+/*
+ * Shared addon module list registered by the HTTP and Stream nginx js
+ * modules.  When adding a new conditional addon, declare it here under the
+ * matching NJS_HAVE_* guard and extend the corresponding NGX_JS_NJS_ADDONS_*
+ * or NGX_JS_QJS_ADDONS_* fragment.
+ */
+
+
+#ifdef NJS_HAVE_OPENSSL
+extern njs_module_t  njs_crypto_module;
+extern njs_module_t  njs_webcrypto_module;
+#define NGX_JS_NJS_ADDONS_OPENSSL   &njs_crypto_module, &njs_webcrypto_module,
+#else
+#define NGX_JS_NJS_ADDONS_OPENSSL
+#endif
+
+#ifdef NJS_HAVE_XML
+extern njs_module_t  njs_xml_module;
+#define NGX_JS_NJS_ADDONS_XML       &njs_xml_module,
+#else
+#define NGX_JS_NJS_ADDONS_XML
+#endif
+
+#ifdef NJS_HAVE_ZLIB
+extern njs_module_t  njs_zlib_module;
+#define NGX_JS_NJS_ADDONS_ZLIB      &njs_zlib_module,
+#else
+#define NGX_JS_NJS_ADDONS_ZLIB
+#endif
+
+
+#define NGX_JS_NJS_ADDON_MODULES                                             \
+    &ngx_js_ngx_module,                                                      \
+    &ngx_js_fetch_module,                                                    \
+    &ngx_js_shared_dict_module,                                              \
+    NGX_JS_NJS_ADDONS_OPENSSL                                                \
+    NGX_JS_NJS_ADDONS_XML                                                    \
+    NGX_JS_NJS_ADDONS_ZLIB
+
+
+#if (NJS_HAVE_QUICKJS)
+
+#ifdef NJS_HAVE_OPENSSL
+extern qjs_module_t  qjs_crypto_module;
+extern qjs_module_t  qjs_webcrypto_module;
+#define NGX_JS_QJS_ADDONS_OPENSSL   &qjs_crypto_module, &qjs_webcrypto_module,
+#else
+#define NGX_JS_QJS_ADDONS_OPENSSL
+#endif
+
+#ifdef NJS_HAVE_XML
+extern qjs_module_t  qjs_xml_module;
+#define NGX_JS_QJS_ADDONS_XML       &qjs_xml_module,
+#else
+#define NGX_JS_QJS_ADDONS_XML
+#endif
+
+#ifdef NJS_HAVE_ZLIB
+extern qjs_module_t  qjs_zlib_module;
+#define NGX_JS_QJS_ADDONS_ZLIB      &qjs_zlib_module,
+#else
+#define NGX_JS_QJS_ADDONS_ZLIB
+#endif
+
+
+#define NGX_JS_QJS_ADDON_MODULES                                             \
+    &ngx_qjs_ngx_module,                                                     \
+    &ngx_qjs_ngx_shared_dict_module,                                         \
+    &ngx_qjs_ngx_fetch_module,                                               \
+    NGX_JS_QJS_ADDONS_OPENSSL                                                \
+    NGX_JS_QJS_ADDONS_XML                                                    \
+    NGX_JS_QJS_ADDONS_ZLIB
+
+#endif /* NJS_HAVE_QUICKJS */
+
+
+#endif /* _NGX_JS_MODULES_H_INCLUDED_ */
index b21b701dd2fa7c721e07e06f4eb01ecf12f96c4d..3b12a3356514ec9c8d879410d14e7a81524e0a76 100644 (file)
@@ -10,6 +10,7 @@
 #include <ngx_core.h>
 #include <ngx_stream.h>
 #include "ngx_js.h"
+#include "ngx_js_modules.h"
 
 
 typedef struct ngx_stream_js_ctx_s  ngx_stream_js_ctx_t;
@@ -809,22 +810,7 @@ njs_module_t  ngx_js_stream_module = {
 
 
 njs_module_t *njs_stream_js_addon_modules[] = {
-    /*
-     * Shared addons should be in the same order and the same positions
-     * in all nginx modules.
-     */
-    &ngx_js_ngx_module,
-    &ngx_js_fetch_module,
-    &ngx_js_shared_dict_module,
-#ifdef NJS_HAVE_OPENSSL
-    &njs_webcrypto_module,
-#endif
-#ifdef NJS_HAVE_XML
-    &njs_xml_module,
-#endif
-#ifdef NJS_HAVE_ZLIB
-    &njs_zlib_module,
-#endif
+    NGX_JS_NJS_ADDON_MODULES
     &ngx_js_stream_module,
     NULL,
 };
@@ -906,22 +892,7 @@ static JSClassDef ngx_stream_qjs_variables_class = {
 
 
 qjs_module_t *njs_stream_qjs_addon_modules[] = {
-    &ngx_qjs_ngx_module,
-    &ngx_qjs_ngx_shared_dict_module,
-    &ngx_qjs_ngx_fetch_module,
-    /*
-     * Shared addons should be in the same order and the same positions
-     * in all nginx modules.
-     */
-#ifdef NJS_HAVE_OPENSSL
-    &qjs_webcrypto_module,
-#endif
-#ifdef NJS_HAVE_XML
-    &qjs_xml_module,
-#endif
-#ifdef NJS_HAVE_ZLIB
-    &qjs_zlib_module,
-#endif
+    NGX_JS_QJS_ADDON_MODULES
     NULL,
 };
 
diff --git a/nginx/t/js_crypto.t b/nginx/t/js_crypto.t
new file mode 100644 (file)
index 0000000..84d41c9
--- /dev/null
@@ -0,0 +1,85 @@
+#!/usr/bin/perl
+
+# (C) Dmitry Volyntsev
+# (C) F5, Inc.
+
+# Tests for http njs module, crypto module import.
+# Regression test for Github issue #1049.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/http/)
+       ->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+http {
+    %%TEST_GLOBALS_HTTP%%
+
+    js_import test.js;
+
+    server {
+        listen       127.0.0.1:8080;
+        server_name  localhost;
+
+        location /hash {
+            js_content test.hash;
+        }
+
+        location /hmac {
+            js_content test.hmac;
+        }
+    }
+}
+
+EOF
+
+$t->write_file('test.js', <<EOF);
+    import cr from 'crypto';
+
+    function hash(r) {
+        r.return(200,
+            cr.createHash('sha256').update('abc').digest('hex'));
+    }
+
+    function hmac(r) {
+        r.return(200,
+            cr.createHmac('sha256', 'key').update('message').digest('hex'));
+    }
+
+    export default {hash, hmac};
+EOF
+
+$t->try_run('no njs crypto module')->plan(2);
+
+###############################################################################
+
+like(http_get('/hash'),
+       qr/ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad/,
+       'crypto sha256 digest');
+
+like(http_get('/hmac'),
+       qr/6e9ef29b75fffc5b7abae527d58fdadb2fe42e7219011976917343065f58ed4a/,
+       'crypto hmac-sha256 digest');
+
+###############################################################################
diff --git a/nginx/t/stream_js_crypto.t b/nginx/t/stream_js_crypto.t
new file mode 100644 (file)
index 0000000..7dd7619
--- /dev/null
@@ -0,0 +1,70 @@
+#!/usr/bin/perl
+
+# (C) Dmitry Volyntsev
+# (C) F5, Inc.
+
+# Tests for stream njs module, crypto module import.
+# Regression test for Github issue #1049.
+
+###############################################################################
+
+use warnings;
+use strict;
+
+use Test::More;
+
+BEGIN { use FindBin; chdir($FindBin::Bin); }
+
+use lib 'lib';
+use Test::Nginx;
+use Test::Nginx::Stream qw/ stream /;
+
+###############################################################################
+
+select STDERR; $| = 1;
+select STDOUT; $| = 1;
+
+my $t = Test::Nginx->new()->has(qw/stream stream_return/)
+       ->write_file_expand('nginx.conf', <<'EOF');
+
+%%TEST_GLOBALS%%
+
+daemon off;
+
+events {
+}
+
+stream {
+    %%TEST_GLOBALS_STREAM%%
+
+    js_import test.js;
+
+    js_set $hash test.hash;
+
+    server {
+        listen  127.0.0.1:8081;
+        return  $hash;
+    }
+}
+
+EOF
+
+$t->write_file('test.js', <<EOF);
+    import cr from 'crypto';
+
+    function hash(s) {
+        return cr.createHash('sha256').update('abc').digest('hex');
+    }
+
+    export default {hash};
+EOF
+
+$t->try_run('no njs crypto module')->plan(1);
+
+###############################################################################
+
+like(stream('127.0.0.1:' . port(8081))->io('###'),
+       qr/ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad/,
+       'crypto sha256 digest');
+
+###############################################################################