Aller au contenu

sorted-args: Normalisation des paramètres de la chaîne de requête HTTP pour NGINX

Nécessite le plan Pro (ou supérieur) de l'abonnement GetPageSpeed NGINX Extras.

Installation

Vous pouvez installer ce module dans toute distribution basée sur RHEL, y compris, mais sans s'y limiter :

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

Activez le module en ajoutant ce qui suit en haut de /etc/nginx/nginx.conf :

load_module modules/ngx_http_sorted_args.so;

Ce document décrit nginx-module-sorted-args v3.0.0 publié le 31 décembre 2025.


Un puissant module Nginx qui normalise les paramètres de requête HTTP en les triant par ordre alphanumérique. Ce module fournit une représentation cohérente et canonique des chaînes de requête, quel que soit l'ordre des paramètres d'origine, ce qui le rend idéal pour la génération de clés de cache, la dé-duplication des requêtes et la normalisation des URL.

Vue d'ensemble

Différentes URL avec les mêmes paramètres de requête dans des ordres différents produiront la même chaîne de requête normalisée :

  • /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

Tous les exemples ci-dessus produiront la même chaîne de requête normalisée : a=1&b=2&c=3

Cette normalisation est accessible via la variable $sorted_args, qui peut être utilisée dans les clés de cache, les journaux et d'autres contextes Nginx.

Test Build

Fonctionnalités

  • Tri naturel des paramètres de requête par clé, puis par valeur (par exemple, item2 < item10)
  • Suppression des valeurs vides — les paramètres comme ?a= sont automatiquement supprimés
  • Mode liste noire (sorted_args_ignore_list) pour exclure des paramètres spécifiques de la sortie triée
  • Mode liste blanche (sorted_args_allow_list) pour ne conserver que des paramètres spécifiques, en supprimant tous les autres
  • Modèles génériques — utilisez utm_* pour correspondre à tous les paramètres UTM, *_id pour les suffixes
  • Dé-duplication (sorted_args_dedupe) — ne garder que la première ou la dernière occurrence des clés dupliquées
  • Remplacement optionnel de $args pour remplacer automatiquement la chaîne de requête d'origine par les arguments triés
  • Configuration au niveau de l'emplacement avec héritage des contextes serveur et principal
  • Mise en œuvre efficace utilisant le tri de file d'attente natif de Nginx
  • Correspondance de noms de paramètres insensible à la casse pour le filtrage
  • Détection des doublons dans les listes de filtrage

Configuration

Variables

$sorted_args

Renvoie les paramètres de la chaîne de requête triés par ordre alphanumérique par nom de paramètre, puis par valeur. Les paramètres sont joints avec & et conservent leur encodage URL d'origine.

Exemple :

Requête : /page?zebra=1&apple=2&banana=3
$sorted_args : apple=2&banana=3&zebra=1

Comportement : - Une chaîne de requête vide renvoie une chaîne vide - Les paramètres sans valeurs (par exemple, ?param) sont inclus comme param - Les paramètres avec des valeurs vides (par exemple, ?param=) sont automatiquement supprimés - Les valeurs multiples pour le même paramètre sont triées individuellement - Tri naturel : p=1, p=2, p=10 se trient correctement (pas p=1, p=10, p=2) - Tri insensible à la casse pour les noms de paramètres

Directives

sorted_args_ignore_list

Syntaxe : sorted_args_ignore_list pattern [pattern ...];

Par défaut : aucun

Contexte : http, server, location, if

Description :

Spécifie un ou plusieurs modèles à exclure de la variable $sorted_args (mode liste noire). Cela est utile pour supprimer les paramètres de contournement de cache (comme les horodatages, les numéros de version ou les ID de suivi) des clés de cache tout en préservant d'autres paramètres.

Types de modèles : - name — correspondance exacte (insensible à la casse) - name* — correspondance par préfixe (correspond à name, name_foo, name123, etc.) - *name — correspondance par suffixe (correspond à foo_name, bar_name, etc.) - *name* — correspondance par contenu (correspond à tout paramètre contenant name)

Les modèles en double dans la liste sont automatiquement supprimés.

Exemple :

