Модуль 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
, по умолчанию является строкой. Начиная с 0.8.5, по умолчанию значениеdata
неявно преобразуется в валидную строку UTF-8. Для бинарных данных параметрbuffer_type
необходимо установить вbuffer
. 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_fetch_keepalive |
---|---|
Умолчание: |
js_fetch_keepalive 0; |
Контекст: |
http , server , location |
Эта директива появилась в версии 0.9.2.
Активирует кэш для соединений с серверами назначения.
Если значение больше 0
,
включает keepalive-соединения для
Fetch API.
Параметр соединения
задаёт максимальное количество
неактивных keepalive-соединений с серверами назначения,
которые сохраняются в кэше каждого рабочего процесса.
Если это количество превышено, наименее недавно использованные соединения закрываются.
Пример:
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 |
---|---|
Умолчание: |
js_fetch_keepalive_requests 1000; |
Контекст: |
http , server , location |
Эта директива появилась в версии 0.9.2.
Задаёт максимальное количество запросов, которые могут быть обслужены через одно keepalive-соединение при помощи Fetch API. После выполнения максимального количества запросов соединение закрывается.
Периодическое закрытие соединений необходимо для освобождения выделенной под соединение памяти. Поэтому использование слишком большого максимального количества запросов может привести к чрезмерному потреблению памяти и не рекомендуется.
Синтаксис: |
js_fetch_keepalive_time |
---|---|
Умолчание: |
js_fetch_keepalive_time 1h; |
Контекст: |
http , server , location |
Эта директива появилась в версии 0.9.2.
Ограничивает максимальное время, в течение которого запросы могут обрабатываться через одно keepalive-соединение при помощи Fetch API. По истечении этого времени соединение закрывается после обработки очередного запроса.
Синтаксис: |
js_fetch_keepalive_timeout |
---|---|
Умолчание: |
js_fetch_keepalive_timeout 60s; |
Контекст: |
http , server , location |
Эта директива появилась в версии 0.9.2.
Задаёт таймаут, в течение которого неактивное keepalive-соединение с сервером назначения остается открытым при помощи 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 получает один аргумент, объект запроса.