Saltar a contenido

sorted-args: Normalización de parámetros de la cadena de consulta HTTP para NGINX

Requiere el plan Pro (o superior) de la suscripción NGINX Extras de GetPageSpeed.

Instalación

Puedes instalar este módulo en cualquier distribución basada en RHEL, incluyendo, pero no limitado a:

  • RedHat Enterprise Linux 7, 8, 9 y 10
  • CentOS 7, 8, 9
  • AlmaLinux 8, 9
  • Rocky Linux 8, 9
  • Amazon Linux 2 y 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

Habilita el módulo añadiendo lo siguiente en la parte superior de /etc/nginx/nginx.conf:

load_module modules/ngx_http_sorted_args.so;

Este documento describe nginx-module-sorted-args v3.0.0 lanzado el 31 de diciembre de 2025.


Un poderoso módulo de Nginx que normaliza los parámetros de la cadena de consulta de la solicitud HTTP ordenándolos alfanuméricamente. Este módulo proporciona una representación consistente y canónica de las cadenas de consulta independientemente del orden original de los parámetros, lo que lo hace ideal para la generación de claves de caché, deduplicación de solicitudes y normalización de URL.

Descripción general

Diferentes URLs con los mismos parámetros de consulta en diferentes órdenes producirán la misma cadena de consulta 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 los anteriores producirán la misma cadena de consulta normalizada: a=1&b=2&c=3

Esta normalización es accesible a través de la variable $sorted_args, que se puede usar en claves de caché, registros y otros contextos de Nginx.

Test Build

Características

  • Ordenamiento natural de los parámetros de consulta por clave, luego por valor (por ejemplo, item2 < item10)
  • Eliminación de valores vacíos — parámetros como ?a= son eliminados automáticamente
  • Modo de lista negra (sorted_args_ignore_list) para excluir parámetros específicos de la salida ordenada
  • Modo de lista blanca (sorted_args_allow_list) para mantener solo parámetros específicos, eliminando todos los demás
  • Patrones comodín — usa utm_* para coincidir con todos los parámetros UTM, *_id para sufijos
  • Deduplicación (sorted_args_dedupe) — mantiene solo la primera o última ocurrencia de claves duplicadas
  • Sobrescritura opcional de $args para reemplazar automáticamente la cadena de consulta original con los argumentos ordenados
  • Configuración a nivel de ubicación con herencia de los contextos de servidor y principal
  • Implementación eficiente utilizando el ordenamiento de cola nativo de Nginx
  • Coincidencia de nombres de parámetros sin distinción de mayúsculas y minúsculas para filtrado
  • Detección de duplicados en listas de filtros

Configuración

Variables

$sorted_args

Devuelve los parámetros de la cadena de consulta ordenados alfanuméricamente por nombre de parámetro, luego por valor. Los parámetros se unen con & y mantienen su codificación URL original.

Ejemplo:

Solicitud: /page?zebra=1&apple=2&banana=3
$sorted_args: apple=2&banana=3&zebra=1

Comportamiento: - La cadena de consulta vacía devuelve una cadena vacía - Los parámetros sin valores (por ejemplo, ?param) se incluyen como param - Los parámetros con valores vacíos (por ejemplo, ?param=) son eliminados automáticamente - Múltiples valores para el mismo parámetro se ordenan individualmente - Ordenamiento natural: p=1, p=2, p=10 se ordenan correctamente (no p=1, p=10, p=2) - Ordenamiento sin distinción de mayúsculas y minúsculas para nombres de parámetros

Directivas

sorted_args_ignore_list

Sintaxis: sorted_args_ignore_list pattern [pattern ...];

Por defecto: ninguno

Contexto: http, server, location, if

Descripción:

Especifica uno o más patrones para excluir de la variable $sorted_args (modo de lista negra). Esto es útil para eliminar parámetros que rompen la caché (como marcas de tiempo, números de versión o IDs de seguimiento) de las claves de caché mientras se preservan otros parámetros.

