Zum Inhalt

sorted-args: Normalisierung von HTTP-Querystring-Parametern für NGINX

Erfordert den Pro-Plan (oder höher) des GetPageSpeed NGINX Extras-Abonnements.

Installation

Sie können dieses Modul in jeder RHEL-basierten Distribution installieren, einschließlich, aber nicht beschränkt auf:

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

Aktivieren Sie das Modul, indem Sie Folgendes an den Anfang von /etc/nginx/nginx.conf hinzufügen:

load_module modules/ngx_http_sorted_args.so;

Dieses Dokument beschreibt nginx-module-sorted-args v3.0.0, veröffentlicht am 31. Dezember 2025.


Ein leistungsstarkes Nginx-Modul, das HTTP-Anforderungs-Querystring-Parameter normalisiert, indem es sie alphanumerisch sortiert. Dieses Modul bietet eine konsistente, kanonische Darstellung von Query-Strings, unabhängig von der ursprünglichen Parameterreihenfolge, was es ideal für die Generierung von Cache-Schlüsseln, die Duplikation von Anforderungen und die Normalisierung von URLs macht.

Übersicht

Verschiedene URLs mit denselben Query-Parametern in unterschiedlicher Reihenfolge erzeugen denselben normalisierten Querystring:

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

Alle oben genannten erzeugen denselben normalisierten Querystring: a=1&b=2&c=3

Diese Normalisierung ist über die Variable $sorted_args zugänglich, die in Cache-Schlüsseln, Protokollierung und anderen Nginx-Kontexten verwendet werden kann.

Test Build

Funktionen

  • Natürliche Sortierung der Query-Parameter nach Schlüssel, dann nach Wert (z.B. item2 < item10)
  • Entfernen leerer Werte — Parameter wie ?a= werden automatisch entfernt
  • Blocklistenmodus (sorted_args_ignore_list), um spezifische Parameter vom sortierten Output auszuschließen
  • Whitelistmodus (sorted_args_allow_list), um nur spezifische Parameter zu behalten und alle anderen zu verwerfen
  • Wildcard-Muster — verwenden Sie utm_*, um alle UTM-Parameter zu erfassen, *_id für Suffixe
  • Duplikatserkennung (sorted_args_dedupe) — nur das erste oder letzte Vorkommen von doppelten Schlüsseln behalten
  • Optionale $args-Überschreibung, um den ursprünglichen Querystring automatisch durch sortierte Argumente zu ersetzen
  • Standortbezogene Konfiguration mit Vererbung von Server- und Hauptkontexten
  • Effiziente Implementierung unter Verwendung der nativen Warteschlangen-Sortierung von Nginx
  • Groß-/Kleinschreibung-unempfindliche Übereinstimmung von Parameternamen zur Filterung
  • Duplikaterkennung in Filterlisten

Konfiguration

Variablen

$sorted_args

Gibt die Querystring-Parameter zurück, die alphanumerisch nach Parametername und dann nach Wert sortiert sind. Parameter werden mit & verbunden und behalten ihre ursprüngliche URL-Codierung.

Beispiel:

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

Verhalten: - Ein leerer Querystring gibt einen leeren String zurück - Parameter ohne Werte (z.B. ?param) werden als param einbezogen - Parameter mit leeren Werten (z.B. ?param=) werden automatisch entfernt - Mehrere Werte für denselben Parameter werden einzeln sortiert - Natürliche Sortierung: p=1, p=2, p=10 sortieren korrekt (nicht p=1, p=10, p=2) - Groß-/Kleinschreibung-unempfindliche Sortierung für Parameternamen

Direktiven

sorted_args_ignore_list

Syntax: sorted_args_ignore_list pattern [pattern ...];

Standard: keine

Kontext: http, server, location, if

Beschreibung:

Gibt ein oder mehrere Muster an, die aus der Variable $sorted_args ausgeschlossen werden sollen (Blocklistenmodus). Dies ist nützlich, um Cache-busting-Parameter (wie Zeitstempel, Versionsnummern oder Tracking-IDs) aus Cache-Schlüsseln zu entfernen, während andere Parameter erhalten bleiben.

