Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
nginx
GitHub Repository: nginx/nginx.org
Path: blob/main/xml/ru/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="Нативные модули"
10
link="/ru/docs/njs/native_modules.html"
11
lang="ru"
12
rev="1">
13
14
<section id="intro" name="Обзор">
15
16
<para>
17
Нативные модули позволяют загружать разделяемые библиотеки на основе C
18
(файлы .so) в NGINX JavaScript для выполнения критичных по производительности
19
операций или системных интеграций.
20
Данная возможность доступна только с
21
<link doc="engine.xml" id="quickjs_engine">движком QuickJS</link>
22
и не поддерживается встроенным движком njs.
23
Поддержка нативных модулей доступна
24
начиная с версии <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="Когда использовать нативные модули">
31
32
<para>
33
Нативные модули могут использоваться в следующих случаях:
34
35
<list type="bullet">
36
37
<listitem>
38
Критичные по производительности операции, превышающие возможности JavaScript
39
</listitem>
40
41
<listitem>
42
Системные интеграции, требующие использования библиотек на C
43
</listitem>
44
45
<listitem>
46
Задействование существующих кодовых баз на C/C++
47
</listitem>
48
49
</list>
50
</para>
51
52
<para>
53
Нативные модули следует использовать для низкоуровневых примитивов,
54
а не для сложной бизнес-логики, например для
55
криптографических операций (хеширование, шифрование),
56
сжатия/распаковки данных, разбора бинарных протоколов,
57
высокопроизводительных строковых операций или математических вычислений.
58
Сложная логика приложения должна оставаться в JavaScript,
59
где её легче сопровождать, отлаживать и изменять.
60
</para>
61
62
<para>
63
Ограничения:
64
65
<list type="bullet">
66
67
<listitem>
68
Нативные модули должны быть скомпилированы для той же архитектуры, что и NGINX
69
</listitem>
70
71
<listitem>
72
Нативные модули работают с полными привилегиями процесса
73
и требуют тщательной проверки безопасности
74
</listitem>
75
76
</list>
77
</para>
78
79
</section>
80
81
82
<section id="loading" name="Загрузка нативных модулей в NGINX">
83
84
<para>
85
Нативные модули загружаются с помощью следующих директив,
86
указанных в контексте <literal>main</literal>:
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> для контекста HTTP
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> для контекста Stream
98
</listitem>
99
100
</list>
101
</para>
102
103
<para>
104
Пример конфигурации:
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
После загрузки модуль можно импортировать в JavaScript-коде:
124
<example>
125
// Импорт по имени файла
126
import * as mylib from 'mylib.so';
127
128
// Импорт по псевдониму
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="Сборка нативных модулей">
144
145
<para>
146
Нативные модули должны реализовывать функцию <literal>js_init_module</literal>
147
в качестве точки входа.
148
Эта функция вызывается QuickJS при загрузке модуля.
149
</para>
150
151
<para>
152
Пример простого нативного модуля,
153
экспортирующего две функции:
154
<example>
155
#include &lt;quickjs.h&gt;
156
157
#define countof(x) (sizeof(x) / sizeof((x)[0]))
158
159
/* Сложение двух чисел */
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
/* Переворот строки */
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
/* Список функций модуля */
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
/* Инициализация модуля */
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
/* Обязательная точка входа */
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
Для компиляции нативного модуля:
253
<example>
254
gcc -fPIC -shared -I/path/to/quickjs -o mymodule.so mymodule.c
255
</example>
256
где <literal>/path/to/quickjs</literal> — каталог,
257
содержащий заголовочные файлы QuickJS.
258
</para>
259
260
<para>
261
<note>
262
Для корректного учёта памяти всегда используйте функции выделения памяти QuickJS
263
(<literal>js_malloc</literal>, <literal>js_free</literal>)
264
вместо функций стандартной библиотеки
265
(<literal>malloc</literal>, <literal>free</literal>).
266
</note>
267
</para>
268
269
</section>
270
271
272
<section id="resources" name="Дополнительные ресурсы">
273
274
<para>
275
Для получения дополнительной информации о C API QuickJS:
276
277
<list type="bullet">
278
279
<listitem>
280
<link url="https://bellard.org/quickjs/">Официальный сайт QuickJS</link>
281
</listitem>
282
283
<listitem>
284
Заголовочный файл QuickJS (<literal>quickjs.h</literal>)
285
содержит полную документацию по API
286
</listitem>
287
288
</list>
289
</para>
290
291
</section>
292
293
</article>
294
295