Thank you for reading this post, don't forget to subscribe!
NginScript — это среда выполнения JavaScript в Nginx. Его парсер в настоящее время поддерживает ECMAScript 5 (обещают в будущем расширить поддержку). Имеется компилятор внутреннего байткода, который затем выполняется в Nginx каждый раз, когда вызывается JavaScript. Для этого используется виртуальная машина на основе регистров.
nginScript VM немного отличается от популярных виртуальных машин для JavaScript, так как сфокусирована на серверных требованиях, а не оптимизации для браузеров. Интересно, что каждый процесс запускается в отдельной виртуальной среде, поэтому не потребуется сборщик мусора.
Язык конфигов Nginx дополнили синтаксисом, при помощи которого можно встраивать блоки кода на JS непосредственно в файл конфигурации. Для этого используется две новых директивы: js_set и js_run. Они выполняются по мере обработки транзакций HTTP, при этом для каждого запроса можно выполнить корректировку параметров веб-сервера, скорректировать сам запрос или ответ, реализовать весьма сложные условия.
Ко всему прочему, можно приостанавливать и возобновлять любые блокирующие операции, подзапросы HTTP, к примеру. NginScript также пригодится для создания заглушек в качестве временного (и не очень) решения возникшей проблему. Еще несколько важных применений функции: блокировка нехороших/вредоносных запросов или уязвимостей, ограничение интенсивности запросов.
Установка модуля nginScript
Для добавления модуля потребуется Nginx последней версии:
1 2 |
wget http://nginx.org/download/nginx-1.9.9.tar.gz tar -xzvf nginx-1.9.9.tar.gz |
# Закачка и распаковка Nginx с репозитория, требуется установленный Mercurial
Далее нужно получить источники разработки nginScript:
1 |
hg clone http://hg.nginx.org/njs |
# Клонирование репозитория c nginScript из Mercurial
После чего нужно пересобрать и обновить (установить) Nginx:
1 2 3 4 |
cd nginx-1.9.9 ./configure --add-module=../njs/nginx --prefix=/your/custom/installation/directory make make install |
# Компиляция и установка Nginx с модулем nginScript
Учтите, что nginScript все еще находится в активной разработке, так что стоит следить за логом изменений и своевременно обновляться до актуальных и более стабильных версий.
js_set
Директива приводит значение переменной к результату выполнения кода JS.
Переменная, назначенная при помощи js_set, может использоваться в любой директиве Nginx, которая принимает переменные: limit_req_zone, proxy_pass и sub_filter, к примеру.
Примеры использования js_set
nginScript предоставляет объект запроса и умеет передавать его в функцию в качестве первого параметра. Можно считывать и устанавливать свойства этого объекта и использовать методы доступа и изменения запроса.
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
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; } } |
[/codesyntax]
Возврат параметров запроса обратно клиенту
При помощи nginScript можно перенаправить трафик, основываясь на данных запроса: куки, аргументы, заголовки или ключевые слова в теле запроса.
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
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; } } |
[/codesyntax]
Маршрутизация трафика на основе наличия аргумента upstream
js_run
Директива js_run выполняется на этапе генерации контента и используется для выполнения JavaScript и создания ответа HTTP.
Пример использования js_run
Она размещается внутри блока location в файле конфигурации Nginx и запускает выполнение кода JS, когда местоположение соответствует запросу URL.
[codesyntax lang="php"]
1 2 3 4 5 6 7 8 9 |
location / { js_run " var res; res = $r.response; res.status = 200; res.send('js_run test'); res.finish(); "; } |
[/codesyntax]
Вывод на экран текста "js_run test"
Новый модуль nginScript не предназначен для замены модуля Lua или других встроенных языков Nginx. Но с его помощью можно тестировать конфиги, проверять функциональность, создавать фиксы и закрывать дыри. Фактически nginScript дает возможность рефакторинга процесса разработки и развертывания веб-приложений.