Модуль ngx_stream_js_module

Известные проблемы
Пример конфигурации
Директивы
     js_access
     js_filter
     js_include
     js_preread
     js_set
Свойства объекта сессии

Модуль ngx_stream_js_module позволяет задавать обработчики на nginScript — подмножестве языка JavaScript.

По умолчанию этот модуль не собирается, его необходимо собрать с модулем nginScript с помощью конфигурационного параметра --add_module:

./configure --add-module=path-to-njs/nginx

Репозиторий модуля nginScript можно клонировать следующей командой (необходим клиент Mercurial):

hg clone http://hg.nginx.org/njs

Модуль также можно собрать как динамический:

./configure --add-dynamic_module=path-to-njs/nginx

Известные проблемы

Модуль экспериментальный, поэтому возможно всё.

Пример конфигурации

stream {
    js_include stream.js;

    js_set $foo foo;
    js_set $bar bar;

    server {
        listen 12345;

        js_preread qux;
        return     $foo;
    }

    server {
        listen 12346;

        js_access  xyz;
        proxy_pass 127.0.0.1:8000;
        js_filter  baz;
    }
}

http {
    server {
        listen 8000;
        location / {
            return 200 $http_foo\n;
        }
    }
}

Файл stream.js:

var req = '';
var matched = 0;
var line = '';

function qux(s) {
    var n = s.buffer.indexOf('\n');
    if (n == -1) {
        return s.AGAIN;
    }

    line = s.buffer.substr(0, n);
}

function foo(s) {
    return line;
}

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

// Фильтр обрабатывает один буфер за вызов.
// Буфер недоступен в s.buffer для
// чтения и записи.  Вызывается в обоих направлениях.

function baz(s) {
    if (s.fromUpstream || matched) {
        return;
    }

    // Отключение определённых адресов.

    if (s.remoteAddress.match('^192.*')) {
        return s.ERROR;
    }

    // Чтение строки HTTP-запроса.
    // Получение байт в 'req' до того как
    // будет прочитана строка запроса.  Очистка текущего буфера
    // для отключения вывода.

    req = req + s.buffer;
    s.buffer = '';

    var n = req.search('\n');

    if (n != -1) {
        // Вставка нового HTTP-заголовка.
        var rest = req.substr(n + 1);
        req = req.substr(0, n + 1);

        var addr = s.remoteAddress;

        s.log('req:' + req);
        s.log('rest:' + rest);

        // Вывод результата и пропуск дальнейшей
        // обработки.

        s.buffer = req + 'Foo: addr_' + addr + '\r\n' + rest;
        matched = 1;
    }
}

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

Директивы

Синтаксис: js_access функция;
Умолчание:
Контекст: stream, server

Задаёт функцию nginScript, которая будет вызываться в access-фазе.

Синтаксис: js_filter функция;
Умолчание:
Контекст: stream, server

Задаёт фильтр данных.

Синтаксис: js_include файл;
Умолчание:
Контекст: stream

Задаёт файл, который позволяет задавать обработчики server и переменных на nginScript.

Синтаксис: js_preread функция;
Умолчание:
Контекст: stream, server

Задаёт функцию nginScript, которая будет вызываться в preread-фазе.

Синтаксис: js_set $переменная функция;
Умолчание:
Контекст: stream

Задаёт функцию nginScript для указанной переменной.

Свойства объекта сессии

Каждый stream-обработчик nginScript получает один аргумент: объект stream-сессии.

Объект сессии имеет следующие свойства:

remoteAddress
адрес клиента, только чтение
eof
логическое свойство, true, если текущий буфер является последним буфером, только чтение
fromUpstream
логическое свойство, true, если текущий буфер является буфером от проксируемого сервера к клиенту, только чтение
buffer
текущий буфер, доступен для записи
variables{}
объект переменных nginx, только чтение
OK
код OK
DECLINED
код DECLINED
AGAIN
код AGAIN
ERROR
код ERROR
ABORT
код ABORT

Объект сессии имеет следующие методы:

log(строка)
записывает отправленную строку в лог-файл ошибок