# теория · шаг 3 из 5
Справочник: что ещё есть в стандартной сборке
Коротко
В стандартной сборке модулей вчетверо больше, чем прошёл курс, и половина
решает задачу, ради которой обычно пишут код: другие протоколы до приложения
(uwsgi, scgi, grpc, memcached), правка ответа на лету (sub_filter,
ssi, addition, gunzip), файлы и картинки (dav, mp4, image_filter),
разбор JSON прямо в конфиге (json_set) и целый третий корневой блок mail.
Но «стандартная сборка» у каждого своя: часть модулей собирается только явно,
и в официальном образе их нет.
Это карта, а не урок про одну мысль: читай оглавление, запоминай, что существует. Разборы про json_set и про содержимое официального образа стоит прочитать целиком.
Понадобилось уменьшать картинки на лету. Строка из документации, официальный
образ nginx:alpine. Что скажет nginx -t?
image_filter resize 200 -; # 200 - ширина, прочерк - «высоту подобрать по пропорции»
nginx: [emerg] unknown directive "image_filter"
Модуль есть в документации, описан на сайте nginx, и его нет в твоём nginx. Список того, что документация называет стандартным, и список того, что собрано у тебя, - разные списки.
На что это похоже
Справочник по модулям - это аптечка, а не учебник. Наизусть дозировки никто не помнит; помнят, что в аптечке лежит жгут, и где он лежит. Половина времени, потраченного на «напишу-ка я для этого сервис», уходит зря именно потому, что человек не знал: жгут уже есть.
Поэтому читать этот урок надо один раз целиком, а возвращаться - по оглавлению.
Как это устроено: три состояния модуля
Правило
Перед тем как писать директиву из документации, спроси свою сборку:
nginx -V 2>&1 | tr ' ' '\n' | grep -E "with-|module"
Модули со звёздочкой в документации собираются только явно
(--with-http_image_filter_module), в пакетах дистрибутивов часть вынесена в
отдельные файлы (nginx-module-njs, nginx-module-image-filter), и тогда
нужна строка load_module в самом верху конфига (.so - файл собранного
модуля, load_module подключает его до всех блоков).
Разбор: что реально лежит в официальном образе
Прогон по образу nginx:alpine 1.31.5 - каждая директива проверена на
unknown directive:
| в сборке есть | в сборке нет |
|---|---|
ssi, sub_filter, addition, gunzip |
image_filter |
uwsgi_pass, scgi_pass, grpc_pass, memcached_pass |
xslt_stylesheet |
dav_methods, mp4, random_index, slice |
degradation |
userid, charset, empty_gif, valid_referers |
perl_set |
json_max_depth, stub_status, auth_request |
- |
В debian-образе те же image_filter и xslt лежат отдельными файлами в
/etc/nginx/modules/ - то есть там они есть, но молчат, пока не написан
load_module. Один и тот же «официальный nginx» ведёт себя по-разному в двух
официальных образах, и это стоит проверить до того, как под фичу заведена
задача.
Разбор: json_set и путь, который молча ничего не находит
Свежий модуль стандартной сборки, которого нет в старых руководствах:
ngx_http_json_module. Он достаёт значение из JSON прямо в конфиге - без njs
и без похода в приложение.
json_set $user_name $request_body user.name;
json_max_depth 8;
Путь пишется точками. И вот тут ловушка: похожие на JSON Pointer записи
проверку проходят, а значения не дают. Один и тот же заголовок
{"user":{"name":"бобр"},"items":["раз","два"]}, разные пути:
| путь | что вернулось |
|---|---|
user.name |
бобр |
user |
{"name":"бобр"} - весь вложенный объект |
items |
["раз","два"] |
user/name |
пусто, nginx -t доволен |
/user/name |
пусто, nginx -t доволен |
items.0 |
пусто: элемент массива так не достать |
глубже json_max_depth |
пусто |
Битый JSON тоже даёт пустое значение и ни строки в логе. То есть все ошибки здесь выглядят одинаково - пустая переменная, - и различать их придётся прогоном, а не чтением конфига.
Вторая тонкость: $request_body заполняется, только когда тело реально
прочитано. С return в том же location переменная пуста, с proxy_pass -
работает:
proxy_set_header X-User $user_name;
proxy_pass http://app:8000;
Другие способы дойти до приложения
| Модуль | Когда нужен |
|---|---|
fastcgi_pass |
PHP через php-fpm - разобран в седьмом разделе |
uwsgi_pass |
Python через uWSGI: uwsgi_pass unix:/run/app.sock; плюс include uwsgi_params; |
scgi_pass |
тот же протокол, но проще; старые Python- и Perl-приложения |
grpc_pass |
gRPC: grpc_pass grpc://app:9000; или grpcs://, обязательно поверх HTTP/2 |
memcached_pass |
отдать значение прямо из memcached, не будя приложение; ключ - в $memcached_key |
grpc_pass стоит запомнить отдельно: gRPC внутри - это HTTP/2, поэтому обычный
proxy_pass для него не годится, а на порту нужен http2 on.
Правка ответа на лету
sub_filter заменяет текст в теле - спасает при переезде домена, когда в
вёрстке остались абсолютные ссылки, а править приложение нельзя:
sub_filter 'http://old.shop.local' 'https://shop.local';
sub_filter_once off;
sub_filter_types text/html text/css;
Плата - разбор тела каждого ответа, поэтому это временная мера, а не
архитектура. Рядом: ssi собирает страницу из кусков прямо в nginx,
addition приклеивает ответ подзапроса до или после основного без разбора
тела, gunzip распаковывает ответ бэкенда для клиента, который сжатия не
понимает.
Файлы, картинки и мелочи
image_filter- изменить размер, повернуть, обрезать картинку на лету; прожорлив по процессору, результат обязательно кешировать.dav- загрузка и удаление файлами методамиPUT,DELETE,MKCOL. Включать только с ограничением доступа: помни CVE-2026-27654 из двенадцатого раздела.mp4иflv- перемотка видео по времени без скачивания всего файла;sliceрежет большой файл на куски для кеша.useridставит клиенту cookie-идентификатор ($uid_got,$uid_set),charsetдописывает и перекодирует кодировку,empty_gifотдаёт однопиксельный gif из памяти,random_indexвыдаёт случайный файл каталога.
Совсем другой мир: почта
Кроме http и stream есть третий корневой блок - mail: прокси для IMAP,
POP3 и SMTP с терминацией TLS и внешней авторизацией.
mail {
server_name mail.shop.local;
auth_http http://app:8000/mail/auth;
server {
listen 993 ssl;
protocol imap;
proxy_pass_error_message on;
}
}
nginx принимает соединение, спрашивает у твоего http-сервиса, куда направить пользователя, и соединяет его с нужным почтовым сервером. Задача узкая, но если она твоя - отдельный прокси заводить не нужно.
Что ломается без этого
Дважды написанная логика. Приложение, которое парсит JSON только затем, чтобы
положить поле в заголовок, - это json_set. Скрипт, склеивающий страницу из
двух кусков, - это ssi или addition. Сервис, распаковывающий ответ соседа, -
это gunzip. Каждая такая замена стоит своего процесса, своего деплоя и своего
дежурства.
Обратная ошибка тоже дорогая: sub_filter на всех ответах и image_filter без
кеша выглядят как экономия, а стоят процессорного времени на каждом запросе.
Оба модуля - временная мера, у которой должен быть срок.
Зачем это в работе
На разборе инцидента полезнее всего помнить не синтаксис, а список
существующего. «Нам нужен сервис, который подменит домен в html» - это одна
строка конфига и пятнадцать минут. «Нам нужно вытащить поле из тела запроса
для маршрутизации» - json_set вместо njs, то есть без кода в рабочем
процессе.
И обратная сторона: nginx -V стоит смотреть первым делом на чужом сервере.
Половина «у нас это не работает» объясняется тем, что модуля там просто нет.
Теперь сам
В конфиг добавили строку image_filter resize 200 -;, nginx -t ругается
unknown directive. Коллега советует пересобрать nginx из исходников. Что
проверить до этого?
Ответ: сначала nginx -V - если модуль собран, дело не в нём. Дальше -
дистрибутив: в пакетах nginx.org и в debian-образе image_filter лежит
отдельным файлом /etc/nginx/modules/ngx_http_image_filter_module.so, и нужен
только load_module .../ngx_http_image_filter_module.so; первой строкой
nginx.conf плюс установка пакета nginx-module-image-filter. Пересборка из
исходников нужна лишь там, где пакета нет вовсе, - например в alpine-образе,
где этого модуля не собрано.
Главное
Стандартная сборка шире курса: uwsgi_pass, scgi_pass, grpc_pass и
memcached_pass - другие протоколы до приложения; sub_filter, ssi,
addition, gunzip - правка ответа; dav, mp4, slice, image_filter -
файлы; json_set достаёт значение из JSON прямо в конфиге, но путь пишется
точками, а похожие записи со слешами молча возвращают пустое. Есть третий
корневой блок mail. Главное правило справочника: «стандартная сборка» у
каждого своя - в официальном alpine-образе нет image_filter, xslt,
degradation и perl, а в debian-образе они есть, но только через
load_module. Смотри nginx -V раньше, чем пишешь директиву.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий