view xml/ru/docs/stream/ngx_stream_js_module.xml @ 3039:e6b785b7e308

Minor fixes in njs documentation.
author Yaroslav Zhuravlev <yar@nginx.com>
date Tue, 06 Feb 2024 08:52:52 +0000
parents c0a4a4a55e45
children
line wrap: on
line source

<?xml version="1.0"?>

<!--
  Copyright (C) Nginx, Inc.
  -->

<!DOCTYPE module SYSTEM "../../../../dtd/module.dtd">

<module name="Модуль ngx_stream_js_module"
        link="/ru/docs/stream/ngx_stream_js_module.html"
        lang="ru"
        rev="44">

<section id="summary">

<para>
Модуль <literal>ngx_stream_js_module</literal> позволяет задавать
обработчики на <link doc="../njs/index.xml">njs</link> —
подмножестве языка JavaScript.
</para>

<para>
Инструкция по сборке и установке доступны
<link doc="../njs/install.xml">здесь</link>.
</para>

</section>


<section id="example" name="Пример конфигурации">

<para>
Пример работает начиная с версии
<link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>.
<example>
stream {
    js_import stream.js;

    js_set $bar stream.bar;
    js_set $req_line stream.req_line;

    server {
        listen 12345;

        js_preread stream.preread;
        return     $req_line;
    }

    server {
        listen 12346;

        js_access  stream.access;
        proxy_pass 127.0.0.1:8000;
        js_filter  stream.header_inject;
    }
}

http {
    server {
        listen 8000;
        location / {
            return 200 $http_foo\n;
        }
    }
}
</example>
</para>

<para>
Файл <path>stream.js</path>:
<example>
var line = '';

function bar(s) {
    var v = s.variables;
    s.log("hello from bar() handler!");
    return "bar-var" + v.remote_port + "; pid=" + v.pid;
}

function preread(s) {
    s.on('upload', function (data, flags) {
        var n = data.indexOf('\n');
        if (n != -1) {
            line = data.substr(0, n);
            s.done();
        }
    });
}

function req_line(s) {
    return line;
}

// Чтение строки HTTP-запроса.
// Получение байт в 'req' до того как
// будет прочитана строка запроса.
// Добавление HTTP-заголовка в запрос клиента

var my_header =  'Foo: foo';
function header_inject(s) {
    var req = '';
    s.on('upload', function(data, flags) {
        req += data;
        var n = req.search('\n');
        if (n != -1) {
            var rest = req.substr(n + 1);
            req = req.substr(0, n + 1);
            s.send(req + my_header + '\r\n' + rest, flags);
            s.off('upload');
        }
    });
}

function access(s) {
    if (s.remoteAddress.match('^192.*')) {
        s.deny();
        return;
    }

    s.allow();
}

export default {bar, preread, req_line, header_inject, access};
</example>
</para>

</section>


<section id="directives" name="Директивы">

<directive name="js_access">
<syntax><value>функция</value> | <value>модуль.функция</value></syntax>
<default/>
<context>stream</context>
<context>server</context>

<para>
Задаёт функцию njs, которая будет вызываться в
<link doc="stream_processing.xml" id="access_phase">access</link>-фазе.
Начиная с <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
можно ссылаться на функцию модуля.
</para>

<para>
Функция вызывается однократно при первом достижении сессией
<link doc="stream_processing.xml" id="access_phase">access</link>-фазы.
Функция вызывается со следующими аргументами:

<list type="tag">
<tag-name><literal>s</literal></tag-name>
<tag-desc>
объект <link doc="../njs/reference.xml" id="stream">stream-сессии</link>
</tag-desc>

</list>
</para>

<para>
В этой фазе может происходить инициализация,
также при помощи метода
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
может регистрироваться вызов
для каждого входящего блока данных пока не будет вызван один из методов:
<link doc="../njs/reference.xml" id="s_done"><literal>s.done()</literal></link>
<link doc="../njs/reference.xml" id="s_decline"><literal>s.decline()</literal></link>,
<link doc="../njs/reference.xml" id="s_allow"><literal>s.allow()</literal></link>.
При вызове любого из этих методов обработка сессии
переходит на <link doc="stream_processing.xml">следующую фазу</link>
и все текущие вызовы
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
сбрасываются.
</para>

</directive>


<directive name="js_fetch_buffer_size">
<syntax><value>размер</value></syntax>
<default>16k</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.4</appeared-in>

<para>
Задаёт <value>размер</value> буфера, который будет использоваться
для чтения и записи для
<link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_fetch_ciphers">
<syntax><value>шифры</value></syntax>
<default>HIGH:!aNULL:!MD5</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.0</appeared-in>