Tipos de patrones: - name — coincidencia exacta (sin distinción de mayúsculas y minúsculas) - name* — coincidencia de prefijo (coincide con name, name_foo, name123, etc.) - *name — coincidencia de sufijo (coincide con foo_name, bar_name, etc.) - *name* — coincidencia de contiene (coincide con cualquier parámetro que contenga name)

Los patrones duplicados en la lista son eliminados automáticamente.

Ejemplo:

location /api {
    # Filtrar nombres exactos y todos los parámetros de seguimiento utm_*
    sorted_args_ignore_list timestamp version _ utm_* fb_*;

    proxy_cache_key "$uri$sorted_args";
    proxy_pass http://backend;
}

En este ejemplo, solicitudes como /api?user=123&timestamp=1234567890&utm_source=google&utm_medium=cpc producirán $sorted_args como user=123, con timestamp y todos los parámetros UTM filtrados.

sorted_args_allow_list

Sintaxis: sorted_args_allow_list pattern [pattern ...];

Por defecto: ninguno

Contexto: http, server, location, if

Descripción:

Especifica uno o más patrones para mantener en la variable $sorted_args (modo de lista blanca). Todos los parámetros que NO coincidan con ningún patrón serán excluidos. Esto es útil cuando deseas controlar estrictamente qué parámetros de consulta están permitidos para la caché.

Tipos de patrones: - name — coincidencia exacta (sin distinción de mayúsculas y minúsculas) - name* — coincidencia de prefijo (coincide con name, name_foo, name123, etc.) - *name — coincidencia de sufijo (coincide con foo_name, bar_name, etc.) - *name* — coincidencia de contiene (coincide con cualquier parámetro que contenga name)

Cuando se configuran tanto sorted_args_allow_list como sorted_args_ignore_list, la lista blanca se aplica primero (manteniendo solo los parámetros permitidos), luego se aplica la lista de ignorados para filtrar cualquier parámetro no deseado restante.

Ejemplo:

location /api {
    # Solo permitir parámetros de paginación y ordenamiento
    sorted_args_allow_list page* sort* limit;

    proxy_cache_key "$uri$sorted_args";
    proxy_pass http://backend;
}

En este ejemplo, una solicitud como /api?page=1&page_size=10&sort=asc&timestamp=123 producirá $sorted_args como limit=10&page=1&page_size=10&sort=asc. El parámetro timestamp se elimina porque no coincide con ningún patrón.

sorted_args_overwrite

Sintaxis: sorted_args_overwrite on | off;

Por defecto: off

Contexto: http, server, location, if

Descripción:

Cuando está habilitada, esta directiva sobrescribe automáticamente la variable incorporada $args con los argumentos de consulta ordenados (y opcionalmente filtrados). Esto es útil cuando deseas que todo el procesamiento posterior (proxy, registros, redirecciones) utilice la cadena de consulta normalizada sin hacer referencia explícita a $sorted_args.

La sobrescritura ocurre durante la fase de reescritura, por lo que todas las fases posteriores verán los argumentos ordenados en $args.

Ejemplo:

location /api {
    sorted_args_overwrite on;
    sorted_args_ignore_list timestamp version;

    # $args ahora está automáticamente ordenado y filtrado
    proxy_pass http://backend$uri?$args;
}

En este ejemplo, una solicitud a /api?z=1&a=2&timestamp=123 será proxied como /api?a=2&z=1 — ordenada y con timestamp filtrado.

sorted_args_dedupe

Sintaxis: sorted_args_dedupe first | last | off;

Por defecto: off

Contexto: http, server, location, if

Descripción:

Controla cómo se manejan las claves de parámetros duplicados. Cuando múltiples parámetros tienen la misma clave (por ejemplo, ?a=1&a=2&a=3), esta directiva determina qué valor mantener.

  • first — mantener solo la primera ocurrencia de cada clave
  • last — mantener solo la última ocurrencia de cada clave
  • off — mantener todas las ocurrencias (comportamiento predeterminado)

