Модуль ngx_http_js_module
Модуль ngx_http_js_module позволяет задавать
обработчики location и переменных
на njs —
подмножестве языка JavaScript.
Инструкция по сборке и установке доступны здесь.
Пример конфигурации
Пример работает начиная с версии 0.4.0.
http {
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;
}
# начиная с версии 0.7.0
location = /fetch {
js_content http.fetch;
js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
}
# начиная с версии 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!");
}
// начиная с версии 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));
}
// начиная с версии 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 |
|---|---|
| Умолчание: | — |
| Контекст: |
location, if in location, limit_except |
Эта директива появилась в версии 0.5.2.
Задаёт функцию njs в качестве фильтра тела ответа. Функция фильтра вызывается для каждого блока данных тела ответа со следующими аргументами:
r- объект HTTP request
data-
входящий блок данных
может быть строкой или буфером
в зависимости от значения
buffer_type, по умолчанию является строкой. flags-
объект со следующими свойствами:
last- логическое значение, true, если данные являются последним буфером.
Функция фильтра может передавать свою модифицированную версию
входящего блока данных следующему фильтру тела ответа при помощи вызова
r.sendBuffer().
Пример преобразования букв в нижний регистр в теле ответа:
function filter(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}
Для отмены фильтра (блоки данных будут передаваться клиенту
без вызова js_body_filter),
можно использовать
r.done().
Если функция фильтра изменяет длину тела ответа, то
необходимо очистить заголовок ответа “Content-Length”
(если присутствует) в
js_header_filter,
чтобы применить поблочное кодирование.
Так как обработчик js_body_filter
должен сразу возвращать результат,
то поддерживаются только синхронные операции,
Таким образом, асинхронные операции, например
r.subrequest()
или
setTimeout(),
не поддерживаются.
Директива может быть указана внутри блока if начиная с 0.7.7.
| Синтаксис: |
js_content |
|---|---|
| Умолчание: | — |
| Контекст: |
location, if in location, limit_except |
Задаёт функцию njs в качестве обработчика содержимого location. Начиная с версии 0.4.0 можно ссылаться на функцию модуля.
Директива может быть указана внутри блока if начиная с 0.7.7.
| Синтаксис: |
js_context_reuse |
|---|---|
| Умолчание: |
js_context_reuse 128; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.8.6.
Задаёт максимальное число контекстов JS для повторного использования движке QuickJS. Каждый контекст используется для одного запроса. Завершённый контекст помещается в пул повторно используемых контекстов. Если пул заполнен, контекст уничтожается.
| Синтаксис: |
js_engine |
|---|---|
| Умолчание: |
js_engine njs; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.8.6.
Задаёт движок JavaScript
для использования в сценариях njs.
Параметр njs задаёт использование движка njs,
также используемого по умолчанию.
Параметр qjs задаёт использование движка QuickJS.
| Синтаксис: |
js_fetch_buffer_size |
|---|---|
| Умолчание: |
js_fetch_buffer_size 16k; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.4.
Задаёт размер буфера, который будет использоваться
для чтения и записи для
Fetch API.
| Синтаксис: |
js_fetch_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 |
|---|---|
| Умолчание: |
js_fetch_max_response_buffer_size 1m; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.4.
Задаёт максимальный размер ответа, полученного
при помощи Fetch API.
| Синтаксис: |
js_fetch_protocols
[ |
|---|---|
| Умолчание: |
js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.0.
Разрешает указанные протоколы для HTTPS-запросов при помощи Fetch API.
| Синтаксис: |
js_fetch_timeout |
|---|---|
| Умолчание: |
js_fetch_timeout 60s; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.4.
Задаёт таймаут при чтении и записи при помощи Fetch API. Таймаут устанавливается не на всю передачу ответа, а только между двумя операциями чтения. Если по истечении этого времени данные не передавались, соединение закрывается.
| Синтаксис: |
js_fetch_trusted_certificate |
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.0.
Задаёт файл с доверенными сертификатами CA в формате PEM,
используемыми при
проверке
HTTPS-сертификата
при помощи Fetch API.
| Синтаксис: |
js_fetch_verify |
|---|---|
| Умолчание: |
js_fetch_verify on; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.4.
Разрешает или запрещает проверку сертификата HTTPS-сервера при помощи Fetch API.
| Синтаксис: |
js_fetch_verify_depth |
|---|---|
| Умолчание: |
js_fetch_verify_depth 100; |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.0.
Устанавливает глубину проверки в цепочке HTTPS-сертификатов при помощи Fetch API.
| Синтаксис: |
js_header_filter |
|---|---|
| Умолчание: | — |
| Контекст: |
location, if in location, limit_except |
Эта директива появилась в версии 0.5.1.
Задаёт функцию njs в качестве фильтра заголовка ответа. Директива позволяет менять произвольные поля заголовка ответа.
Так как обработчик js_header_filter
должен сразу возвращать результат,
то поддерживаются только синхронные операции,
Таким образом, асинхронные операции, например
r.subrequest()
или
setTimeout(),
не поддерживаются.
Директива может быть указана внутри блока if начиная с 0.7.7.
| Синтаксис: |
js_import |
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.4.0.
Импортирует модуль, позволяющий задавать обработчики location и переменных
на njs.
Имя_экспорта является пространством имён
при доступе к функциям модуля.
Если имя_экспорта не задано,
то пространством имён будет являться имя модуля.
js_import http.js;
В примере при доступе к экспорту в качестве
пространства имён используется имя модуля http.
Если импортируемый модуль экспортирует foo(),
то для доступа используется http.foo.
Директив js_import может быть несколько.
Директива может быть указана на уровнеserverиlocationначиная с 0.7.7.
| Синтаксис: |
js_include |
|---|---|
| Умолчание: | — |
| Контекст: |
http |
Задаёт файл, позволяющий задавать обработчики location и переменных на 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_path
|
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.3.0.
Задаёт дополнительный путь для модулей njs.
Директива может быть указана на уровнеserverиlocationначиная с 0.7.7.
| Синтаксис: |
js_periodic |
|---|---|
| Умолчание: | — |
| Контекст: |
location |
Эта директива появилась в версии 0.8.1.
Задаёт периодичность запуска обработчика содержимого. В качестве первого аргумента обработчик получает объект сессии, также у обработчика есть доступ к глобальным объектам таким как ngx.
Необязательный параметр interval
задаёт интервал между двумя последовательными запусками,
по умолчанию 5 секунд.
Необязательный параметр jitter
задаёт время, в пределах которого
случайным образом задерживается каждый запуск,
по умолчанию задержки нет.
По умолчанию js_handler выполняется для рабочего процесса 0.
Необязательный параметр worker_affinity
позволяет указать рабочий процесс,
для которого будет выполняться обработчик содержимого location.
Рабочие процессы задаются битовой маской разрешённых к использованию рабочих
процессов.
Маска all позволяет обработчику выполняться
для всех рабочих процессов.
Пример:
example.conf:
location @periodics {
# интервал выполнения 1 минута для рабочего процесса 0
js_periodic main.handler interval=60s;
# интервал выполнения 1 минута для всех рабочих процессов
js_periodic main.handler interval=60s worker_affinity=all;
# интервал выполнения 1 минута для рабочих процессов 1 и 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 |
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.7.8.
Предварительно загружает
неизменяемый объект
во время конфигурации.
Имя используется в качестве имени глобальной переменной,
через которую объект доступен в коде njs.
Если имя не указано,
то будет использоваться имя файла.
js_preload_object map.json;
В примере map используется в качестве имени
во время доступа к предварительно загруженному объекту.
Директив js_preload_object может быть несколько.
| Синтаксис: |
js_set
|
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Задаёт функцию njs
для указанной переменной.
Начиная с 0.4.0
можно ссылаться на функцию модуля.
Функция вызывается в момент первого обращения к переменной для данного запроса. Точный момент вызова функции зависит от фазы, в которой происходит обращение к переменной. Это можно использовать для реализации дополнительной логики, не относящейся к вычислению переменной. Например, если переменная указана в директиве log_format, то её обработчик не будет выполняться до фазы записи в лог. Этот обработчик также может использоваться для выполнения процедур непосредственно перед освобождением запроса.
Начиная с 0.8.6,
если указан необязательный параметр nocache, то
обработчик выполняется каждый раз при обращении к переменной.
Из-за ограничения модуля rewrite
при обращении к nocache-переменной при помощи
директивы set,
обработчик должен возвращать значение фиксированной длины.
Так как обработчик js_set
должен сразу возвращать результат,
то поддерживаются только синхронные операции,
Таким образом, асинхронные операции, например
r.subrequest()
или
setTimeout(),
не поддерживаются.
Директива может быть указана на уровнеserverиlocationначиная с 0.7.7.
| Синтаксис: |
js_shared_dict_zone
|
|---|---|
| Умолчание: | — |
| Контекст: |
http |
Эта директива появилась в версии 0.8.0.
Задаёт имя и размер зоны разделяемой памяти,
в которой хранится
словарь ключей и значений,
разделяемый между рабочими процессами.
По умолчанию в качестве ключа и значения используется строка.
Необязательный параметр type
позволяет изменить тип значения на число.
Необязательный параметр timeout задаёт время в миллисекундах,
по завершении которого все записи в словаре удаляются из зоны.
Если для части записей требуется другое время удаления,
его можно задать при помощи аргумента timeout
методов
add,
incr и
set
(0.8.5).
Необязательный параметр evict удаляет самую старую
пару ключ-значение при переполнении зоны.
Пример:
example.conf:
# Создаётся словарь размером 1Мб со строковыми значениями,
# пары ключ-значение удаляются при отсутствии активности в течение 60 секунд:
js_shared_dict_zone zone=foo:1M timeout=60s;
# Создаётся словарь размером 512Кб со строковыми значениями,
# удаляется самая старая пара ключ-значение при переполнении зоны:
js_shared_dict_zone zone=bar:512K timeout=30s evict;
# Создаётся постоянный словарь размером 32Кб с числовыми значениями:
js_shared_dict_zone zone=num:32k type=number;
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 |
|---|---|
| Умолчание: | — |
| Контекст: |
http, server, location |
Эта директива появилась в версии 0.5.3.
Объявляет перезаписываемую переменную. В качестве значения можно использовать текст, переменные и их комбинации. Переменная не перезаписывается после перенаправления, в отличие от переменных, созданных при помощи директивы set.
Директива может быть указана на уровнеserverиlocationначиная с 0.7.7.
Аргумент запроса
Каждый HTTP-обработчик njs получает один аргумент, объект запроса.