<para>
Описывает разрешённые шифры для HTTPS-соединений
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
Шифры задаются в формате, поддерживаемом библиотекой OpenSSL.
</para>

<para>
Полный список можно посмотреть с помощью команды
“<command>openssl ciphers</command>”.
</para>

</directive>


<directive name="js_fetch_max_response_buffer_size">
<syntax><value>размер</value></syntax>
<default>1m</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.4</appeared-in>

<para>
Задаёт максимальный <value>размер</value> ответа, полученного
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_fetch_protocols">
<syntax>
    [<literal>TLSv1</literal>]
    [<literal>TLSv1.1</literal>]
    [<literal>TLSv1.2</literal>]
    [<literal>TLSv1.3</literal>]</syntax>
<default>TLSv1 TLSv1.1 TLSv1.2</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.0</appeared-in>

<para>
Разрешает указанные протоколы для HTTPS-соединений
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_fetch_timeout">
<syntax><value>время</value></syntax>
<default>60s</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.4</appeared-in>

<para>
Задаёт таймаут при чтении и записи
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
Таймаут устанавливается не на всю передачу ответа,
а только между двумя операциями чтения.
Если по истечении этого времени данные не передавались, соединение закрывается.
</para>

</directive>


<directive name="js_fetch_trusted_certificate">
<syntax><value>файл</value></syntax>
<default/>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.0</appeared-in>

<para>
Задаёт <value>файл</value> с доверенными сертификатами CA в формате PEM,
используемыми при
<link doc="../njs/reference.xml" id="fetch_verify">проверке</link>
HTTPS-сертификата
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_fetch_verify">
<syntax><literal>on</literal> | <literal>off</literal></syntax>
<default>on</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.4</appeared-in>

<para>
Разрешает или запрещает проверку сертификата HTTPS-сервера
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_fetch_verify_depth">
<syntax><value>число</value></syntax>
<default>100</default>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.0</appeared-in>

<para>
Устанавливает глубину проверки в цепочке HTTPS-сертификатов
при помощи <link doc="../njs/reference.xml" id="ngx_fetch">Fetch API</link>.
</para>

</directive>


<directive name="js_filter">
<syntax><value>функция</value> | <value>модуль.функция</value></syntax>
<default/>
<context>stream</context>
<context>server</context>

<para>
Задаёт фильтр данных.
Начиная с <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
можно ссылаться на функцию модуля.
Функция фильтра вызывается однократно при первом достижении сессией
<link doc="stream_processing.xml" id="content_phase">content</link>-фазы.
</para>

<para>
Функция фильтра вызывается со следующими аргументами:
<list type="tag">
<tag-name><literal>s</literal></tag-name>
<tag-desc>
объект <link doc="../njs/reference.xml" id="stream">stream-сессии</link>
</tag-desc>

</list>
</para>

<para>
В этой фазе может происходить инициализация,
также при помощи метода
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
может регистрироваться вызов
для каждого входящего блока данных.
Для отмены регистрации вызова и отмены фильтра
можно использовать метод
<link doc="../njs/reference.xml" id="s_off"><literal>s.off()</literal></link>.
</para>

<para>
<note>
Так как обработчик <literal>js_filter</literal>
должен сразу возвращать результат,
то поддерживаются только синхронные операции.
Таким образом, асинхронные операции, например
<link doc="../njs/reference.xml" id="ngx_fetch"><literal>ngx.fetch()</literal></link>
или
<link doc="../njs/reference.xml" id="settimeout"><literal>setTimeout()</literal></link>,
не поддерживаются.
</note>
</para>

</directive>


<directive name="js_import">
<syntax><value>модуль.js</value> |
<value>имя_экспорта from модуль.js</value></syntax>
<default/>
<context>stream</context>
<context>server</context>
<appeared-in>0.4.0</appeared-in>

<para>
Импортирует модуль, позволяющий задавать обработчики location и переменных
на njs.
<literal>Имя_экспорта</literal> является пространством имён
при доступе к функциям модуля.
Если <literal>имя_экспорта</literal> не задано,
то пространством имён будет являться имя модуля.
<example>
js_import stream.js;
</example>
В примере при доступе к экспорту в качестве
пространства имён используется имя модуля <literal>stream</literal>.
Если импортируемый модуль экспортирует <literal>foo()</literal>,
то для доступа используется <literal>stream.foo</literal>.
</para>

<para>
Директив <literal>js_import</literal> может быть несколько.
</para>

<para>
<note>
Директива может быть указана
на уровне <literal>server</literal>
начиная с <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>

</directive>


