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.
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,*_idfü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×tamp=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×tamp=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×tamp=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 behaltenlast— nur das letzte Vorkommen jedes Schlüssels behaltenoff— 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
- Parameterextraktion: Das Modul analysiert den Querystring aus
r->args, indem es an&und=splittet - Warteschlangenaufbau: Jeder Parameter wird in einer Warteschlangenstruktur mit seinem Schlüssel, Wert und vollständigem Schlüssel-Wert-Paar gespeichert
- Sortierung: Parameter werden mithilfe einer natürlichen Vergleichsfunktion sortiert:
- Primäre Sortierung: Parametername (groß-/kleinschreibung-unempfindlich, natürliche Reihenfolge)
- Sekundäre Sortierung: vollständiger Parameterstring (key=value, natürliche Reihenfolge)
- Natürliche Reihenfolge bedeutet, dass eingebettete Zahlen numerisch verglichen werden:
item2<item10 - Entfernen leerer Werte: Parameter mit
=aber ohne Wert (wie?a=) werden entfernt - Whitelist-Filterung: Wenn
sorted_args_allow_listkonfiguriert ist, werden nur Parameter, die den Mustern entsprechen, behalten - Blocklistenfilterung: Parameter, die Mustern in
sorted_args_ignore_listentsprechen, werden ausgeschlossen - Duplikaterkennung: Wenn
sorted_args_dedupeaktiviert ist, wird nur das erste oder letzte Vorkommen jedes Schlüssels behalten - 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=2 → b=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