Musterarten: - name — exakte Übereinstimmung (groß-/kleinschreibung-unempfindlich) - name* — Präfixübereinstimmung (übereinstimmt mit name, name_foo, name123 usw.) - *name — Suffixübereinstimmung (übereinstimmt mit foo_name, bar_name usw.) - *name* — Enthält-Übereinstimmung (übereinstimmt mit jedem Parameter, der name enthält)

Doppelte Muster in der Liste werden automatisch entfernt.

Beispiel:

location /api {
    # Exakte Namen und alle utm_* Tracking-Parameter filtern
    sorted_args_ignore_list timestamp version _ utm_* fb_*;

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

In diesem Beispiel erzeugen Anfragen wie /api?user=123&timestamp=1234567890&utm_source=google&utm_medium=cpc $sorted_args als user=123, wobei timestamp und alle UTM-Parameter herausgefiltert werden.

sorted_args_allow_list

Syntax: sorted_args_allow_list pattern [pattern ...];

Standard: keine

Kontext: http, server, location, if

Beschreibung:

Gibt ein oder mehrere Muster an, die in der Variable $sorted_args behalten werden sollen (Whitelistmodus). Alle Parameter, die keinem Muster entsprechen, werden ausgeschlossen. Dies ist nützlich, wenn Sie streng kontrollieren möchten, welche Query-Parameter für das Caching zugelassen sind.

Musterarten: - name — exakte Übereinstimmung (groß-/kleinschreibung-unempfindlich) - name* — Präfixübereinstimmung (übereinstimmt mit name, name_foo, name123 usw.) - *name — Suffixübereinstimmung (übereinstimmt mit foo_name, bar_name usw.) - *name* — Enthält-Übereinstimmung (übereinstimmt mit jedem Parameter, der name enthält)

Wenn sowohl sorted_args_allow_list als auch sorted_args_ignore_list konfiguriert sind, wird die Whitelist zuerst angewendet (nur erlaubte Parameter werden behalten), dann wird die Ignorierliste angewendet, um verbleibende unerwünschte Parameter herauszufiltern.

Beispiel:

location /api {
    # Nur Paginierungs- und Sortierungsparameter zulassen
    sorted_args_allow_list page* sort* limit;

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

In diesem Beispiel wird eine Anfrage wie /api?page=1&page_size=10&sort=asc&timestamp=123 $sorted_args als limit=10&page=1&page_size=10&sort=asc erzeugen. Der Parameter timestamp wird verworfen, da er keinem Muster entspricht.

sorted_args_overwrite

Syntax: sorted_args_overwrite on | off;

Standard: off

Kontext: http, server, location, if

Beschreibung:

Wenn aktiviert, überschreibt diese Direktive automatisch die integrierte Variable $args mit den sortierten (und optional gefilterten) Query-Argumenten. Dies ist nützlich, wenn Sie möchten, dass alle nachgelagerten Prozesse (Proxying, Protokollierung, Weiterleitungen) den normalisierten Querystring verwenden, ohne explizit auf $sorted_args zu verweisen.

Die Überschreibung erfolgt während der Rewrite-Phase, sodass alle nachfolgenden Phasen die sortierten Argumente in $args sehen.

Beispiel:

location /api {
    sorted_args_overwrite on;
    sorted_args_ignore_list timestamp version;

    # $args ist jetzt automatisch sortiert und gefiltert
    proxy_pass http://backend$uri?$args;
}

In diesem Beispiel wird eine Anfrage an /api?z=1&a=2&timestamp=123 als /api?a=2&z=1 proxied — sortiert und mit timestamp herausgefiltert.

sorted_args_dedupe

Syntax: sorted_args_dedupe first | last | off;

Standard: off

Kontext: http, server, location, if

Beschreibung:

Steuert, wie doppelte Parameter-Schlüssel behandelt werden. Wenn mehrere Parameter denselben Schlüssel haben (z.B. ?a=1&a=2&a=3), bestimmt diese Direktive, welchen Wert man behalten soll.

  • first — nur das erste Vorkommen jedes Schlüssels behalten
  • last — nur das letzte Vorkommen jedes Schlüssels behalten
  • off — alle Vorkommen behalten (Standardverhalten)

Dies ist nützlich zur Normalisierung von URLs, bei denen derselbe Parameter möglicherweise mehrfach angegeben wird, um konsistente Cache-Schlüssel sicherzustellen.

Beispiel:

location /search {
    sorted_args_dedupe first;

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

In diesem Beispiel wird eine Anfrage wie /search?q=foo&q=bar&q=baz $sorted_args als q=foo erzeugen, wobei nur der erste Wert behalten wird. Mit sorted_args_dedupe last würde es q=baz erzeugen.

Anwendungsbeispiele

Grundlegende Normalisierung von Cache-Schlüsseln

Normalisieren Sie Cache-Schlüssel unabhängig von der Parameterreihenfolge:

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

Automatische Überschreibung der Argumente

Automatisch $args mit sortierten Parametern für alle nachgelagerten Prozesse umschreiben:

server {
    listen 80;

    location /api {
        sorted_args_overwrite on;
        sorted_args_ignore_list timestamp _;

        # Alle diese verwenden jetzt automatisch sortierte, gefilterte Argumente
        proxy_pass http://backend;
        # Entspricht: proxy_pass http://backend$uri?$sorted_args;
    }
}

Herausfiltern von Cache-Busting-Parametern

Entfernen Sie Zeitstempel- und Tracking-Parameter aus Cache-Schlüsseln:

location /static {
    sorted_args_ignore_list _ t timestamp v version;

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

Whitelistmodus (nur spezifische Parameter zulassen)

Wenn Query-Parameter zu schwerem serverseitigem Processing führen können, verwenden Sie eine Whitelist, um streng zu kontrollieren, welche Parameter für das Caching zugelassen sind:

location /search {
    # Nur diese Parameter beeinflussen den Cache-Schlüssel; alle anderen werden verworfen
    sorted_args_allow_list q page limit category;

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

In diesem Beispiel werden Anfragen wie /search?q=nginx&page=1&debug=true&nocache=1 mit nur category=&limit=&page=1&q=nginx zwischengespeichert, wobei effektiv alle Cache-busting- oder Debugging-Parameter ignoriert werden.

Kombination von Whitelist und Blockliste

Sie können beide Direktiven zusammen verwenden, um eine feinkörnige Kontrolle zu erhalten. Die Whitelist wird zuerst angewendet, dann die Blockliste:

location /api {
    # Zuerst nur diese Parameter behalten
    sorted_args_allow_list user_id action page limit timestamp;

    # Dann den Zeitstempel aus dem erlaubten Set entfernen
    sorted_args_ignore_list timestamp;

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

Protokollierung normalisierter Querystrings

Einschließlich sortierter Querystrings in den Zugriffsprotokollen:

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

Standortbezogene Filterung

Verschiedene Standorte können unterschiedliche Filterlisten haben:

server {
    # Standard: häufige Tracking-Parameter filtern
    sorted_args_ignore_list _ utm_source utm_medium utm_campaign;

    location /api {
        # API: auch Version und Zeitstempel filtern
        sorted_args_ignore_list _ utm_source utm_medium utm_campaign version t;
        proxy_pass http://api_backend;
    }

    location /content {
        # Inhalt: nur Tracking filtern
        proxy_pass http://content_backend;
    }
}

Vollständiges Beispiel

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;

        # Tracking- und Cache-busting-Parameter filtern
        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;
        }

        # Verwenden Sie sortierte Argumente ohne Filterung
        location / {
            proxy_pass http://localhost:8081;

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

    # Backend-Server zum Testen
    server {
        listen       8081;

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

Wie es funktioniert

  1. Parameterextraktion: Das Modul analysiert den Querystring aus r->args, indem es an & und = splittet
  2. Warteschlangenaufbau: Jeder Parameter wird in einer Warteschlangenstruktur mit seinem Schlüssel, Wert und vollständigem Schlüssel-Wert-Paar gespeichert
  3. Sortierung: Parameter werden mithilfe einer natürlichen Vergleichsfunktion sortiert:
  4. Primäre Sortierung: Parametername (groß-/kleinschreibung-unempfindlich, natürliche Reihenfolge)
  5. Sekundäre Sortierung: vollständiger Parameterstring (key=value, natürliche Reihenfolge)
  6. Natürliche Reihenfolge bedeutet, dass eingebettete Zahlen numerisch verglichen werden: item2 < item10
  7. Entfernen leerer Werte: Parameter mit = aber ohne Wert (wie ?a=) werden entfernt
  8. Whitelist-Filterung: Wenn sorted_args_allow_list konfiguriert ist, werden nur Parameter, die den Mustern entsprechen, behalten
  9. Blocklistenfilterung: Parameter, die Mustern in sorted_args_ignore_list entsprechen, werden ausgeschlossen
  10. Duplikaterkennung: Wenn sorted_args_dedupe aktiviert ist, wird nur das erste oder letzte Vorkommen jedes Schlüssels behalten
  11. Rekonstruktion: Die sortierten, gefilterten Parameter werden mit & verbunden, um den finalen String zu bilden

Tests

Dieses Projekt verwendet Test::Nginx für sein Test-Framework, das in Docker für reproduzierbare Builds läuft.

Voraussetzungen

  • Docker

Tests ausführen

Führen Sie das vollständige Test-Framework aus:

make tests

Führen Sie eine spezifische Testdatei aus:

make tests T=t/sorted_args.t

Deaktivieren Sie den HUP-Modus für Debugging (langsamer, aber isolierter):

make tests HUP=0

Verwenden Sie eine andere Nginx-Version:

make tests NGINX_VERSION=release-1.26.2

Öffnen Sie eine interaktive Shell im Testcontainer für Debugging:

make shell

Testabdeckung

Das Test-Framework überprüft: - ✅ Grundlegende Sortierfunktionalität - ✅ Natürliche/numerische Sortierung (z.B. p=1, p=2, p=10 in der richtigen Reihenfolge) - ✅ Array-ähnliche Parameter (z.B. c[]=1&c[]=2) - ✅ Blocklistenfilterung (sorted_args_ignore_list) - ✅ Whitelistfilterung (sorted_args_allow_list) - ✅ Kombinierte Verwendung von Whitelist und Blockliste - ✅ Wildcard-Muster: Präfix (utm_*), Suffix (*_id), enthält (*token*) - ✅ Duplikaterkennung: sorted_args_dedupe first und last - ✅ Behandlung leerer Querystrings - ✅ Entfernen leerer Werte (?a=&b=2b=2) - ✅ Verwendung von Cache-Schlüsseln - ✅ Standortbezogene Konfigurationsvererbung - ✅ Direktive sorted_args_overwrite - ✅ Groß-/Kleinschreibung-unempfindliche Übereinstimmung von Parametern (sowohl Whitelist als auch Blockliste) - ✅ Parameter ohne Werte vs. leere Werte - ✅ Behandlung doppelter Parameter - ✅ Erhaltung spezieller Zeichen - ✅ Fehlformatierte Query-Strings (aufeinanderfolgende Kaufzeichen) - ✅ Parameter mit mehreren Gleichheitszeichen - ✅ E2E: $args wird vor der Auswertung des Cache-Schlüssels geändert (REWRITE-Phasenzeitpunkt) - ✅ E2E: Umgestellte Parameter erzeugen identische Cache-Schlüssel - ✅ E2E: Rewrite-Direktiven sehen überschriebenes $args

Leistungsüberlegungen

  • Der sortierte Querystring wird einmal pro Anfrage berechnet und im Anfragekontext zwischengespeichert
  • Die Sortierung verwendet Nginx's effizienten warteschlangenbasierten Algorithmus
  • Die Filterung verwendet eine groß-/kleinschreibung-unempfindliche Zeichenfolgenvergleich
  • Die Speicherzuweisung erfolgt aus dem Anfragepool, sodass keine explizite Bereinigung erforderlich ist

Einschränkungen

  • Parameterwerte werden nicht dekodiert/kodiert; die ursprüngliche Kodierung bleibt erhalten
  • Die Filterung ist groß-/kleinschreibung-unempfindlich für Parameternamen, bewahrt jedoch die ursprüngliche Groß-/Kleinschreibung im Output
  • Parameter mit leeren Werten (z.B. ?a=) werden immer entfernt; verwenden Sie ?a (kein Gleichheitszeichen) für Flags