<directive name="js_include">
<syntax><value>файл</value></syntax>
<default/>
<context>stream</context>

<para>
Задаёт файл, который позволяет задавать обработчики server и переменных на njs:
<example>
nginx.conf:
js_include stream.js;
js_set     $js_addr address;
server {
    listen 127.0.0.1:12345;
    return $js_addr;
}

stream.js:
function address(s) {
    return s.remoteAddress;
}
</example>
</para>

<para>
Директива устарела в версии
<link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
и была удалена в версии
<link doc="../njs/changes.xml" id="njs0.7.1">0.7.1</link>.
Вместо неё следует использовать директиву <link id="js_import"/>.
</para>

</directive>


<directive name="js_preload_object">
<syntax><value>имя.json</value> |
<value>имя</value> from <value>файл.json</value></syntax>
<default/>
<context>stream</context>
<context>server</context>
<appeared-in>0.7.8</appeared-in>

<para>
Предварительно загружает
<link doc="../njs/preload_objects.xml">неизменяемый объект</link>
во время конфигурации.
<literal>Имя</literal> используется в качестве имени глобальной переменной,
через которую объект доступен в коде njs.
Если <literal>имя</literal> не указано,
то будет использоваться имя файла.
<example>
js_preload_object map.json;
</example>
В примере <literal>map</literal> используется в качестве имени
во время доступа к предварительно загруженному объекту.
</para>

<para>
Директив <literal>js_preload_object</literal> может быть несколько.
</para>

</directive>


<directive name="js_preread">
<syntax><value>функция</value> | <value>модуль.функция</value></syntax>
<default/>
<context>stream</context>
<context>server</context>

<para>
Задаёт функцию njs, которая будет вызываться в
<link doc="stream_processing.xml" id="preread_phase">preread</link>-фазе.
Начиная с <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
можно ссылаться на функцию модуля.
</para>

<para>
Функция вызывается однократно при первом достижении сессией
<link doc="stream_processing.xml" id="preread_phase">preread</link>-фазы.
Функция вызывается со следующими аргументами:

<list type="tag">
<tag-name><literal>s</literal></tag-name>
<tag-desc>
объект <link doc="../njs/reference.xml" id="stream">stream-сессии</link>
</tag-desc>

</list>
</para>

<para>
В этой фазе может происходить инициализация,
также при помощи метода
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
может регистрироваться вызов
для каждого входящего блока данных пока не будет вызван один из методов:
<link doc="../njs/reference.xml" id="s_done"><literal>s.done()</literal></link>
<link doc="../njs/reference.xml" id="s_decline"><literal>s.decline()</literal></link>,
<link doc="../njs/reference.xml" id="s_allow"><literal>s.allow()</literal></link>.
При вызове любого из этих методов обработка сессии
переходит на <link doc="stream_processing.xml">следующую фазу</link>
и все текущие вызовы
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
сбрасываются.
</para>

<para>
<note>
Так как обработчик <literal>js_preread</literal>
должен сразу возвращать результат,
то поддерживаются только синхронные операции.
Таким образом, асинхронные операции, например
<link doc="../njs/reference.xml" id="ngx_fetch"><literal>ngx.fetch()</literal></link>
или
<link doc="../njs/reference.xml" id="settimeout"><literal>setTimeout()</literal></link>,
не поддерживаются.
Тем не менее асинхронные операции поддерживаются в вызовах
<link doc="../njs/reference.xml" id="s_on"><literal>s.on()</literal></link>
в
<link doc="stream_processing.xml" id="preread_phase">preread</link>-фазе.
Подробнее см.
<link url="https://github.com/nginx/njs-examples#authorizing-connections-using-ngx-fetch-as-auth-request-stream-auth-request">пример</link>.
</note>
</para>

</directive>


<directive name="js_path">
<syntax>
<value>путь</value></syntax>
<default/>
<context>stream</context>
<context>server</context>
<appeared-in>0.3.0</appeared-in>

<para>
Задаёт дополнительный путь для модулей njs.
</para>

<para>
<note>
Директива может быть указана
на уровне <literal>server</literal>
начиная с <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>

</directive>


<directive name="js_periodic">
<syntax><value>функция</value> |
        <value>модуль.функция</value>
        [<literal>interval</literal>=<value>время</value>]
        [<literal>jitter</literal>=<value>число</value>]
        [<literal>worker_affinity</literal>=<value>маска</value>]</syntax>
<default/>
<context>server</context>
<appeared-in>0.8.1</appeared-in>

