sorted-args: Нормализация параметров запроса HTTP для NGINX
Установка для Debian/Ubuntu
Эти документы относятся к пакету APT nginx-module-sorted-args, предоставляемому репозиторием GetPageSpeed Extras.
- Настройте APT-репозиторий, как описано в настройке APT-репозитория.
- Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-sorted-args
Показать дистрибутивы и архитектуры
| Дистрибутив | Версия | Компонент | Архитектуры |
|-------------|-------------------|-------------|-----------------|
| debian | bookworm | main | amd64, arm64 |
| debian | bookworm-mainline | main | amd64, arm64 |
| debian | trixie | main | amd64, arm64 |
| debian | trixie-mainline | main | amd64, arm64 |
| ubuntu | focal | main | amd64, arm64 |
| ubuntu | focal-mainline | main | amd64, arm64 |
| ubuntu | jammy | main | amd64, arm64 |
| ubuntu | jammy-mainline | main | amd64, arm64 |
| ubuntu | noble | main | amd64, arm64 |
| ubuntu | noble-mainline | main | amd64, arm64 |
Мощный модуль Nginx, который нормализует параметры строки запроса HTTP, сортируя их алфавитно-цифровым образом. Этот модуль предоставляет последовательное, каноническое представление строк запроса независимо от оригинального порядка параметров, что делает его идеальным для генерации ключей кэша, дедупликации запросов и нормализации URL.
Обзор
Разные URL с одинаковыми параметрами запроса в разных порядках будут производить одинаковую нормализованную строку запроса:
/index.php?b=2&a=1&c=3/index.php?b=2&c=3&a=1/index.php?c=3&a=1&b=2/index.php?c=3&b=2&a=1
Все вышеперечисленные URL создадут одну и ту же нормализованную строку запроса: a=1&b=2&c=3
Эта нормализация доступна через переменную $sorted_args, которая может использоваться в ключах кэша, логировании и других контекстах Nginx.
Особенности
- ✅ Естественная сортировка параметров запроса по ключу, затем по значению (например,
item2<item10) - ✅ Устранение пустых значений — параметры типа
?a=автоматически удаляются - ✅ Режим черного списка (
sorted_args_ignore_list) для исключения конкретных параметров из отсортированного вывода - ✅ Режим белого списка (
sorted_args_allow_list) для сохранения только конкретных параметров, удаляя все остальные - ✅ Шаблоны с подстановочными знаками — используйте
utm_*для соответствия всем UTM параметрам,*_idдля суффиксов - ✅ Удаление дубликатов (
sorted_args_dedupe) — сохранять только первое или последнее вхождение дублирующихся ключей - ✅ Необязательное перезаписывание
$argsдля автоматической замены исходной строки запроса на отсортированные аргументы - ✅ Конфигурация на уровне локации с наследованием от серверного и основного контекстов
- ✅ Эффективная реализация с использованием родной сортировки очереди Nginx
- ✅ Игнорирование регистра при сопоставлении имен параметров для фильтрации
- ✅ Обнаружение дубликатов в списках фильтров
Конфигурация
Переменные
$sorted_args
Возвращает параметры запроса, отсортированные в алфавитном порядке по имени параметра, затем по значению. Параметры соединяются с помощью & и сохраняют свое первоначальное кодирование URL.
Пример:
Запрос: /page?zebra=1&apple=2&banana=3
$sorted_args: apple=2&banana=3&zebra=1
Поведение:
- Пустая строка запроса возвращает пустую строку
- Параметры без значений (например, ?param) включаются как param
- Параметры с пустыми значениями (например, ?param=) автоматически удаляются
- Множественные значения для одного и того же параметра сортируются по отдельности
- Естественная сортировка: p=1, p=2, p=10 сортируются правильно (не p=1, p=10, p=2)
- Сортировка без учета регистра для имен параметров
Директивы
sorted_args_ignore_list
Синтаксис: sorted_args_ignore_list pattern [pattern ...];
По умолчанию: нет
Контекст: http, server, location, if
Описание:
Указывает одну или несколько масок, чтобы исключить из переменной $sorted_args (режим черного списка). Это полезно для удаления параметров, нарушающих кеширование (таких как временные метки, номера версий или идентификаторы отслеживания) из ключей кеша, сохраняя другие параметры.
Типы шаблонов:
- name — точное совпадение (без учета регистра)
- name* — совпадение по префиксу (совпадает с name, name_foo, name123 и т.д.)
- *name — совпадение по суффиксу (совпадает с foo_name, bar_name и т.д.)
- *name* — совпадение по содержимому (совпадает с любым параметром, содержащим name)
Дублирующиеся шаблоны в списке автоматически удаляются.
Пример:
location /api {
# Фильтровать точные имена и все utm_* параметры отслеживания
sorted_args_ignore_list timestamp version _ utm_* fb_*;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
В этом примере запросы типа /api?user=123×tamp=1234567890&utm_source=google&utm_medium=cpc будут производить $sorted_args как user=123, с отфильтрованными timestamp и всеми UTM параметрами.
sorted_args_allow_list
Синтаксис: sorted_args_allow_list pattern [pattern ...];
По умолчанию: нет
Контекст: http, server, location, if
Описание:
Указывает одну или несколько масок, чтобы сохранить в переменной $sorted_args (режим белого списка). Все параметры, НЕ совпадающие с какой-либо маской, будут исключены. Это полезно, когда вы хотите строго контролировать, какие параметры запроса разрешены для кеширования.
Типы шаблонов:
- name — точное совпадение (без учета регистра)
- name* — совпадение по префиксу (совпадает с name, name_foo, name123 и т.д.)
- *name — совпадение по суффиксу (совпадает с foo_name, bar_name и т.д.)
- *name* — совпадение по содержимому (совпадает с любым параметром, содержащим name)
Когда оба sorted_args_allow_list и sorted_args_ignore_list настроены, сначала применяется белый список (оставляя только разрешенные параметры), затем применяется черный список для фильтрации оставшихся нежелательных параметров.
Пример:
location /api {
# Разрешить только параметры постраничной навигации и сортировки
sorted_args_allow_list page* sort* limit;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
В этом примере запрос типа /api?page=1&page_size=10&sort=asc×tamp=123 будет производить $sorted_args как limit=10&page=1&page_size=10&sort=asc. Параметр timestamp будет удалён, потому что он не соответствует ни одной маске.
sorted_args_overwrite
Синтаксис: sorted_args_overwrite on | off;
По умолчанию: off
Контекст: http, server, location, if
Описание:
При включении эта директива автоматически перезаписывает встроенную переменную $args с отсортированными (и, при необходимости, отфильтрованными) аргументами запроса. Это полезно, когда вы хотите, чтобы вся последующая обработка (прокси, ведение журналов, перенаправления) использовала нормализованную строку запроса без явного упоминания $sorted_args.
Перезапись происходит во время стадии переписывания, так что все последующие фазы увидят отсортированные аргументы в $args.
Пример:
location /api {
sorted_args_overwrite on;
sorted_args_ignore_list timestamp version;
# $args теперь автоматически отсортированы и отфильтрованы
proxy_pass http://backend$uri?$args;
}
В этом примере запрос к /api?z=1&a=2×tamp=123 будет проксироваться как /api?a=2&z=1 — отсортированный и с отфильтрованным timestamp.
sorted_args_dedupe
Синтаксис: sorted_args_dedupe first | last | off;
По умолчанию: off
Контекст: http, server, location, if
Описание:
Управляет тем, как обрабатываются дублирующиеся ключи параметров. Когда несколько параметров имеют один и тот же ключ (например, ?a=1&a=2&a=3), эта директива определяет, какое значение сохранить.
first— сохранять только первое вхождение каждого ключаlast— сохранять только последнее вхождение каждого ключаoff— сохранять все вхождения (поведение по умолчанию)
Это полезно для нормализации URL, когда один и тот же параметр может быть указан несколько раз, что обеспечивает постоянные ключи кеша.
Пример:
location /search {
sorted_args_dedupe first;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
В этом примере запрос типа /search?q=foo&q=bar&q=baz будет производить $sorted_args как q=foo, сохраняя только первое значение. С sorted_args_dedupe last было бы произведено q=baz.
Примеры Использования
Нормализация Ключей Кэша
Нормализуйте ключи кэша независимо от порядка параметров:
http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m;
server {
listen 80;
location / {
proxy_cache my_cache;
proxy_cache_key "$scheme$host$uri$sorted_args";
proxy_pass http://backend;
}
}
}
Автоматическое Перезаписывание Аргументов
Автоматически переписывайте $args с отсортированными параметрами для всей последующей обработки:
server {
listen 80;
location /api {
sorted_args_overwrite on;
sorted_args_ignore_list timestamp _;
# Все эти параметры теперь используют автоматически отсортированные и отфильтрованные аргументы
proxy_pass http://backend;
# Эквивалентно: proxy_pass http://backend$uri?$sorted_args;
}
}
Фильтрация Параметров, Разрушающих Кэш
Удалите параметры временной метки и отслеживания из ключей кэша:
location /static {
sorted_args_ignore_list _ t timestamp v version;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://cdn;
}
Режим Разрешенного Списка (Только Определенные Параметры)
Когда параметры запроса могут вызывать интенсивную серверную обработку, используйте разрешенный список, чтобы строго контролировать, какие параметры разрешены для кэширования:
location /search {
# Только эти параметры влияют на ключ кэша; все остальные отбрасываются
sorted_args_allow_list q page limit category;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://search_backend;
}
В этом примере запросы, такие как /search?q=nginx&page=1&debug=true&nocache=1, будут кешироваться, используя только category=&limit=&page=1&q=nginx, эффективно игнорируя любые параметры, разрушающие кэш или для отладки.
Сочетание Разрешенного и Запрещенного Списков
Вы можете использовать обе директивы вместе для более тонкого контроля. Сначала применяется разрешенный список, затем запрещенный:
location /api {
# Сначала сохраняйте только эти параметры
sorted_args_allow_list user_id action page limit timestamp;
# Затем уберите временную метку из разрешенного набора
sorted_args_ignore_list timestamp;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://api_backend;
}
Логирование Нормализованных Строк Запроса
Включите отсортированные строки запросов в журналы доступа:
http {
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'args="$args" sorted_args="$sorted_args"';
server {
access_log /var/log/nginx/access.log detailed;
# ...
}
}
Фильтрация На Основе Местоположения
Разные местоположения могут иметь разные списки фильтров:
server {
# По умолчанию: фильтровать общие параметры отслеживания
sorted_args_ignore_list _ utm_source utm_medium utm_campaign;
location /api {
# API: также фильтровать версию и временную метку
sorted_args_ignore_list _ utm_source utm_medium utm_campaign version t;
proxy_pass http://api_backend;
}
location /content {
# Контент: фильтровать только отслеживание
proxy_pass http://content_backend;
}
}
Полный Пример
pid logs/nginx.pid;
error_log logs/error.log warn;
worker_processes auto;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" "$http_user_agent" '
'args="$args" sorted_args="$sorted_args"';
access_log logs/access.log main;
proxy_cache_path /tmp/cache
levels=1:2
keys_zone=zone:10m
inactive=10d
max_size=100m;
server {
listen 8080;
server_name localhost;
# Фильтровать параметры отслеживания и разрушающие кэш
location /filtered {
sorted_args_ignore_list v _ time timestamp;
proxy_set_header Host "backend";
proxy_pass http://localhost:8081;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_cache_valid 200 1m;
}
# Использовать отсортированные аргументы без фильтрации
location / {
proxy_pass http://localhost:8081;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_cache_valid 200 10m;
}
}
# Сервер заднего плана для тестирования
server {
listen 8081;
location / {
return 200 "args: $args\nsorted_args: $sorted_args\n";
}
}
}
Как это работает
- Извлечение параметров: Модуль разбирает строку запроса из
r->args, разделяя на&и= - Формирование очереди: Каждый параметр сохраняется в структуре очереди с его ключом, значением и полным парой ключ-значение
- Сортировка: Параметры сортируются с использованием функции естественного сравнения:
- Первичная сортировка: имя параметра (без учета регистра, естественный порядок)
- Вторичная сортировка: полная строка параметра (ключ=значение, естественный порядок)
- Естественный порядок означает, что вложенные числа сравниваются численно:
item2<item10 - Удаление пустых значений: Параметры с
=но без значения (например,?a=) удаляются - Фильтрация по белому списку: Если
sorted_args_allow_listнастроен, сохраняются только параметры, соответствующие шаблонам - Фильтрация по черному списку: Параметры, соответствующие шаблонам в
sorted_args_ignore_list, исключаются - Удаление дубликатов: Если
sorted_args_dedupeвключен, сохраняется только первое или последнее вхождение каждого ключа - Реконструкция: Отсортированные и отфильтрованные параметры объединяются с
&, чтобы сформировать окончательную строку
Тестирование
Этот проект использует Test::Nginx для своего тестового набора, работающего внутри Docker для воспроизводимых сборок.
Предварительные требования
- Docker
Запуск тестов
Запустите полный тестовый набор:
make tests
Запустите конкретный файл теста:
make tests T=t/sorted_args.t
Отключите режим HUP для отладки (медленнее, но более изолированно):
make tests HUP=0
Используйте другую версию Nginx:
make tests NGINX_VERSION=release-1.26.2
Откройте интерактивную оболочку в тестовом контейнере для отладки:
make shell
Покрытие тестами
Тестовый набор проверяет:
- ✅ Основная функциональность сортировки
- ✅ Естественная/числовая сортировка (например, p=1, p=2, p=10 в правильном порядке)
- ✅ Параметры в виде массивов (например, c[]=1&c[]=2)
- ✅ Фильтрация по черному списку (sorted_args_ignore_list)
- ✅ Фильтрация по белому списку (sorted_args_allow_list)
- ✅ Совместное использование белого и черного списков
- ✅ Шаблоны с подстановочными знаками: префикс (utm_*), суффикс (*_id), содержит (*token*)
- ✅ Удаление дубликатов: sorted_args_dedupe first и last
- ✅ Обработка пустой строки запроса
- ✅ Удаление пустых значений (?a=&b=2 → b=2)
- ✅ Использование ключа кэша
- ✅ Унаследование конфигурации на уровне местоположения
- ✅ Директива sorted_args_overwrite
- ✅ Регистронезависимое соответствие параметров (как для белого, так и для черного списков)
- ✅ Параметры без значений против пустых значений
- ✅ Обработка дубликатов параметров
- ✅ Сохранение специальных символов
- ✅ Неправильно сформированные строки запроса (последовательные амперсанды)
- ✅ Параметры с несколькими знаками равенства
- ✅ E2E: $args изменяется перед оценкой ключа кэша (временные параметры стадии ПЕРЗаписи)
- ✅ E2E: Переупорядоченные параметры создают идентичные ключи кэша
- ✅ E2E: Директивы переписывания видят перезаписанный $args
Учет производительности
- Упорядоченная строка запроса вычисляется один раз на запрос и кэшируется в контексте запроса
- Сортировка использует эффективный алгоритм на основе очереди от Nginx
- Фильтрация использует нечувствительное к регистру сравнение строк
- Выделение памяти осуществляется из пула запроса, так что явная очистка не требуется
Ограничения
- Значения параметров не декодируются/кодируются; оригинальная кодировка сохраняется
- Фильтрация нечувствительна к регистру для имен параметров, но сохраняет оригинальный регистр в выходных данных
- Параметры с пустыми значениями (например,
?a=) всегда удаляются; используйте?a(без знака равно) для флагов