NginScript на практике

NginScript — это среда выполнения JavaScript в Nginx. Его парсер в настоящее время поддерживает ECMAScript 5 (обещают в будущем расширить поддержку). Имеется компилятор внутреннего байткода, который затем выполняется в Nginx каждый раз, когда вызывается JavaScript. Для этого используется виртуальная машина на основе регистров. NginScript

nginScript VM немного отличается от популярных виртуальных машин для JavaScript, так как сфокусирована на серверных требованиях, а не оптимизации для браузеров. Интересно, что каждый процесс запускается в отдельной виртуальной среде, поэтому не потребуется сборщик мусора.

Язык конфигов Nginx дополнили синтаксисом, при помощи которого можно встраивать блоки кода на JS непосредственно в файл конфигурации. Для этого используется две новых директивы: js_set и js_run. Они выполняются по мере обработки транзакций HTTP, при этом для каждого запроса можно выполнить корректировку параметров веб-сервера, скорректировать сам запрос или ответ, реализовать весьма сложные условия.

Ко всему прочему, можно приостанавливать и возобновлять любые блокирующие операции, подзапросы HTTP, к примеру. NginScript также пригодится для создания заглушек в качестве временного (и не очень) решения возникшей проблему. Еще несколько важных применений функции: блокировка нехороших/вредоносных запросов или уязвимостей, ограничение интенсивности запросов.

Установка модуля nginScript

Для добавления модуля потребуется Nginx последней версии:

wget http://nginx.org/download/nginx-1.9.9.tar.gz
tar -xzvf nginx-1.9.9.tar.gz

# Закачка и распаковка Nginx с репозитория, требуется установленный Mercurial

Далее нужно получить источники разработки nginScript:

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

# Клонирование репозитория c nginScript из Mercurial

После чего нужно пересобрать и обновить (установить) Nginx:

cd nginx-1.9.9
./configure --add-module=../njs/nginx --prefix=/your/custom/installation/directory
make
make install

# Компиляция и установка Nginx с модулем nginScript

Учтите, что nginScript все еще находится в активной разработке, так что стоит следить за логом изменений и своевременно обновляться до актуальных и более стабильных версий.

js_set

Директива приводит значение переменной к результату выполнения кода JS. nginScript js_set

Переменная, назначенная при помощи js_set, может использоваться в любой директиве Nginx, которая принимает переменные: limit_req_zone, proxy_pass и sub_filter, к примеру.

Примеры использования js_set

nginScript предоставляет объект запроса и умеет передавать его в функцию в качестве первого параметра. Можно считывать и устанавливать свойства этого объекта и использовать методы доступа и изменения запроса.

js_set $summary "function summary(req, res) {
    var a, s, h;

    s = 'Request summary\n\n';

    s += 'Method: ' + req.method + '\n';
    s += 'HTTP version: ' + req.httpVersion + '\n';
    s += 'Host: ' + req.headers.host + '\n';
    s += 'Remote Address: ' + req.remoteAddress + '\n';
    s += 'URI: ' + req.uri + '\n';

    s += 'Headers:\n';
    for (h in req.headers) {
        s += '  header \"' + h + '\" is \"' + req.headers[h] + '\"\n';
    }

    s += 'Args:\n';
    for (a in req.args) {
        s += '  arg \"' + a + '\" is \"' + req.args[a] + '\"\n';
    }

    return s;
}";

http {
    js_set $summary "
    var a, s, h;

    s = 'JS summary\n\n';

    s += 'Method: ' + $r.method + '\n';
    s += 'HTTP version: ' + $r.httpVersion + '\n';
    s += 'Host: ' + $r.headers.host + '\n';
    s += 'Remote Address: ' + $r.remoteAddress + '\n';
    s += 'URI: ' + $r.uri + '\n';

    s += 'Headers:\n';
    for (h in $r.headers) {
        s += '  header \"' + h + '\" is \"' + $r.headers[h] + '\"\n';
    }

    s += 'Args:\n';
    for (a in $r.args) {
        s += '  arg \"' + a + '\" is \"' + $r.args[a] + '\"\n';
    }

    s;
    ";

    server {
    listen 8000;

    location /summary {
        return 200 $summary;
    }
}

# Возврат параметров запроса обратно клиенту

При помощи nginScript можно перенаправить трафик, основываясь на данных запроса: куки, аргументы, заголовки или ключевые слова в теле запроса.

upstream my_upstream0 {
    server server1.example.com;
    server server2.example.com;
}
upstream my_upstream1 {
    server server3.example.com;
    server server4.example.com;
}

js_set $my_upstream "
    var s, upstream, upstream_num;

    upstream = $r.args.upstream;

    // преобразование числа апстримов в целое число
    upstream_num = +upstream | 0;

    if (upstream_num < 0 || upstream_num > 1) {
        upstream_num = 0;
    }

    s = 'my_upstream' + upstream_num;

    s;
";

server {
    listen 80;

    location / {
        proxy_set_header Host $host;
        proxy_pass http://$my_upstream;
    }
}

# Маршрутизация трафика на основе наличия аргумента upstream

js_run

Директива js_run выполняется на этапе генерации контента и используется для выполнения JavaScript и создания ответа HTTP. nginScript js_run

Пример использования js_run

Она размещается внутри блока location в файле конфигурации Nginx и запускает выполнение кода JS, когда местоположение соответствует запросу URL.

location / {
    js_run "
        var res;
        res = $r.response;
        res.status = 200;
        res.send('js_run test');
        res.finish();
    ";
}

# Вывод на экран текста "js_run test"

Самое главное

Новый модуль nginScript не предназначен для замены модуля Lua или других встроенных языков Nginx. Но с его помощью можно тестировать конфиги, проверять функциональность, создавать фиксы и закрывать дыри. Фактически nginScript дает возможность рефакторинга процесса разработки и развертывания веб-приложений.

материалы по теме

Подпишитесь на Хайлоад с помощью Google аккаунта
или закройте эту хрень