Сервер Angie вобрал в себя всю функциональность, которая десятилетиями формировалась в Nginx. Кроме того, разработчики за несколько лет добавили еще несколько модулей и расширили возможности существующих. Тем не менее, при реализации сложных задач может потребоваться индивидуальное решение, нестандартное поведение сервера и кастомизированная конфигурация. В таких задачах полезно использовать модули для расширения функциональности сервера на базе различных языков программирования: доступны njs, Lua и Perl.
Навигация по циклу
Настройка location в Angie. Разделение динамических и статических запросов.
Перенаправления в Angie: return, rewrite и примеры их применения.
Сжатие текста в Angie: статика, динамика, производительность.
Кастомизация Angie (njs, Lua, Perl).
Видеоверсия
Для вашего удобства подготовлена видеоверсия этой статьи, доступна на Rutube, VKVideo и YouTube.
Модуль Perl
Начнём с классического модуля Perl, вносящего динамику в конфигурацию Angie. На всякий случай: документация предупреждает нас об экспериментальном статусе модуля. Он появился на ранних этапах развития Nginx и до сих пор поставляется в комплекте с Angie. Хотя сегодня язык Perl не пользуется большой популярностью у разработчиков, он имеет ряд преимуществ. Во‑первых, интерпретатор Perl входит в комплект большинства дистрибутивов Linux, то есть обладает высокой совместимостью. Также, язык обладает очень высокой стабильностью с точки зрения синтаксиса. Если вы найдёте решение, написанное лет 20 назад, практически всегда оно будет работать на современной версии интерпретатора.
Использовать модуль Perl можно для нескольких задач:
определение внутренних переменных Angie;
подключение полноценных обработчиков запросов;
использование при включении Perl‑скриптов в SSI.
Модуль Perl работает только в контексте HTTP. Установка и подключение модуля стандартны:
apt install angie-module-perlПодключение (в контексте main):
load_module modules/ngx_http_perl_module.so;Рассмотрим несложный пример определения переменных. Задача следующая: конвертировать URI запросов в нижний регистр. Например, /Uri -> /uri, /URI -> /uri, /TeSt -> /test.
Для решения задачи настроим переменную с изменённым URI через подпрограмму Perl:
http {
perl_set $my_uri_to_lowercase 'sub {
my $r = shift;
my $uri = $r->uri;
$uri = lc($uri);
return $uri;
}';
}В директиве perl_set мы создаём переменную $my_uri_to_lowercase, которая будет содержать новый URI запроса. Для этого мы заносим в Perl‑переменную $uri исходный URI запроса и применяем к нему функцию lc — перевод в нижний регистр. Результат работы функции присваивается Angie‑переменной $my_uri_to_lowercase.
Использование новой переменной можно реализовать следующим образом: создаём локацию с для URI с символами в верхнем регистре и возвращаем редирект на новый URI из переменной:
server {
location ~ [A-Z] {
return 301 $scheme://$host$my_uri_to_lowercase;
}
}На этом наша задача решена. Если требуется менять регистр не для всех запросов, локацию можно сделать вложенной.
Для реализации более сложных сценариев наверняка пот��ебуется подключить дополнительные модули Perl (из CPAN). Сделать это можно директивой perl_require. Рассмотрим пример с подключением модуля и установкой обработчика запроса. Конфигурация Angie:
http {
perl_modules perl/lib;
perl_require hello.pm;
server {
location / {
perl hello::handler;
}
}
}Здесь указывается директория для поиска Perl‑модулей (perl_modules) и подключается модуль hello.pm. В серверном блоке для локации определяется обработчик hello::handler — вызов функции handler из модуля hello.pm.
Код модуля Perl для обработчика (hello.pm):
package hello;
use nginx;
sub handler {
my $r = shift;
$r->send_http_header("text/html");
return OK if $r->header_only;
$r->print("hello!\n<br/>");
if (-f $r->filename or -d _) {
$r->print($r->uri, " exists!\n");
}
return OK;
}
1;
__END__Основная часть модуля — функция обработчика запроса (handler). Она выводит текст «hello!» и в случае наличия файла или директории, совпадающих с URI, добавляет «$uri exists!».
Важно понимать, что Perl‑модуль работает в синхронном режиме, поэтому во время исполнения кода рабочий процесс не может обрабатывать другие запросы. По этой причине не рекомендуется реализовывать таким образом длительные операции с непредсказуемым временем ответа.
Модуль Lua
Сторонние модули позволяют использовать популярный скриптовый язык Lua в Angie. Мы рассмотрим базовые возможности модуля lua из комплекта фреймворка OpenResty.
При подключении модуля lua также необходим модуль NDK. Установка:
apt install angie-module-luaПодключение модулей:
load_module modules/ndk_http_module.so;
load_module modules/ngx_http_lua_module.so;Для примера использования модуля будем использовать задачу записи тела запроса (request body) в лог-файл. Для этого определим соответствующий формат лога и дополнительную переменную:
http {
log_format bodylog '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" $request_time '
'<"$request_body" >"$resp_body"';
lua_need_request_body on;
body_filter_by_lua '
local resp_body = string.sub(ngx.arg[1], 1, 1000)
ngx.ctx.buffered = (ngx.ctx.buffered or "") .. resp_body
if ngx.arg[2] then
ngx.var.resp_body = ngx.ctx.buffered
end
';
server {
listen 80;
set $resp_body "";
access_log /var/log/nginx/server.log bodylog;
}
}Этот код добавляет специальный формат лога и устанавливает директиву lua_need_request_body on, чтобы у Lua был доступ к телу запроса. Далее добавлен обработчик для тела запроса на Lua, задача которого — заполнить переменную в Angie ($resp_body). В данном примере размер ограничен 1000 байтами. Сама переменная объявляется на уровне блока сервера, и там же используется кастомный access_log.
В отличие от модуля Perl, Lua можно использовать как в контексте HTTP, так и в Stream. Кроме того, Lua позволяет создавать неблокирующий код для доступа к внешним системам. В общем, возможности модуля Lua широки и охватывают практически все аспекты работы с запросом и ответом в Angie.
Модуль NJS
Наконец, мы добрались до модуля NJS. Пожалуй, это самый естественный способ расширения функциональности для Angie. Дело в том, что NJS — подмножество языка JavaScript, специально адаптированное для использования в Nginx (а значит, и в Angie). Создание модуля NJS было обусловлено необходимостью создания гибких конфигураций сервера и нестандартных сценариев обработки запросов.
Модуль NJS поддерживает работу как в контексте HTTP, так и в Stream. Установка модуля стандартна:
apt install angie-module-luaПодключение модуля, как обычно, производится в контексте main (существуют отдельные модули для http и stream):
load_module modules/ngx_http_js_module.so;
load_module modules/ngx_stream_js_module.so;Для примера возьмём задачу перевода тела ответа в нижний регистр. Будем использовать код примеров из репозитория. Клонируем репозиторий в директорию /etc/angie:
cd /etc/angie
git clone https://github.com/nginx/njs-examples.gitВ конфигурации сервера подключим файлы скриптов и обработчик NJS.
http {
js_path "/etc/angie/njs-examples/njs/";
js_import main from http/response/to_lower_case.js;
server {
listen 80;
location / {
js_body_filter main.to_lower_case;
proxy_pass http://localhost:8080;
}
}
server {
listen 8080;
location / {
return 200 'Hello World';
}
}
}Директива js_path определяет директорию для поиска файлов njs-скриптов. Далее мы импортируем файл скрипта по относительному пути (код мы получили из репозитория).
Первый блок server (80 порт) отвечает за основную точку входа в наше импровизированное приложение. При этом в корневой локации подключён обработчик js_body_filter. Он будет вызывать функцию to_lower_case из файла to_lower_case.js для обработки тела ответа. Код скрипта максимально лаконичен:
function to_lower_case(r, data, flags) {
r.sendBuffer(data.toLowerCase(), flags);
}
export default {to_lower_case};По сути, скрипт приводит к нижнему регистру любые входящие данные.
Второй блок server (8080) выступает бэкендом и отвечает на любой запрос фразой «Hello World».
При проверке такой конфигурации увидим эффект:
curl localhost
hello worldВозможности работы с запросами, ответами и заголовками здесь очень широкие. Для быстрого старта можно начать с примеров в эталонном репозитории модуля.
Итоги
Возможности Angie можно расширять за счет стандартных и сторонних модулей на базе ряда языков программирования. С помощью программной обработки можно преобразовывать заголовки, модифицировать ответ или запрос, создать собственную систему аутентификации. Наиболее близким по задумке к Angie является модуль NJS, так как он создавался специально для расширения возможностей сервера разработчиками Nginx. То есть, NJS в какой‑то степени позволяет создавать динамические модули для сервера без необходимости работать c внутренностями сервера Angie на языке C.
Следующая статья цикла: Запуск CGI-скриптов в Angie.