Esto es útil para normalizar URLs donde el mismo parámetro podría especificarse múltiples veces, asegurando claves de caché consistentes.

Ejemplo:

location /search {
    sorted_args_dedupe first;

    proxy_cache_key "$uri$sorted_args";
    proxy_pass http://backend;
}

En este ejemplo, una solicitud como /search?q=foo&q=bar&q=baz producirá $sorted_args como q=foo, manteniendo solo el primer valor. Con sorted_args_dedupe last, produciría q=baz.

Ejemplos de uso

Normalización básica de claves de caché

Normaliza las claves de caché independientemente del orden de los 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;
        }
    }
}

Sobrescritura automática de argumentos

Reescribe automáticamente $args con parámetros ordenados para todo el procesamiento posterior:

server {
    listen 80;

    location /api {
        sorted_args_overwrite on;
        sorted_args_ignore_list timestamp _;

        # Todos estos ahora usan automáticamente args ordenados y filtrados
        proxy_pass http://backend;
        # Equivalente a: proxy_pass http://backend$uri?$sorted_args;
    }
}

Filtrado de parámetros que rompen la caché

Elimina parámetros de marca de tiempo y de seguimiento de las claves de caché:

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 blanca (solo parámetros específicos permitidos)

Cuando los parámetros de consulta pueden causar un procesamiento pesado en el servidor, utiliza una lista blanca para controlar estrictamente qué parámetros están permitidos para la caché:

location /search {
    # Solo estos parámetros afectan la clave de caché; todos los demás son eliminados
    sorted_args_allow_list q page limit category;

    proxy_cache zone;
    proxy_cache_key "$uri$sorted_args";
    proxy_pass http://search_backend;
}

En este ejemplo, solicitudes como /search?q=nginx&page=1&debug=true&nocache=1 serán almacenadas en caché utilizando solo category=&limit=&page=1&q=nginx, ignorando efectivamente cualquier parámetro que rompa la caché o de depuración.

Combinando lista blanca y lista negra

Puedes usar ambas directivas juntas para un control más detallado. La lista blanca se aplica primero, luego la lista negra:

location /api {
    # Primero, mantener solo estos parámetros
    sorted_args_allow_list user_id action page limit timestamp;

    # Luego, eliminar timestamp del conjunto permitido
    sorted_args_ignore_list timestamp;

    proxy_cache zone;
    proxy_cache_key "$uri$sorted_args";
    proxy_pass http://api_backend;
}

Registro de cadenas de consulta normalizadas

Incluye cadenas de consulta ordenadas en los registros de acceso:

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;
        # ...
    }
}

Filtrado específico por ubicación

Diferentes ubicaciones pueden tener diferentes listas de filtros:

server {
    # Predeterminado: filtrar parámetros de seguimiento comunes
    sorted_args_ignore_list _ utm_source utm_medium utm_campaign;

    location /api {
        # API: también filtrar versión y marca de tiempo
        sorted_args_ignore_list _ utm_source utm_medium utm_campaign version t;
        proxy_pass http://api_backend;
    }

    location /content {
        # Contenido: solo filtrar seguimiento
        proxy_pass http://content_backend;
    }
}

Ejemplo 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 seguimiento y que rompen la caché
        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 sin filtrado
        location / {
            proxy_pass http://localhost:8081;

            proxy_cache zone;
            proxy_cache_key "$uri$sorted_args";
            proxy_cache_valid 200 10m;
        }
    }

    # Servidor backend para pruebas
    server {
        listen       8081;

        location / {
            return 200 "args: $args\nsorted_args: $sorted_args\n";
        }
    }
}

