Модуль ngx_http_js_module
- Пример конфигурации
- Директивы
- js_body_filter
- js_access
- js_content
- js_context_reuse
- js_engine
- js_fetch_buffer_size
- js_fetch_ciphers
- js_fetch_max_response_buffer_size
- js_fetch_protocols
- js_fetch_timeout
- js_fetch_trusted_certificate
- js_fetch_verify
- js_fetch_verify_depth
- js_fetch_proxy
- js_fetch_keepalive
- js_fetch_keepalive_requests
- js_fetch_keepalive_time
- js_fetch_keepalive_timeout
- js_header_filter
- js_import
- js_include
- js_load_http_native_module
- js_path
- js_periodic
- js_preload_object
- js_set
- js_shared_dict_zone
- js_var
- Аргумент запроса
Модуль ngx_http_js_module используется для реализации обработчиков расположений и переменных в njs — подмножестве языка JavaScript.
Инструкции по загрузке и установке доступны здесь.
Пример конфигурации
Пример работает начиная с версии 0.4.0.
http {
# since 0.9.1
js_engine qjs;
js_import http.js;
js_set $foo http.foo;
js_set $summary http.summary;
js_set $hash http.hash;
resolver 10.0.0.1;
server {
listen 8000;
location / {
add_header X-Foo $foo;
js_content http.baz;
}
location = /summary {
return 200 $summary;
}
location = /hello {
js_content http.hello;
}
# since 0.7.0
location = /fetch {
js_content http.fetch;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
# since 0.7.0
location = /crypto {
add_header Hash $hash;
return 200;
}
}
}
Файл http.js:
function foo(r) {
r.log("hello from foo() handler");
return "foo";
}
function summary(r) {
var a, s, h;
s = "JS summary\n\n";
s += "Method: " + r.method + "\n";
s += "HTTP version: " + r.httpVersion + "\n";
s += "Host: " + r.headersIn.host + "\n";
s += "Remote Address: " + r.remoteAddress + "\n";
s += "URI: " + r.uri + "\n";
s += "Headers:\n";
for (h in r.headersIn) {
s += " header '" + h + "' is '" + r.headersIn[h] + "'\n";
}
s += "Args:\n";
for (a in r.args) {
s += " arg '" + a + "' is '" + r.args[a] + "'\n";
}
return s;
}
function baz(r) {
r.status = 200;
r.headersOut.foo = 1234;
r.headersOut['Content-Type'] = "text/plain; charset=utf-8";
r.headersOut['Content-Length'] = 15;
r.sendHeader();
r.send("nginx");
r.send("java");
r.send("script");
r.finish();
}
function hello(r) {
r.return(200, "Hello world!");
}
// since 0.7.0
async function fetch(r) {
let results = await Promise.all([ngx.fetch('https://nginx.org/'),
ngx.fetch('https://nginx.org/en/')]);
r.return(200, JSON.stringify(results, undefined, 4));
}
// since 0.7.0
async function hash(r) {
let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
r.setReturnValue(Buffer.from(hash).toString('hex'));
}
export default {foo, summary, baz, hello, fetch, hash};
Директивы
| Синтаксис: | js_body_filter module.function
[buffer_type=string | buffer]; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | location, if in location, limit_except |
Директива появилась в версии 0.5.2.
Назначает функцию njs фильтром тела ответа. Функция фильтра вызывается для каждого блока данных тела ответа со следующими аргументами:
r- объект HTTP-запроса
data- входящий блок данных; в зависимости от значения
buffer_typeэто может быть строка или Buffer, по умолчанию — строка. Начиная с версии 0.8.5, значениеdataпо умолчанию неявно преобразуется в допустимую строку UTF-8. Для двоичных данных следует задать значениеbuffer_typeравнымbuffer. flags- объект со следующими свойствами:
last- логическое значение: true, если это последний буфер данных.
Функция фильтра может передать следующему фильтру тела собственную изменённую версию входящего блока данных, вызвав r.sendBuffer(). Например, чтобы преобразовать все строчные буквы в теле ответа:
function filter(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}
Если функция фильтра изменяет длину тела ответа, заголовок ответа «Content-Length» (если он присутствует) следует очистить в js_header_filter, чтобы включить передачу с кодированием chunked:
example.conf:
location /foo {
# proxy_pass http://localhost:8080;
js_header_filter main.clear_content_length;
js_body_filter main.filter;
}
example.js:
function clear_content_length(r) {
delete r.headersOut['Content-Length'];
}
Чтобы прекратить фильтрацию и передать блоки данных клиенту, не вызывая js_body_filter, можно использовать r.done(). Например, чтобы добавить данные в начало тела ответа:
function prepend(r, data, flags) {
r.sendBuffer("XXX");
r.sendBuffer(data, flags);
r.done();
}
Поскольку обработчик js_body_filter немедленно возвращает результат, он поддерживает только синхронные операции. Поэтому асинхронные операции, такие как r.subrequest() или setTimeout(), не поддерживаются.
Директиву можно указывать внутри блока if начиная с версии 0.7.7.
| Синтаксис: | js_access module.function; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | location, if in location, limit_except |
Директива появилась в версии 0.9.9.
Назначает функцию njs обработчиком в фазе доступа. Поддерживаются асинхронные операции, такие как r.subrequest(), ngx.fetch() и setTimeout().
Обработчик, который возвращает управление, не вызывая r.return() или r.decline(), разрешает доступ. Чтобы запретить доступ или отправить собственный ответ (например, перенаправление), обработчик может вызвать r.return(). Чтобы обработчик не выносил решения и передал его другим проверяющим доступ согласно директиве satisfy any, он может вызвать r.decline().
Например:
example.conf:
location /protected/ {
js_access main.auth;
proxy_pass http://upstream;
}
example.js:
async function auth(r) {
let reply = await ngx.fetch('http://authsvc/check', {
headers: {Authorization: r.headersIn.Authorization}
});
if (reply.status != 200) {
r.return(401);
return;
}
}
export default {auth};
| Синтаксис: | js_content module.function; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | location, if in location, limit_except |
Назначает функцию njs обработчиком содержимого расположения. Начиная с версии 0.4.0, можно ссылаться на функцию модуля.
Директиву можно указывать внутри блока if начиная с версии 0.7.7.
| Синтаксис: | js_context_reuse number; |
|---|---|
| Значение по умолчанию: | js_context_reuse 128; |
| Контекст: | http, server, location |
Директива появилась в версии 0.8.6.
Задаёт максимальное число контекстов JS, которые можно повторно использовать в движке QuickJS. Каждый контекст используется для одного запроса. Завершивший работу контекст помещается в пул повторно используемых контекстов. Если пул заполнен, контекст уничтожается.
| Синтаксис: | js_engine njs | qjs; |
|---|---|
| Значение по умолчанию: | js_engine njs; |
| Контекст: | http, server, location |
Директива появилась в версии 0.8.6.
Задаёт движок JavaScript, который будет использоваться для скриптов njs. Параметр njs задаёт движок njs, используемый также по умолчанию. Параметр qjs задаёт движок QuickJS.
Движокnjsобъявлен устаревшим начиная с версии 1.0.0; в новых конфигурациях следует использовать движокqjs(QuickJS).
| Синтаксис: | js_fetch_buffer_size size; |
|---|---|
| Значение по умолчанию: | js_fetch_buffer_size 16k; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.4.
Задаёт size буфера, используемого для чтения и записи с помощью Fetch API.
| Синтаксис: | js_fetch_ciphers ciphers; |
|---|---|
| Значение по умолчанию: | js_fetch_ciphers HIGH:!aNULL:!MD5; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.0.
Задаёт разрешённые шифры для HTTPS-запросов с помощью Fetch API. Шифры задаются в формате, поддерживаемом библиотекой OpenSSL.
Полный список можно просмотреть с помощью команды «openssl ciphers».
| Синтаксис: | js_fetch_max_response_buffer_size size; |
|---|---|
| Значение по умолчанию: | js_fetch_max_response_buffer_size 1m; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.4.
Задаёт максимальный size ответа, полученного с помощью Fetch API.
| Синтаксис: | js_fetch_protocols
[TLSv1]
[TLSv1.1]
[TLSv1.2]
[TLSv1.3]; |
|---|---|
| Значение по умолчанию: | js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.0.
Разрешает указанные протоколы для HTTPS-запросов с помощью Fetch API.
| Синтаксис: | js_fetch_timeout time; |
|---|---|
| Значение по умолчанию: | js_fetch_timeout 60s; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.4.
Задаёт тайм-аут чтения и записи для Fetch API. Тайм-аут применяется только между двумя последовательными операциями чтения/записи, а не ко всему ответу. Если за это время данные не передаются, соединение закрывается.
| Синтаксис: | js_fetch_trusted_certificate file; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.0.
Задаёт file с доверенными сертификатами CA в формате PEM, используемый для проверки сертификата HTTPS с помощью Fetch API.
| Синтаксис: | js_fetch_verify on | off; |
|---|---|
| Значение по умолчанию: | js_fetch_verify on; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.4.
Включает или отключает проверку сертификата HTTPS-сервера с помощью Fetch API.
| Синтаксис: | js_fetch_verify_depth number; |
|---|---|
| Значение по умолчанию: | js_fetch_verify_depth 100; |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.0.
Задаёт глубину проверки цепочки сертификатов HTTPS-сервера с помощью Fetch API.
| Синтаксис: | js_fetch_proxy url; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.9.4.
Настраивает URL прямого прокси-сервера для Fetch API. Параметр url поддерживает только схему HTTP и может содержать необязательные учётные данные пользователя в формате http://[user:password@]host:port для базовой аутентификации. Поддерживаются подключения по HTTP и HTTPS к серверам назначения. Если url пуст, маршрутизация через прокси отключена. Значение параметра может содержать переменные.
Пример:
location /fetch {
js_fetch_proxy http://user:pass@proxy.example.com:3128;
js_content main.fetch_handler;
}
| Синтаксис: | js_fetch_keepalive connections; |
|---|---|
| Значение по умолчанию: | js_fetch_keepalive 0; |
| Контекст: | http, server, location |
Директива появилась в версии 0.9.2.
Включает кэширование подключений к серверам назначения. Если значение больше 0, для Fetch API включаются постоянные соединения.
Параметр connections задаёт максимальное число простаивающих постоянных соединений с серверами назначения, сохраняемых в кэше каждого рабочего процесса. При превышении этого числа закрываются соединения, которые использовались дольше всего назад.
Пример:
location /fetch {
js_fetch_keepalive 32;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
js_content main.fetch_handler;
}
| Синтаксис: | js_fetch_keepalive_requests number; |
|---|---|
| Значение по умолчанию: | js_fetch_keepalive_requests 1000; |
| Контекст: | http, server, location |
Директива появилась в версии 0.9.2.
Задаёт максимальное число запросов, которые можно обработать через одно постоянное соединение с помощью Fetch API. После обработки максимального числа запросов соединение закрывается.
Периодически закрывать соединения необходимо для освобождения выделенной для них памяти. Поэтому слишком большое максимальное число запросов может привести к чрезмерному использованию памяти и не рекомендуется.
| Синтаксис: | js_fetch_keepalive_time time; |
|---|---|
| Значение по умолчанию: | js_fetch_keepalive_time 1h; |
| Контекст: | http, server, location |
Директива появилась в версии 0.9.2.
Ограничивает максимальное время, в течение которого запросы могут обрабатываться через одно постоянное соединение с помощью Fetch API. По истечении этого времени соединение закрывается после обработки следующего запроса.
| Синтаксис: | js_fetch_keepalive_timeout time; |
|---|---|
| Значение по умолчанию: | js_fetch_keepalive_timeout 60s; |
| Контекст: | http, server, location |
Директива появилась в версии 0.9.2.
Задаёт тайм-аут, в течение которого простаивающее постоянное соединение с сервером назначения остаётся открытым для Fetch API.
| Синтаксис: | js_header_filter module.function; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | location, if in location, limit_except |
Директива появилась в версии 0.5.1.
Назначает функцию njs фильтром заголовка ответа. Директива позволяет изменять произвольные поля заголовка ответа.
Поскольку обработчик js_header_filter немедленно возвращает результат, он поддерживает только синхронные операции. Поэтому асинхронные операции, такие как r.subrequest() или setTimeout(), не поддерживаются.
Директиву можно указывать внутри блока if начиная с версии 0.7.7.
| Синтаксис: | js_import module.js |
export_name from module.js; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.4.0.
Импортирует модуль, реализующий обработчики расположений и переменных в njs. Параметр export_name используется как пространство имён для доступа к функциям модуля. Если export_name не задан, в качестве пространства имён используется имя модуля.
js_import http.js;
Здесь имя модуля http используется как пространство имён при доступе к экспортируемым объектам. Если импортированный модуль экспортирует foo(), для обращения к нему используется http.foo.
Можно указать несколько директив js_import.
Если js_import указана внутри location, импортированные модули доступны только в том случае, если ранее в запросе не выполнялся код JavaScript. Для каждого запроса создаётся одна виртуальная машина при первом обращении к переменной js_set или первом вызове обработчика js_content, js_header_filter, js_body_filter или js_access. Виртуальная машина копируется из области конфигурации, активной в этот момент, и все последующие вызовы JavaScript в рамках запроса используют её повторно. Поэтому, если к любому из перечисленных выше обработчиков обращаются до того, как запрос сопоставлен с конечным расположением, например из директивы set уровня server, виртуальная машина привязывается к набору импортов внешней области, и модули, импортированные в соответствующем location, будут недоступны. Чтобы этого избежать, объявляйте такие импорты в общей родительской области.
Директиву можно указывать на уровнеserverиlocationначиная с версии 0.7.7.
| Синтаксис: | js_include file; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http |
Указывает файл, реализующий обработчики расположений и переменных в njs:
nginx.conf:
js_include http.js;
location /version {
js_content version;
}
http.js:
function version(r) {
r.return(200, njs.version);
}
Директива устарела в версии 0.4.0 и удалена в версии 0.7.1. Вместо неё следует использовать директиву js_import.
| Синтаксис: | js_load_http_native_module path [as name]; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | main |
Директива появилась в версии 0.9.5.
Загружает нативный модуль (разделяемую библиотеку) для использования в коде JavaScript HTTP. Директива доступна только в QuickJS и не работает при использовании встроенного движка JavaScript njs.
Параметр path задаёт абсолютный путь к файлу разделяемой библиотеки. Необязательный параметр as name задаёт псевдоним для импорта модуля в коде JavaScript. Если он не указан, модуль можно импортировать по имени файла.
Пример:
js_load_http_native_module /path/to/mylib.so;
js_load_http_native_module /path/to/other.so as myalias;
http {
js_import main.js;
# ... rest of http configuration
}
В коде JavaScript:
// Import by filename import * as mylib from 'mylib.so'; // Import by alias import * as myalias from 'myalias'; // Use exported functions let result = mylib.add(5, 10);
По соображениям безопасности эту директиву разрешено использовать только в контексте конфигурации main. Нативные модули выполняются с полными правами процесса; используйте абсолютные пути и тщательно проверяйте код.
| Синтаксис: | js_path
path; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.3.0.
Задаёт дополнительный путь для модулей njs.
Директиву можно указывать на уровнеserverиlocationначиная с версии 0.7.7.
| Синтаксис: | js_periodic module.function
[interval=time]
[jitter=number]
[worker_affinity=mask]; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | location |
Директива появилась в версии 0.8.1.
Задаёт обработчик содержимого, который запускается с регулярным интервалом. Первым аргументом обработчик получает объект сеанса; ему также доступны глобальные объекты, такие как ngx.
Необязательный параметр interval задаёт интервал между последовательными запусками; по умолчанию — 5 секунд.
Необязательный параметр jitter задаёт промежуток времени, в пределах которого запуск обработчика содержимого расположения будет случайным образом отложен; по умолчанию задержки нет.
По умолчанию js_handler выполняется в рабочем процессе 0. Необязательный параметр worker_affinity позволяет указать конкретные рабочие процессы, в которых должен выполняться обработчик содержимого расположения. Каждый набор рабочих процессов представлен битовой маской разрешённых рабочих процессов. Маска all позволяет выполнять обработчик во всех рабочих процессах.
Пример:
example.conf:
location @periodics {
# to be run at 1 minute intervals in worker process 0
js_periodic main.handler interval=60s;
# to be run at 1 minute intervals in all worker processes
js_periodic main.handler interval=60s worker_affinity=all;
# to be run at 1 minute intervals in worker processes 1 and 3
js_periodic main.handler interval=60s worker_affinity=0101;
resolver 10.0.0.1;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
example.js:
async function handler(s) {
let reply = await ngx.fetch('https://nginx.org/en/docs/njs/');
let body = await reply.text();
ngx.log(ngx.INFO, body);
}
| Синтаксис: | js_preload_object name.json |
name from file.json; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.7.8.
Предварительно загружает неизменяемый объект на этапе настройки. Параметр name используется как имя глобальной переменной, через которую объект доступен в коде njs. Если name не задан, вместо него используется имя файла.
js_preload_object map.json;
Здесь map используется как имя для доступа к предварительно загруженному объекту.
Можно указать несколько директив js_preload_object.
| Синтаксис: | js_set
$variable
module.function
[nocache]; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Назначает function njs указанной variable. Начиная с версии 0.4.0, можно ссылаться на функцию модуля.
Функция вызывается при первом обращении к переменной в рамках данного запроса. Точный момент зависит от фазы, в которой используется переменная. Это можно использовать для выполнения логики, не связанной с вычислением значения переменной. Например, если переменная используется только в директиве log_format, её обработчик будет выполнен только в фазе логирования. Этот обработчик можно использовать для очистки непосредственно перед освобождением запроса.
Начиная с версии 0.8.6, если указан необязательный аргумент nocache, обработчик вызывается при каждом обращении к переменной. Из-за текущих ограничений модуля rewrite, при использовании переменной nocache в директиве set её обработчик должен всегда возвращать значение фиксированной длины.
Поскольку обработчик js_set немедленно возвращает результат, он поддерживает только синхронные операции. Поэтому асинхронные операции, такие как r.subrequest() или setTimeout(), не поддерживаются.
Директиву можно указывать на уровнеserverиlocationначиная с версии 0.7.7.
Задаёт name и size зоны общей памяти, в которой хранится общий для рабочих процессов словарь «ключ-значение» .
По умолчанию в общем словаре для ключей и значений используются строки. Необязательный параметр type позволяет изменить тип значения на число.
Необязательный параметр timeout задаёт время в миллисекундах, по истечении которого все записи общего словаря удаляются из зоны. Для записей, которые нужно удалять через другое время, его можно задать аргументом timeout методов add, incr и set (0.8.5).
Необязательный параметр evict удаляет самую старую пару «ключ-значение», если пространство зоны исчерпано.
Необязательный параметр state задаёт file, который сохраняет состояние общего словаря в формате JSON и обеспечивает его сохранение после перезапуска nginx (0.9.1).
Пример:
example.conf:
# Creates a 1Mb dictionary with string values,
# removes key-value pairs after 60 seconds of inactivity:
js_shared_dict_zone zone=foo:1M timeout=60s;
# Creates a 512Kb dictionary with string values,
# forcibly removes oldest key-value pairs when the zone is exhausted:
js_shared_dict_zone zone=bar:512K timeout=30s evict;
# Creates a 32Kb permanent dictionary with number values:
js_shared_dict_zone zone=num:32k type=number;
# Creates a 1Mb dictionary with string values and persistent state:
js_shared_dict_zone zone=persistent:1M state=/tmp/dict.json;
example.js:
function get(r) {
r.return(200, ngx.shared.foo.get(r.args.key));
}
function set(r) {
r.return(200, ngx.shared.foo.set(r.args.key, r.args.value));
}
function del(r) {
r.return(200, ngx.shared.bar.delete(r.args.key));
}
function increment(r) {
r.return(200, ngx.shared.num.incr(r.args.key, 2));
}
| Синтаксис: | js_var $variable [value]; |
|---|---|
| Значение по умолчанию: | — |
| Контекст: | http, server, location |
Директива появилась в версии 0.5.3.
Объявляет доступную для записи переменную. Значение может содержать текст, переменные или их сочетание. В отличие от переменных, созданных директивой set, эта переменная не перезаписывается после перенаправления.
Директиву можно указывать на уровнеserverиlocationначиная с версии 0.7.7.
Аргумент запроса
Каждый обработчик HTTP njs получает один аргумент — объект запроса.
© 2002-2021 Igor Sysoev
© 2011-2026 Nginx, Inc.
Licensed under the BSD License.
https://nginx.org/en/docs/http/ngx_http_js_module.html