Nginx sub_filter: заменить текст в ответе прокси

Категория: Nginx · Обновлено:

sub_filter заменяет строки в теле ответа, который Nginx получает от прокси или статики. Это удобно, когда нужно добавить скрипт на все страницы, поменять домен в ссылках или исправить HTML без сборки приложения. Фильтр работает только с текстовыми ответами и по умолчанию обрабатывает лишь text/html.

Добавить скрипт и заменить домен

Текст
upstream backend {
    server 127.0.0.1:9002;
}

server {
    listen 80;

    location / {
        proxy_pass http://backend;
        proxy_set_header Accept-Encoding "";

        sub_filter '</head>' '<script src="/banner.js" defer></script></head>';
        sub_filter 'https://old.example.com' 'https://new.example.com';
        sub_filter_once off;
        sub_filter_types text/css application/javascript;
    }
}

sub_filter_once off важен, если строка встречается несколько раз: по умолчанию заменяется только первое совпадение. sub_filter_types расширяет фильтр на CSS и JavaScript; без него Nginx не трогает эти ответы. Совпадение регистронезависимое, а в строке замены можно использовать переменные.

proxy_set_header Accept-Encoding ""; отключает сжатие у upstream. Nginx не фильтрует gzip-тело: если бэкенд вернёт сжатый ответ, замена не сработает. Включайте ngx_http_gunzip_module, только если действительно нужно принимать сжатые ответы, — это добавляет распаковку на каждый запрос.

Фильтрация требует буферизации ответа и меняет Content-Length, поэтому не применяйте её к большим файлам и потоковому видео. Для JSON API надёжнее менять данные в приложении: sub_filter может испортить структуру, если строка встретится в неожиданном месте. Проверяйте, что замена не ломает подписи, скрипты и ETag.

Не подставляйте в шаблон замены пользовательский ввод без экранирования: это может привести к XSS. После изменения конфигурации выполните nginx -t и перезагрузите Nginx через nginx -s reload.

Документация: ngx_http_sub_module, ngx_http_gunzip_module.