location /api {
    # Filtrer les noms exacts et tous les paramètres de suivi utm_*
    sorted_args_ignore_list timestamp version _ utm_* fb_*;

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

Dans cet exemple, des requêtes comme /api?user=123&timestamp=1234567890&utm_source=google&utm_medium=cpc produiront $sorted_args comme user=123, avec timestamp et tous les paramètres UTM filtrés.

sorted_args_allow_list

Syntaxe : sorted_args_allow_list pattern [pattern ...];

Par défaut : aucun

Contexte : http, server, location, if

Description :

Spécifie un ou plusieurs modèles à conserver dans la variable $sorted_args (mode liste blanche). Tous les paramètres NE correspondant PAS à un modèle seront exclus. Cela est utile lorsque vous souhaitez contrôler strictement quels paramètres de requête sont autorisés pour le cache.

Types de modèles : - name — correspondance exacte (insensible à la casse) - name* — correspondance par préfixe (correspond à name, name_foo, name123, etc.) - *name — correspondance par suffixe (correspond à foo_name, bar_name, etc.) - *name* — correspondance par contenu (correspond à tout paramètre contenant name)

Lorsque sorted_args_allow_list et sorted_args_ignore_list sont configurés, la liste blanche est appliquée en premier (ne conservant que les paramètres autorisés), puis la liste noire est appliquée pour filtrer les paramètres indésirables restants.

Exemple :

location /api {
    # N'autoriser que les paramètres de pagination et de tri
    sorted_args_allow_list page* sort* limit;

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

Dans cet exemple, une requête comme /api?page=1&page_size=10&sort=asc&timestamp=123 produira $sorted_args comme limit=10&page=1&page_size=10&sort=asc. Le paramètre timestamp est supprimé car il ne correspond à aucun modèle.

sorted_args_overwrite

Syntaxe : sorted_args_overwrite on | off;

Par défaut : off

Contexte : http, server, location, if

Description :

Lorsqu'il est activé, cette directive remplace automatiquement la variable intégrée $args par les arguments de requête triés (et éventuellement filtrés). Cela est utile lorsque vous souhaitez que tout le traitement en aval (proxy, journaux, redirections) utilise la chaîne de requête normalisée sans référencer explicitement $sorted_args.

Le remplacement se produit pendant la phase de réécriture, donc toutes les phases suivantes verront les arguments triés dans $args.

Exemple :

location /api {
    sorted_args_overwrite on;
    sorted_args_ignore_list timestamp version;

    # $args est maintenant automatiquement trié et filtré
    proxy_pass http://backend$uri?$args;
}

Dans cet exemple, une requête à /api?z=1&a=2&timestamp=123 sera proxifiée comme /api?a=2&z=1 — triée et avec timestamp filtré.

sorted_args_dedupe

Syntaxe : sorted_args_dedupe first | last | off;

Par défaut : off

Contexte : http, server, location, if

Description :

Contrôle la manière dont les clés de paramètres dupliquées sont gérées. Lorsque plusieurs paramètres ont la même clé (par exemple, ?a=1&a=2&a=3), cette directive détermine quelle valeur conserver.

  • first — ne garder que la première occurrence de chaque clé
  • last — ne garder que la dernière occurrence de chaque clé
  • off — garder toutes les occurrences (comportement par défaut)

Cela est utile pour normaliser les URL où le même paramètre peut être spécifié plusieurs fois, garantissant des clés de cache cohérentes.

Exemple :

location /search {
    sorted_args_dedupe first;

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

Dans cet exemple, une requête comme /search?q=foo&q=bar&q=baz produira $sorted_args comme q=foo, ne gardant que la première valeur. Avec sorted_args_dedupe last, cela produirait q=baz.

Exemples d'utilisation

Normalisation de la clé de cache de base

Normalisez les clés de cache indépendamment de l'ordre des paramètres :

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

Remplacement automatique des arguments

Réécrivez automatiquement $args avec des paramètres triés pour tout traitement en aval :

server {
    listen 80;

    location /api {
        sorted_args_overwrite on;
        sorted_args_ignore_list timestamp _;

        # Tous ceux-ci utilisent maintenant automatiquement des args triés et filtrés
        proxy_pass http://backend;
        # Équivalent à : proxy_pass http://backend$uri?$sorted_args;
    }
}

Filtrage des paramètres de contournement de cache

Supprimez les horodatages et les paramètres de suivi des clés 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;
}

Mode liste blanche (Autoriser uniquement des paramètres spécifiques)

Lorsque les paramètres de requête peuvent provoquer un traitement intensif côté serveur, utilisez une liste blanche pour contrôler strictement quels paramètres sont autorisés pour le cache :

location /search {
    # Seuls ces paramètres affectent la clé de cache ; tous les autres sont supprimés
    sorted_args_allow_list q page limit category;

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

Dans cet exemple, des requêtes comme /search?q=nginx&page=1&debug=true&nocache=1 seront mises en cache en utilisant uniquement category=&limit=&page=1&q=nginx, ignorant effectivement tous les paramètres de contournement de cache ou de débogage.

Combinaison de la liste blanche et de la liste noire

Vous pouvez utiliser les deux directives ensemble pour un contrôle précis. La liste blanche est appliquée en premier, puis la liste noire :

location /api {
    # D'abord, ne garder que ces paramètres
    sorted_args_allow_list user_id action page limit timestamp;

    # Ensuite, supprimer le timestamp de l'ensemble autorisé
    sorted_args_ignore_list timestamp;

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

Journalisation des chaînes de requête normalisées

Incluez les chaînes de requête triées dans les journaux d'accès :

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

Filtrage spécifique à l'emplacement

Différents emplacements peuvent avoir différentes listes de filtrage :

server {
    # Par défaut : filtrer les paramètres de suivi communs
    sorted_args_ignore_list _ utm_source utm_medium utm_campaign;

    location /api {
        # API : filtrer également la version et l'horodatage
        sorted_args_ignore_list _ utm_source utm_medium utm_campaign version t;
        proxy_pass http://api_backend;
    }

    location /content {
        # Contenu : ne filtrer que le suivi
        proxy_pass http://content_backend;
    }
}

Exemple complet

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;

        # Filtrer les paramètres de suivi et de contournement de 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;
        }

        # Utiliser des args triés sans filtrage
        location / {
            proxy_pass http://localhost:8081;

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

    # Serveur backend pour les tests
    server {
        listen       8081;

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

Comment ça fonctionne

  1. Extraction des paramètres : Le module analyse la chaîne de requête à partir de r->args, en se séparant sur & et =
  2. Construction de la file d'attente : Chaque paramètre est stocké dans une structure de file d'attente avec sa clé, sa valeur et la paire clé-valeur complète
  3. Tri : Les paramètres sont triés à l'aide d'une fonction de comparaison naturelle :
  4. Tri principal : nom du paramètre (insensible à la casse, ordre naturel)
  5. Tri secondaire : chaîne de paramètre complète (key=value, ordre naturel)
  6. L'ordre naturel signifie que les nombres intégrés sont comparés numériquement : item2 < item10
  7. Suppression des valeurs vides : Les paramètres avec = mais sans valeur (comme ?a=) sont supprimés
  8. Filtrage de la liste blanche : Si sorted_args_allow_list est configuré, seuls les paramètres correspondant aux modèles sont conservés
  9. Filtrage de la liste noire : Les paramètres correspondant aux modèles dans sorted_args_ignore_list sont exclus
  10. Dé-duplication : Si sorted_args_dedupe est activé, seule la première ou la dernière occurrence de chaque clé est conservée
  11. Reconstruction : Les paramètres triés et filtrés sont joints avec & pour former la chaîne finale

Tests

Ce projet utilise Test::Nginx pour sa suite de tests, s'exécutant à l'intérieur de Docker pour des builds reproductibles.

Prérequis

  • Docker

Exécution des tests

Exécutez l'ensemble de la suite de tests :

make tests

Exécutez un fichier de test spécifique :

make tests T=t/sorted_args.t

Désactivez le mode HUP pour le débogage (plus lent mais plus isolé) :

make tests HUP=0

Utilisez une version différente de Nginx :

make tests NGINX_VERSION=release-1.26.2

Ouvrez un shell interactif dans le conteneur de test pour le débogage :

make shell

Couverture des tests

La suite de tests vérifie : - ✅ Fonctionnalité de tri de base - ✅ Tri naturel/numerique (par exemple, p=1, p=2, p=10 dans le bon ordre) - ✅ Paramètres de type tableau (par exemple, c[]=1&c[]=2) - ✅ Filtrage de la liste noire (sorted_args_ignore_list) - ✅ Filtrage de la liste blanche (sorted_args_allow_list) - ✅ Utilisation combinée de la liste blanche et de la liste noire - ✅ Modèles génériques : préfixe (utm_*), suffixe (*_id), contient (*token*) - ✅ Dé-duplication : sorted_args_dedupe first et last - ✅ Gestion des chaînes de requête vides - ✅ Suppression des valeurs vides (?a=&b=2b=2) - ✅ Utilisation de la clé de cache - ✅ Héritage de la configuration au niveau de l'emplacement - ✅ Directive sorted_args_overwrite - ✅ Correspondance de paramètres insensible à la casse (à la fois liste blanche et liste noire) - ✅ Paramètres sans valeurs vs valeurs vides - ✅ Gestion des paramètres dupliqués - ✅ Préservation des caractères spéciaux - ✅ Chaînes de requête mal formées (ampersands consécutifs) - ✅ Paramètres avec plusieurs signes égal - ✅ E2E : $args est modifié avant l'évaluation de la clé de cache (timing de la phase REWRITE) - ✅ E2E : Les paramètres réordonnés produisent des clés de cache identiques - ✅ E2E : Les directives de réécriture voient $args écrasé

Considérations de performance

  • La chaîne de requête triée est calculée une fois par requête et mise en cache dans le contexte de la requête
  • Le tri utilise l'algorithme efficace basé sur la file d'attente de Nginx
  • Le filtrage utilise une comparaison de chaînes insensible à la casse
  • L'allocation de mémoire est effectuée à partir du pool de requêtes, donc aucun nettoyage explicite n'est nécessaire

Limitations

  • Les valeurs des paramètres ne sont pas décodées/encodées ; l'encodage d'origine est préservé
  • Le filtrage est insensible à la casse pour les noms de paramètres mais préserve la casse d'origine dans la sortie
  • Les paramètres avec des valeurs vides (par exemple, ?a=) sont toujours supprimés ; utilisez ?a (sans égal) pour les indicateurs