Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nginx
GitHub Repository: nginx/nginx.org
Path: blob/main/xml/en/docs/njs/native_modules.xml
1 views
1
<?xml version="1.0"?>
2
3
<!--
4
Copyright (C) Nginx, Inc.
5
-->
6
7
<!DOCTYPE article SYSTEM "../../../../dtd/article.dtd">
8
9
<article name="Native modules"
10
link="/en/docs/njs/native_modules.html"
11
lang="en"
12
rev="1">
13
14
<section id="intro" name="Overview">
15
16
<para>
17
Native modules allow loading C-based shared libraries (.so files)
18
into NGINX JavaScript for performance-critical operations
19
or system-level integrations.
20
This feature is available only with the
21
<link doc="engine.xml" id="quickjs_engine">QuickJS engine</link>
22
and is not supported by the njs native engine.
23
Native module support has been available
24
since <link doc="changes.xml" id="njs0.9.5">0.9.5</link>.
25
</para>
26
27
</section>
28
29
30
<section id="when_to_use" name="When to use native modules">
31
32
<para>
33
Native modules are useful in the following scenarios:
34
35
<list type="bullet">
36
37
<listitem>
38
Performance-critical operations that exceed JavaScript capabilities
39
</listitem>
40
41
<listitem>
42
System-level integrations requiring C libraries
43
</listitem>
44
45
<listitem>
46
Leveraging existing C/C++ codebases
47
</listitem>
48
49
</list>
50
</para>
51
52
<para>
53
Native modules should be used for low-level primitives
54
rather than for complex business logic,
55
for example, for cryptographic operations (hashing, encryption),
56
data compression/decompression, binary protocol parsing,
57
high-performance string operations, or mathematical computations.
58
Complex application logic should remain in JavaScript
59
where it's easier to maintain, debug, and modify.
60
</para>
61
62
<para>
63
Limitations:
64
65
<list type="bullet">
66
67
<listitem>
68
Native modules must be compiled for the same architecture as NGINX
69
</listitem>
70
71
<listitem>
72
Native modules run with full process privileges
73
and require careful security review
74
</listitem>
75
76
</list>
77
</para>
78
79
</section>
80
81
82
<section id="loading" name="Loading native modules in NGINX">
83
84
<para>
85
Native modules are loaded using these directives
86
specified in the <literal>main</literal> context:
87
88
<list type="bullet">
89
90
<listitem>
91
<link doc="../http/ngx_http_js_module.xml" id="js_load_http_native_module">
92
js_load_http_native_module</link> for HTTP context
93
</listitem>
94
95
<listitem>
96
<link doc="../stream/ngx_stream_js_module.xml" id="js_load_stream_native_module">
97
js_load_stream_native_module</link> for Stream context
98
</listitem>
99
100
</list>
101
</para>
102
103
<para>
104
Example configuration:
105
<example>
106
js_load_http_native_module /path/to/mylib.so;
107
js_load_http_native_module /path/to/other.so as myalias;
108
109
http {
110
js_import main.js;
111
112
server {
113
listen 8000;
114
location / {
115
js_content main.handler;
116
}
117
}
118
}
119
</example>
120
</para>
121
122
<para>
123
Once loaded, the module can be imported in JavaScript code:
124
<example>
125
// Import by filename
126
import * as mylib from 'mylib.so';
127
128
// Import by alias
129
import * as myalias from 'myalias';
130
131
function handler(r) {
132
let result = mylib.add(5, 10);
133
r.return(200, `Result: ${result}\n`);
134
}
135
136
export default { handler };
137
</example>
138
</para>
139
140
</section>
141
142
143
<section id="building" name="Building native modules">
144
145
<para>
146
Native modules must implement the <literal>js_init_module</literal>
147
function as the entry point.
148
This function is called by QuickJS when the module is loaded.
149
</para>
150
151
<para>
152
A complete example of a simple native module
153
that exports two functions:
154
<example>
155
#include &lt;quickjs.h&gt;
156
157
#define countof(x) (sizeof(x) / sizeof((x)[0]))
158
159
/* Add two numbers */
160
static JSValue
161
js_add(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv)
162
{
163
int a, b;
164
165
if (argc &lt; 2) {
166
return JS_ThrowTypeError(ctx, "expected 2 arguments");
167
}
168
169
if (JS_ToInt32(ctx, &amp;a, argv[0]) &lt; 0) {
170
return JS_EXCEPTION;
171
}
172
173
if (JS_ToInt32(ctx, &amp;b, argv[1]) &lt; 0) {
174
return JS_EXCEPTION;
175
}
176
177
return JS_NewInt32(ctx, a + b);
178
}
179
180
/* Reverse a string */
181
static JSValue
182
js_reverse_string(JSContext *ctx, JSValueConst this_val, int argc,
183
JSValueConst *argv)
184
{
185
char *reversed;
186
size_t i, len;
187
JSValue result;
188
const char *str;
189
190
if (argc &lt; 1) {
191
return JS_ThrowTypeError(ctx, "expected 1 argument");
192
}
193
194
str = JS_ToCStringLen(ctx, &amp;len, argv[0]);
195
if (!str) {
196
return JS_EXCEPTION;
197
}
198
199
reversed = js_malloc(ctx, len + 1);
200
if (!reversed) {
201
JS_FreeCString(ctx, str);
202
return JS_EXCEPTION;
203
}
204
205
for (i = 0; i &lt; len; i++) {
206
reversed[i] = str[len - 1 - i];
207
}
208
reversed[len] = '\0';
209
210
result = JS_NewString(ctx, reversed);
211
212
js_free(ctx, reversed);
213
JS_FreeCString(ctx, str);
214
215
return result;
216
}
217
218
/* Module function list */
219
static const JSCFunctionListEntry js_module_funcs[] = {
220
JS_CFUNC_DEF("add", 2, js_add),
221
JS_CFUNC_DEF("reverseString", 1, js_reverse_string),
222
};
223
224
/* Module initialization */
225
static int
226
js_module_init(JSContext *ctx, JSModuleDef *m)
227
{
228
return JS_SetModuleExportList(ctx, m, js_module_funcs,
229
countof(js_module_funcs));
230
}
231
232
/* Required entry point */
233
JSModuleDef *
234
js_init_module(JSContext *ctx, const char *module_name)
235
{
236
JSModuleDef *m;
237
238
m = JS_NewCModule(ctx, module_name, js_module_init);
239
if (!m) {
240
return NULL;
241
}
242
243
JS_AddModuleExportList(ctx, m, js_module_funcs,
244
countof(js_module_funcs));
245
246
return m;
247
}
248
</example>
249
</para>
250
251
<para>
252
To compile the native module:
253
<example>
254
gcc -fPIC -shared -I/path/to/quickjs -o mymodule.so mymodule.c
255
</example>
256
where <literal>/path/to/quickjs</literal> is the directory
257
containing the QuickJS header files.
258
</para>
259
260
<para>
261
<note>
262
For proper memory tracking, always use QuickJS memory allocation functions
263
(<literal>js_malloc</literal>, <literal>js_free</literal>)
264
instead of standard library functions
265
(<literal>malloc</literal>, <literal>free</literal>).
266
</note>
267
</para>
268
269
</section>
270
271
272
<section id="resources" name="Additional resources">
273
274
<para>
275
For more information about the QuickJS C API:
276
277
<list type="bullet">
278
279
<listitem>
280
<link url="https://bellard.org/quickjs/">QuickJS official website</link>
281
</listitem>
282
283
<listitem>
284
QuickJS header file (<literal>quickjs.h</literal>)
285
contains comprehensive API documentation
286
</listitem>
287
288
</list>
289
</para>
290
291
</section>
292
293
</article>
294
295