sorted-args: normalização de parâmetros de querystring HTTP para NGINX
Requer o plano Pro (ou superior) da assinatura GetPageSpeed NGINX Extras.
Instalação
Você pode instalar este módulo em qualquer distribuição baseada em RHEL, incluindo, mas não se limitando a:
- RedHat Enterprise Linux 7, 8, 9 e 10
- CentOS 7, 8, 9
- AlmaLinux 8, 9
- Rocky Linux 8, 9
- Amazon Linux 2 e Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install nginx-module-sorted-args
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install nginx-module-sorted-args
Ative o módulo adicionando o seguinte no topo de /etc/nginx/nginx.conf:
load_module modules/ngx_http_sorted_args.so;
Este documento descreve nginx-module-sorted-args v3.0.0 lançado em 31 de dezembro de 2025.
Um poderoso módulo NGINX que normaliza os parâmetros de querystring de requisições HTTP ordenando-os alfanumericamente. Este módulo fornece uma representação consistente e canônica de query strings, independentemente da ordem original dos parâmetros, tornando-o ideal para geração de chaves de cache, deduplicação de requisições e normalização de URLs.
Visão Geral
URLs diferentes com os mesmos parâmetros de query em ordens diferentes produzirão a mesma querystring normalizada:
/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
Todos os acima produzirão a mesma querystring normalizada: a=1&b=2&c=3
Essa normalização é acessível através da variável $sorted_args, que pode ser usada em chaves de cache, logs e outros contextos do NGINX.
Recursos
- ✅ Ordenação natural dos parâmetros de query por chave, depois por valor (ex.:
item2<item10) - ✅ Remoção de valores vazios — parâmetros como
?a=são automaticamente removidos - ✅ Modo de lista negra (
sorted_args_ignore_list) para excluir parâmetros específicos da saída ordenada - ✅ Modo de lista branca (
sorted_args_allow_list) para manter apenas parâmetros específicos, descartando todos os outros - ✅ Padrões curinga — use
utm_*para corresponder a todos os parâmetros UTM,*_idpara sufixos - ✅ Deduplicação (
sorted_args_dedupe) — mantém apenas a primeira ou última ocorrência de chaves duplicadas - ✅ Sobrescrita opcional de
$argspara substituir automaticamente a querystring original por args ordenados - ✅ Configuração em nível de localização com herança dos contextos de servidor e principal
- ✅ Implementação eficiente usando a ordenação de fila nativa do NGINX
- ✅ Correspondência de nomes de parâmetros sem diferenciação entre maiúsculas e minúsculas para filtragem
- ✅ Detecção de duplicatas em listas de filtro
Configuração
Variáveis
$sorted_args
Retorna os parâmetros da querystring ordenados alfanumericamente por nome de parâmetro, depois por valor. Os parâmetros são unidos com & e mantêm sua codificação de URL original.
Exemplo:
Requisição: /page?zebra=1&apple=2&banana=3
$sorted_args: apple=2&banana=3&zebra=1
Comportamento:
- Querystring vazia retorna uma string vazia
- Parâmetros sem valores (ex.: ?param) são incluídos como param
- Parâmetros com valores vazios (ex.: ?param=) são automaticamente removidos
- Múltiplos valores para o mesmo parâmetro são ordenados individualmente
- Ordenação natural: p=1, p=2, p=10 são ordenados corretamente (não p=1, p=10, p=2)
- Ordenação sem diferenciação entre maiúsculas e minúsculas para nomes de parâmetros
Diretivas
sorted_args_ignore_list
Sintaxe: sorted_args_ignore_list pattern [pattern ...];
Padrão: nenhum
Contexto: http, server, location, if
Descrição:
Especifica um ou mais padrões a serem excluídos da variável $sorted_args (modo de lista negra). Isso é útil para remover parâmetros que quebram o cache (como timestamps, números de versão ou IDs de rastreamento) das chaves de cache, preservando outros parâmetros.
Tipos de padrões:
- name — correspondência exata (sem diferenciação entre maiúsculas e minúsculas)
- name* — correspondência por prefixo (corresponde a name, name_foo, name123, etc.)
- *name — correspondência por sufixo (corresponde a foo_name, bar_name, etc.)
- *name* — correspondência de contém (corresponde a qualquer parâmetro contendo name)
Padrões duplicados na lista são automaticamente removidos.
Exemplo:
location /api {
# Filtrar nomes exatos e todos os parâmetros de rastreamento utm_*
sorted_args_ignore_list timestamp version _ utm_* fb_*;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
Neste exemplo, requisições como /api?user=123×tamp=1234567890&utm_source=google&utm_medium=cpc produzirão $sorted_args como user=123, com timestamp e todos os parâmetros UTM filtrados.
sorted_args_allow_list
Sintaxe: sorted_args_allow_list pattern [pattern ...];
Padrão: nenhum
Contexto: http, server, location, if
Descrição:
Especifica um ou mais padrões para manter na variável $sorted_args (modo de lista branca). Todos os parâmetros que NÃO corresponderem a nenhum padrão serão excluídos. Isso é útil quando você deseja controlar estritamente quais parâmetros de query são permitidos para cache.
Tipos de padrões:
- name — correspondência exata (sem diferenciação entre maiúsculas e minúsculas)
- name* — correspondência por prefixo (corresponde a name, name_foo, name123, etc.)
- *name — correspondência por sufixo (corresponde a foo_name, bar_name, etc.)
- *name* — correspondência de contém (corresponde a qualquer parâmetro contendo name)
Quando tanto sorted_args_allow_list quanto sorted_args_ignore_list estão configurados, a lista branca é aplicada primeiro (mantendo apenas os parâmetros permitidos), depois a lista negra é aplicada para filtrar quaisquer parâmetros indesejados restantes.
Exemplo:
location /api {
# Permitir apenas parâmetros de paginação e ordenação
sorted_args_allow_list page* sort* limit;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
Neste exemplo, uma requisição como /api?page=1&page_size=10&sort=asc×tamp=123 produzirá $sorted_args como limit=10&page=1&page_size=10&sort=asc. O parâmetro timestamp é descartado porque não corresponde a nenhum padrão.
sorted_args_overwrite
Sintaxe: sorted_args_overwrite on | off;
Padrão: off
Contexto: http, server, location, if
Descrição:
Quando habilitada, esta diretiva sobrescreve automaticamente a variável interna $args com os argumentos de query ordenados (e opcionalmente filtrados). Isso é útil quando você deseja que todo o processamento subsequente (proxy, logging, redirecionamentos) use a querystring normalizada sem referenciar explicitamente $sorted_args.
A sobrescrita ocorre durante a fase de reescrita, então todas as fases subsequentes verão os argumentos ordenados em $args.
Exemplo:
location /api {
sorted_args_overwrite on;
sorted_args_ignore_list timestamp version;
# $args agora é automaticamente ordenado e filtrado
proxy_pass http://backend$uri?$args;
}
Neste exemplo, uma requisição para /api?z=1&a=2×tamp=123 será proxyada como /api?a=2&z=1 — ordenada e com timestamp filtrado.
sorted_args_dedupe
Sintaxe: sorted_args_dedupe first | last | off;
Padrão: off
Contexto: http, server, location, if
Descrição:
Controla como as chaves de parâmetros duplicados são tratadas. Quando múltiplos parâmetros têm a mesma chave (ex.: ?a=1&a=2&a=3), esta diretiva determina qual valor manter.
first— mantém apenas a primeira ocorrência de cada chavelast— mantém apenas a última ocorrência de cada chaveoff— mantém todas as ocorrências (comportamento padrão)
Isso é útil para normalizar URLs onde o mesmo parâmetro pode ser especificado várias vezes, garantindo chaves de cache consistentes.
Exemplo:
location /search {
sorted_args_dedupe first;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://backend;
}
Neste exemplo, uma requisição como /search?q=foo&q=bar&q=baz produzirá $sorted_args como q=foo, mantendo apenas o primeiro valor. Com sorted_args_dedupe last, produziria q=baz.
Exemplos de Uso
Normalização Básica de Chave de Cache
Normalize chaves de cache independentemente da ordem dos parâmetros:
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;
}
}
}
Sobrescrita Automática de Args
Reescreva automaticamente $args com parâmetros ordenados para todo o processamento subsequente:
server {
listen 80;
location /api {
sorted_args_overwrite on;
sorted_args_ignore_list timestamp _;
# Todos esses agora usam args ordenados e filtrados automaticamente
proxy_pass http://backend;
# Equivalente a: proxy_pass http://backend$uri?$sorted_args;
}
}
Filtrando Parâmetros que Quebram o Cache
Remova parâmetros de timestamp e rastreamento das chaves de cache:
location /static {
sorted_args_ignore_list _ t timestamp v version;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://cdn;
}
Modo de Lista Branca (Apenas Parâmetros Específicos)
Quando parâmetros de query podem causar processamento pesado no lado do servidor, use uma lista branca para controlar estritamente quais parâmetros são permitidos para cache:
location /search {
# Apenas esses parâmetros afetam a chave de cache; todos os outros são descartados
sorted_args_allow_list q page limit category;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://search_backend;
}
Neste exemplo, requisições como /search?q=nginx&page=1&debug=true&nocache=1 serão cacheadas usando apenas category=&limit=&page=1&q=nginx, ignorando efetivamente quaisquer parâmetros que quebram o cache ou de depuração.
Combinando Lista Branca e Lista Negra
Você pode usar ambas as diretivas juntas para um controle mais detalhado. A lista branca é aplicada primeiro, depois a lista negra:
location /api {
# Primeiro, mantenha apenas esses parâmetros
sorted_args_allow_list user_id action page limit timestamp;
# Depois, remova timestamp do conjunto permitido
sorted_args_ignore_list timestamp;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_pass http://api_backend;
}
Registrando Querystrings Normalizadas
Inclua querystrings ordenadas nos logs de acesso:
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;
# ...
}
}
Filtragem Específica de Localização
Diferentes localizações podem ter diferentes listas de filtro:
server {
# Padrão: filtrar parâmetros de rastreamento comuns
sorted_args_ignore_list _ utm_source utm_medium utm_campaign;
location /api {
# API: também filtrar versão e timestamp
sorted_args_ignore_list _ utm_source utm_medium utm_campaign version t;
proxy_pass http://api_backend;
}
location /content {
# Conteúdo: apenas filtrar rastreamento
proxy_pass http://content_backend;
}
}
Exemplo Completo
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;
# Filtrar parâmetros de rastreamento e que quebram o cache
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;
}
# Usar args ordenados sem filtragem
location / {
proxy_pass http://localhost:8081;
proxy_cache zone;
proxy_cache_key "$uri$sorted_args";
proxy_cache_valid 200 10m;
}
}
# Servidor backend para testes
server {
listen 8081;
location / {
return 200 "args: $args\nsorted_args: $sorted_args\n";
}
}
}
Como Funciona
- Extração de Parâmetros: O módulo analisa a querystring de
r->args, dividindo em&e= - Construção de Fila: Cada parâmetro é armazenado em uma estrutura de fila com sua chave, valor e par chave-valor completo
- Ordenação: Os parâmetros são ordenados usando uma função de comparação natural:
- Ordenação primária: nome do parâmetro (sem diferenciação entre maiúsculas e minúsculas, ordem natural)
- Ordenação secundária: string completa do parâmetro (key=value, ordem natural)
- Ordem natural significa que números embutidos são comparados numericamente:
item2<item10 - Remoção de Valores Vazios: Parâmetros com
=mas sem valor (como?a=) são removidos - Filtragem de Lista Branca: Se
sorted_args_allow_listestiver configurado, apenas parâmetros que correspondem a padrões são mantidos - Filtragem de Lista Negra: Parâmetros que correspondem a padrões em
sorted_args_ignore_listsão excluídos - Deduplicação: Se
sorted_args_dedupeestiver habilitado, apenas a primeira ou última ocorrência de cada chave é mantida - Reconstrução: Os parâmetros ordenados e filtrados são unidos com
¶ formar a string final
Testes
Este projeto usa Test::Nginx para sua suíte de testes, rodando dentro do Docker para builds reprodutíveis.
Pré-requisitos
- Docker
Executando Testes
Execute a suíte de testes completa:
make tests
Execute um arquivo de teste específico:
make tests T=t/sorted_args.t
Desative o modo HUP para depuração (mais lento, mas mais isolado):
make tests HUP=0
Use uma versão diferente do NGINX:
make tests NGINX_VERSION=release-1.26.2
Abra um shell interativo no contêiner de teste para depuração:
make shell
Cobertura de Testes
A suíte de testes verifica:
- ✅ Funcionalidade básica de ordenação
- ✅ Ordenação natural/númerica (ex.: p=1, p=2, p=10 na ordem correta)
- ✅ Parâmetros semelhantes a arrays (ex.: c[]=1&c[]=2)
- ✅ Filtragem de lista negra (sorted_args_ignore_list)
- ✅ Filtragem de lista branca (sorted_args_allow_list)
- ✅ Uso combinado de lista branca e lista negra
- ✅ Padrões curinga: prefixo (utm_*), sufixo (*_id), contém (*token*)
- ✅ Deduplicação: sorted_args_dedupe first e last
- ✅ Tratamento de querystring vazia
- ✅ Remoção de valores vazios (?a=&b=2 → b=2)
- ✅ Uso de chave de cache
- ✅ Herança de configuração em nível de localização
- ✅ Diretiva sorted_args_overwrite
- ✅ Correspondência de parâmetros sem diferenciação entre maiúsculas e minúsculas (tanto lista branca quanto lista negra)
- ✅ Parâmetros sem valores vs valores vazios
- ✅ Tratamento de parâmetros duplicados
- ✅ Preservação de caracteres especiais
- ✅ Strings de query malformadas (ampersands consecutivos)
- ✅ Parâmetros com múltiplos sinais de igual
- ✅ E2E: $args é modificado antes da avaliação da chave de cache (tempo da fase de REWRITE)
- ✅ E2E: Parâmetros reordenados produzem chaves de cache idênticas
- ✅ E2E: Diretrizes de reescrita veem $args sobrescrito
Considerações de Desempenho
- A querystring ordenada é computada uma vez por requisição e armazenada no contexto da requisição
- A ordenação usa o algoritmo eficiente baseado em fila do NGINX
- A filtragem usa comparação de strings sem diferenciação entre maiúsculas e minúsculas
- A alocação de memória é feita a partir do pool de requisições, portanto, nenhuma limpeza explícita é necessária
Limitações
- Os valores dos parâmetros não são decodificados/codificados; a codificação original é preservada
- A filtragem é sem diferenciação entre maiúsculas e minúsculas para nomes de parâmetros, mas preserva a caixa original na saída
- Parâmetros com valores vazios (ex.:
?a=) são sempre removidos; use?a(sem igual) para flags