<para>
Задаёт периодичность запуска обработчика содержимого.
В качестве первого аргумента обработчик получает
<link doc="../njs/reference.xml" id="periodic_session">объект сессии</link>,
также у обработчика есть доступ к глобальным объектам таким как
<link doc="../njs/reference.xml" id="ngx">ngx</link>.
</para>

<para>
Необязательный параметр <literal>interval</literal>
задаёт интервал между двумя последовательными запусками,
по умолчанию 5 секунд.
</para>

<para>
Необязательный параметр <literal>jitter</literal>
задаёт время, в пределах которого
случайным образом задерживается каждый запуск,
по умолчанию задержки нет.
</para>

<para>
По умолчанию <literal>js_handler</literal> выполняется для рабочего процесса 0.
Необязательный параметр <literal>worker_affinity</literal>
позволяет указать рабочий процесс,
для которого будет выполняться обработчик содержимого location.
Рабочие процессы задаются битовой маской разрешённых к использованию рабочих
процессов.
Маска <literal>all</literal> позволяет обработчику выполняться
для всех рабочих процессов.
</para>

<para>
Пример:
<example>
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);
}
</example>
</para>

</directive>


<directive name="js_set">
<syntax>
<value>$переменная</value> <value>функция</value> |
<value>модуль.функция</value></syntax>
<default/>
<context>stream</context>
<context>server</context>

<para>
Задаёт <literal>функцию</literal> njs
для указанной <literal>переменной</literal>.
Начиная с <link doc="../njs/changes.xml" id="njs0.4.0">0.4.0</link>
можно ссылаться на функцию модуля.
</para>

<para>
Функция вызывается в момент
первого обращения к переменной для данного запроса.
Точный момент вызова функции зависит от
<link doc="stream_processing.xml">фазы</link>,
в которой происходит обращение к переменной.
Это можно использовать для реализации дополнительной логики,
не относящейся к вычислению переменной.
Например, если переменная указана
в директиве <link doc="ngx_stream_log_module.xml" id="log_format"/>,
то её обработчик не будет выполняться до фазы записи в лог.
Этот обработчик также может использоваться для выполнения процедур
непосредственно перед освобождением запроса.
</para>

<para>
<note>
Так как обработчик <literal>js_set</literal>
должен сразу возвращать результат,
то поддерживаются только синхронные операции.
Таким образом, асинхронные операции, например
<link doc="../njs/reference.xml" id="ngx_fetch"><literal>ngx.fetch()</literal></link>
или
<link doc="../njs/reference.xml" id="settimeout"><literal>setTimeout()</literal></link>,
не поддерживаются.
</note>
</para>

<para>
<note>
Директива может быть указана
на уровне <literal>server</literal>
начиная с <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>

</directive>


<directive name="js_shared_dict_zone">
<syntax>
    <literal>zone</literal>=<value>имя</value>:<value>размер</value>
    [<literal>timeout</literal>=<value>время</value>]
    [<literal>type</literal>=<literal>строка</literal>|<literal>число</literal>]
    [<literal>evict</literal>]</syntax>
<default/>
<context>stream</context>
<appeared-in>0.8.0</appeared-in>

<para>
Задаёт <value>имя</value> и <value>размер</value> зоны разделяемой памяти,
в которой хранится
<link doc="../njs/reference.xml" id="dict">словарь</link> ключей и значений,
разделяемый между рабочими процессами.
</para>

<para>
По умолчанию в качестве ключа и значения используется строка.
Необязательный параметр <literal>type</literal>
позволяет изменить тип значения на число.
</para>

<para>
Необязательный параметр <literal>timeout</literal> задаёт время,
по завершении которого все записи в словаре удаляются из зоны.
</para>

<para>
Необязательный параметр <literal>evict</literal> удаляет самую старую
пару ключ-значение при переполнении зоны.
</para>

<para>
Пример:
<example>
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));
    }
</example>
</para>

</directive>


<directive name="js_var">
<syntax><value>$переменная</value> [<value>значение</value>]</syntax>
<default/>
<context>stream</context>
<context>server</context>
<appeared-in>0.5.3</appeared-in>

<para>
Объявляет
<link doc="../njs/reference.xml" id="r_variables">перезаписываемую</link>
переменную.
В качестве значения можно использовать текст, переменные и их комбинации.
</para>

<para>
<note>
Директива может быть указана
на уровне <literal>server</literal>
начиная с <link doc="../njs/changes.xml" id="njs0.7.7">0.7.7</link>.
</note>
</para>

</directive>

</section>


<section id="properties" name="Свойства объекта сессии">

<para>
Каждый stream-обработчик njs получает один аргумент,
<link doc="../njs/reference.xml" id="stream">объект</link> stream-сессии.
</para>

</section>

</module>