Cómo funciona

  1. Extracción de parámetros: El módulo analiza la cadena de consulta de r->args, dividiendo en & y =
  2. Construcción de cola: Cada parámetro se almacena en una estructura de cola con su clave, valor y par clave-valor completo
  3. Ordenamiento: Los parámetros se ordenan utilizando una función de comparación natural:
  4. Orden primario: nombre del parámetro (sin distinción de mayúsculas y minúsculas, orden natural)
  5. Orden secundario: cadena de parámetro completa (key=value, orden natural)
  6. El orden natural significa que los números incrustados se comparan numéricamente: item2 < item10
  7. Eliminación de valores vacíos: Los parámetros con = pero sin valor (como ?a=) son eliminados
  8. Filtrado de lista blanca: Si sorted_args_allow_list está configurado, solo se mantienen los parámetros que coinciden con los patrones
  9. Filtrado de lista negra: Los parámetros que coinciden con los patrones en sorted_args_ignore_list son excluidos
  10. Deduplicación: Si sorted_args_dedupe está habilitado, solo se mantiene la primera o última ocurrencia de cada clave
  11. Reconstrucción: Los parámetros ordenados y filtrados se unen con & para formar la cadena final

Pruebas

Este proyecto utiliza Test::Nginx para su suite de pruebas, ejecutándose dentro de Docker para construcciones reproducibles.

Requisitos previos

  • Docker

Ejecución de pruebas

Ejecuta la suite de pruebas completa:

make tests

Ejecuta un archivo de prueba específico:

make tests T=t/sorted_args.t

Desactiva el modo HUP para depuración (más lento pero más aislado):

make tests HUP=0

Usa una versión diferente de Nginx:

make tests NGINX_VERSION=release-1.26.2

Abre un shell interactivo en el contenedor de prueba para depuración:

make shell

Cobertura de pruebas

La suite de pruebas verifica: - ✅ Funcionalidad básica de ordenamiento - ✅ Ordenamiento natural/numerico (por ejemplo, p=1, p=2, p=10 en el orden correcto) - ✅ Parámetros similares a arreglos (por ejemplo, c[]=1&c[]=2) - ✅ Filtrado de lista negra (sorted_args_ignore_list) - ✅ Filtrado de lista blanca (sorted_args_allow_list) - ✅ Uso combinado de lista blanca y lista negra - ✅ Patrones comodín: prefijo (utm_*), sufijo (*_id), contiene (*token*) - ✅ Deduplicación: sorted_args_dedupe first y last - ✅ Manejo de cadena de consulta vacía - ✅ Eliminación de valores vacíos (?a=&b=2b=2) - ✅ Uso de clave de caché - ✅ Herencia de configuración a nivel de ubicación - ✅ Directiva sorted_args_overwrite - ✅ Coincidencia de parámetros sin distinción de mayúsculas y minúsculas (tanto lista blanca como lista negra) - ✅ Parámetros sin valores vs valores vacíos - ✅ Manejo de parámetros duplicados - ✅ Preservación de caracteres especiales - ✅ Cadenas de consulta mal formadas (ampersands consecutivos) - ✅ Parámetros con múltiples signos de igual - ✅ E2E: $args se modifica antes de la evaluación de la clave de caché (temporización de la fase de REWRITE) - ✅ E2E: Parámetros reordenados producen claves de caché idénticas - ✅ E2E: Las directivas de reescritura ven el $args sobrescrito

Consideraciones de rendimiento

  • La cadena de consulta ordenada se calcula una vez por solicitud y se almacena en el contexto de la solicitud
  • El ordenamiento utiliza el algoritmo eficiente basado en cola de Nginx
  • El filtrado utiliza comparación de cadenas sin distinción de mayúsculas y minúsculas
  • La asignación de memoria se realiza desde el grupo de solicitudes, por lo que no se necesita limpieza explícita

Limitaciones

  • Los valores de los parámetros no se decodifican/codifican; se preserva la codificación original
  • El filtrado es sin distinción de mayúsculas y minúsculas para los nombres de los parámetros pero preserva el caso original en la salida
  • Los parámetros con valores vacíos (por ejemplo, ?a=) siempre son eliminados; usa ?a (sin igual) para banderas