Redaktion – Der Blogbeitrag mit dem Titel „Einführung in das NGINX JavaScript-Modul“ verweist auf diese Seite. Der Beitrag wurde aktualisiert und enthält nun die Direktiven und Funktionen des NGINX JavaScript-Moduls, die seit April 2021 unterstützt werden.

Das NGINX-JavaScript-Modul (njs) wurde mit NGINX Open Source 1.11.10 und NGINX Plus R12. allgemein als stabiles Modul verfügbar. [Das Modul hieß ursprünglich nginScript; dieser Name findet sich daher in einigen älteren Beiträgen.] Seit der Einführung von NGINX JavaScript im September 2015 haben wir kontinuierlich daran gearbeitet und die im stabilen Modul enthaltenen Funktionen und Sprachunterstützung hinzugefügt.
NGINX JavaScript ist eine einzigartige JavaScript-Implementierung für NGINX und NGINX Plus, die speziell für serverseitige Anwendungsfälle und die Verarbeitung einzelner Anfragen entwickelt wurde. Sie erweitert die NGINX-Konfigurationssyntax um JavaScript-Code und ermöglicht so die Umsetzung anspruchsvoller Konfigurationslösungen.
Die Einsatzmöglichkeiten sind vielfältig, insbesondere da das NGINX JavaScript-Modul sowohl für HTTP- als auch für TCP/UDP-Protokolle verfügbar ist. Beispiele für den Einsatz von NGINX JavaScript sind:
- Generieren benutzerdefinierter Protokollformate mit Werten, die über reguläre NGINX-Variablen nicht verfügbar sind (zum Beispiel Diagnoseprotokollierung)
- Ändern von Antworten von Proxy-Servern (Antwortfilterung)
- Implementierung benutzerdefinierter Authentifizierungsschemata (zum Beispiel OAuth 2.0-Token-Introspektion)
- Parsen von TCP-/UDP-Protokollen für Sticky Sessions auf Anwendungsebene (zum Beispiel MQTT-Lastverteilung)
Bevor wir NGINX JavaScript näher erläutern, wollen wir zunächst zwei weitverbreitete Missverständnisse ausräumen.
NGINX JavaScript ist nicht Lua
Die NGINX-Community hat im Laufe der Jahre mehrere programmierbare Erweiterungen entwickelt. Zum Zeitpunkt der Erstellung dieses Artikels ist Lua die beliebteste davon. Es ist als Modul für NGINX sowie als unterstütztes, vorkompiliertes dynamisches Drittanbietermodul für NGINX Plus verfügbar. Das Lua-Modul und die Zusatzbibliotheken bieten eine tiefgreifende Integration in den NGINX-Kern sowie einen umfangreichen Funktionsumfang, darunter einen Treiber für Redis.
Lua ist eine leistungsstarke Skriptsprache. Allerdings ist sie nach wie vor relativ wenig verbreitet und gehört üblicherweise nicht zum Kompetenzrepertoire von Frontend-Entwicklern oder DevOps-Ingenieuren.
NGINX JavaScript soll Lua nicht ersetzen, und es wird noch einige Zeit dauern, bis NGINX JavaScript einen vergleichbaren Funktionsumfang bietet. Ziel von NGINX JavaScript ist es, durch den Einsatz einer weitverbreiteten Programmiersprache einer möglichst großen Community Lösungen für die programmatische Konfiguration bereitzustellen.
NGINX JavaScript ist nicht Node.js
NGINX JavaScript zielt nicht darauf ab, NGINX oder NGINX Plus in einen Anwendungsserver zu verwandeln. Vereinfacht gesagt ähneln die Anwendungsfälle für NGINX JavaScript denen von Middleware, da der JavaScript-Code zwischen dem Client und dem Inhalt ausgeführt wird. Technisch gesehen haben Node.js und die Kombination aus NGINX JavaScript und NGINX oder NGINX Plus nur zwei Dinge gemeinsam – eine ereignisgesteuerte Architektur und die Programmiersprache JavaScript – darüber hinaus enden die Gemeinsamkeiten.
Node.js verwendet die Google-V8-JavaScript-Engine, während NGINX JavaScript eine speziell für NGINX und NGINX Plus entwickelte Implementierung der ECMAScript-Standards ist. Node.js hält eine persistente virtuelle JavaScript-Maschine (VM) im Arbeitsspeicher vor und führt zur Speicherverwaltung regelmäßig eine Garbage Collection durch. NGINX JavaScript hingegen initialisiert für jede Anfrage eine neue JavaScript-VM sowie den erforderlichen Arbeitsspeicher und gibt diesen nach Abschluss der Anfrage wieder frei.
JavaScript als serverseitige Sprache
Wie bereits erwähnt, ist NGINX JavaScript eine speziell entwickelte Implementierung der Programmiersprache JavaScript. Alle anderen vorhandenen JavaScript-Laufzeitumgebungen sind für die Ausführung in einem Webbrowser konzipiert. Die Ausführung von clientseitigem Code unterscheidet sich in vielerlei Hinsicht von der Ausführung von serverseitigem Code – von der Verfügbarkeit von Systemressourcen bis hin zur möglichen Anzahl gleichzeitig ausgeführter Laufzeitinstanzen.
Wir haben uns entschieden, eine eigene JavaScript-Laufzeitumgebung zu implementieren, um die Anforderungen an die serverseitige Codeausführung zu erfüllen und sie nahtlos in die Architektur von NGINX zur Verarbeitung von Anfragen zu integrieren. Unsere Designprinzipien für NGINX JavaScript lauten:
- Die Laufzeitumgebung wird mit der Anfrage erstellt und anschließend wieder beendetDas NGINX JavaScript-Modul führt Bytecode in einem einzelnen Thread aus und ist auf eine schnelle Initialisierung und Freigabe ausgelegt. Die Laufzeitumgebung wird für jede Anfrage neu initialisiert. Der Start erfolgt äußerst schnell, da weder ein komplexer Zustand noch Hilfsfunktionen initialisiert werden müssen. Während der Ausführung wird Speicher in Pools gesammelt und nach Abschluss durch Freigabe der Pools wieder freigegeben. Dank dieses Speicherverwaltungsschemas müssen einzelne Objekte weder nachverfolgt noch freigegeben werden, und auch eine automatische Speicherbereinigung ist nicht erforderlich.
- Nicht blockierende CodeausführungDas ereignisgesteuerte Modell von NGINX und NGINX Plus plant die Ausführung der einzelnen NGINX JavaScript-Laufzeitumgebungen. Wenn eine NGINX JavaScript-Regel einen blockierenden Vorgang ausführt (z. B. Netzwerkdaten liest oder eine externe Unteranfrage sendet), unterbrechen NGINX und NGINX Plus transparent die Ausführung der zugehörigen NGINX JavaScript-VM und planen sie nach Abschluss des Ereignisses erneut ein. Das bedeutet, dass Sie Regeln auf einfache, lineare Weise schreiben können und NGINX und NGINX Plus deren Ausführung ohne interne Blockierung planen.
- Nur die Sprachfunktionen implementieren, die wir benötigenDie Spezifikationen für JavaScript werden durch die ECMAScript-Standards definiert. NGINX JavaScript folgt ECMAScript 5.1 mit einigen Funktionen aus ECMAScript 6 für mathematische Berechnungen. Durch die Implementierung einer eigenen JavaScript-Laufzeitumgebung können wir Sprachfunktionen für serverseitige Anwendungsfälle priorisieren und nicht benötigte Funktionen außer Acht lassen. Wir führen eine Liste der derzeit unterstützten Sprachelemente.
- Enge Integration in die Phasen der AnforderungsverarbeitungNGINX und NGINX Plus verarbeiten Anforderungen in verschiedenen Phasen. Konfigurationsanweisungen werden in der Regel in einer bestimmten Phase ausgeführt, und native NGINX-Module nutzen häufig die Möglichkeit, eine Anforderung in einer bestimmten Phase zu prüfen oder zu ändern. NGINX JavaScript macht einige der Verarbeitungsphasen über Konfigurationsanweisungen zugänglich, sodass sich steuern lässt, wann der JavaScript-Code ausgeführt wird. Diese Integration in die Konfigurationssyntax verbindet die Leistungsfähigkeit und Flexibilität nativer NGINX-Module mit der Einfachheit von JavaScript-Code. Die folgende Tabelle zeigt, welche Verarbeitungsphasen zum Zeitpunkt der Erstellung über NGINX JavaScript zugänglich sind und welche Konfigurationsanweisungen den Zugriff darauf ermöglichen.
| Verarbeitungsphase | HTTP-Modul | Stream-Modul |
|---|---|---|
Access – Authentifizierung und Zugriffskontrolle | auth_request und js_content | js_access |
Pre-read – Nutzdaten lesen/schreiben | k. A. | js_preread |
Filter – Antwort während des Proxy-Vorgangs lesen/schreiben | js_body_filterjs_header_filter | js_filter |
Content – Antwort an den Client senden | js_content | k. A. |
Log / Variables – Bei Bedarf ausgewertet | js_set | js_set |
Erste Schritte mit NGINX JavaScript – ein praxisnahes Beispiel
NGINX JavaScript ist als Modul implementiert, das Sie in eine NGINX Open Source-Binärdatei kompilieren oder dynamisch in NGINX bzw. NGINX Plus laden können. Anleitung zum Aktivieren von NGINX JavaScript mit NGINX und NGINX Plus finden Sie am Ende dieses Artikels.
In diesem Beispiel verwenden wir NGINX oder NGINX Plus als einfachen Reverse-Proxy und erstellen mit NGINX JavaScript Zugriffsprotokolleinträge in einem speziellen Format, das:
- Enthält die vom Client gesendeten Anfrage-Header
- Enthält die vom Backend zurückgegebenen Antwort-Header
- Verwendet Schlüssel-Wert-Paare für die effiziente Aufnahme in und Suche mit Protokollverarbeitungstools wie dem ELK Stack (jetzt Elastic Stack genannt), Graylog und Splunk
Die NGINX-Konfiguration für dieses Beispiel ist äußerst einfach.
Codebeispiel wird geladen…
Wie Sie sehen, ist der NGINX-JavaScript-Code nicht direkt in die Konfigurationssyntax eingebettet. Stattdessen verwenden wir die js_import-Direktive, um die Datei anzugeben, die unseren gesamten JavaScript-Code enthält. Die js_set-Direktive definiert eine neue NGINX-Variable, $access_log_headers, sowie die JavaScript-Funktion, die sie mit einem Wert befüllt. Die log_format-Direktive definiert ein neues Format namens kvpairs, das jede Protokollzeile mit dem Wert von $access_log_headers schreibt.
Der server-Block definiert einen einfachen HTTP-Reverse-Proxy, der alle Anfragen an https://www.example.com weiterleitet. Die access_log-Direktive legt fest, dass alle Anfragen im kvpairs-Format protokolliert werden.
Sehen wir uns nun den JavaScript-Code an, der einen Protokolleintrag vorbereitet.
Codebeispiel wird geladen…
Der Rückgabewert der Funktion kvAccess – ein Protokolleintrag – wird an die Konfigurationsanweisung js_set in rawheader_logging.conf übergeben. Beachten Sie, dass NGINX-Variablen bei Bedarf ausgewertet werden. Das bedeutet wiederum, dass die durch js_set definierte JavaScript-Funktion ausgeführt wird, sobald der Wert der Variablen benötigt wird. In diesem Beispiel wird $access_log_headers in der Anweisung log_format verwendet, sodass kvAccess() zum Zeitpunkt der Protokollierung ausgeführt wird. Variablen, die als Teil von map- oder rewrite-Anweisungen verwendet werden (in diesem Beispiel nicht dargestellt), lösen die entsprechende JavaScript-Ausführung in einer früheren Verarbeitungsphase aus.
Wir können diese durch NGINX JavaScript erweiterte Protokollierungslösung in Aktion sehen, indem wir eine Anfrage über unseren Reverse-Proxy leiten und den daraus resultierenden Protokolldateieintrag betrachten. Dieser enthält Anfrage-Header mit dem Präfix „in.“ und Antwort-Header mit dem Präfix „out.“.
$ curl http://127.0.0.1/$ tail --lines=1 /var/log/nginx/access_headers.log2021-04-23T10:08:15+00:00 client=172.17.0.1 method=GET uri=/index.html status=200 in.Host=localhost:55081 in.User-Agent=curl/7.64.1 in.Accept=*/* out.Content-Type=text/html out.Content-Length=612 out.ETag=x22606339ef-264x22 out.Accept-Ranges=bytesEin Großteil des Nutzens von NGINX JavaScript ergibt sich aus dem Zugriff auf interne Funktionen von NGINX. In diesem Beispiel werden mehrere Eigenschaften des Anfrageobjekts (r) verwendet. Das NGINX JavaScript-Stream-Modul (für TCP- und UDP-Anwendungen) verwendet ein Sitzungsobjekt (s) mit eigenen Eigenschaften. Weitere Beispiele für NGINX JavaScript-Lösungen für HTTP und TCP/UDP finden Sie unter Anwendungsfälle für das NGINX JavaScript-Modul.
Wir würden gerne erfahren, welche Anwendungsfälle Sie für NGINX JavaScript entwickeln – berichten Sie uns davon im Kommentarbereich unten.
Anwendungsfälle für das NGINX-JavaScript-Modul
In diesen Blogbeiträgen erfahren Sie mehr über weitere HTTP- und TCP/UDP-Anwendungsfälle für das NGINX JavaScript-Modul:
- Deklarieren von JavaScript-Code und Variablen in lokalen Kontexten in „Gestalten Sie Ihre NGINX-Konfiguration mit njs 0.7.7 noch modularer und wiederverwendbarer“
- NGINX als DoT- oder DoH-Gateway verwenden
- Ankündigung von NGINX Plus R26 – Verwendung asynchroner Funktionen; Verwendung der WebCrypto API zur Erzeugung sicherer Zufallszahlen und zum Hashen von Textzeichenfolgen
- Behebung der log4j-Sicherheitslücke mit NGINX
- Erweiterte Protokollierung mit dem NGINX-JavaScript-Modul in „MySQL-Skalierung mit TCP-Lastverteilung und Galera Cluster“
- Ankündigung von NGINX Plus R24 – Antwortfilterung für Body und Header; Verwendung eines eingebetteten HTTP-Clients zur Authentifizierung von TCP-/UDP-Verbindungen
- Validieren von Anfragetexten in „NGINX Plus als API-Gateway bereitstellen, Teil 2: Backend-Dienste schützen“
- Diagnoseprotokollierung mit dem NGINX-JavaScript-Modul<.htmla>
- Ankündigung von NGINX Plus R22 – Protokollierung des genauen Satzes von Headern, die vom Client gesendet wurden, sobald ein Fehler auftritt
- Ankündigung von NGINX Plus R21 – Verketten von Unteranfragen in einer einzigen Codesequenz ohne Callbacks; Senden einer Kopie der Anfrage-Header an ein SIEM-System (Security Information and Event Management)
- Nur ein POST: Deklaratives DNS mit F5 und dem NGINX-JavaScript-Modul ermöglichen
- Erweiterung von
auth_requestmit dem NGINX-JavaScript-Modul in „Validierung von OAuth-2.0-Zugriffstoken mit NGINX und NGINX Plus“ - Over-the-Air-Updates für IoT-Geräte mit NGINX
- Ankündigung von NGINX Plus R18 – Protokollierung einer gehashten (maskierten) Version der Client-IP-Adresse anstelle der tatsächlichen Adresse
- Virtuelles Patching mit dem NGINX-JavaScript-Modul
- Bündeln von API-Anfragen mit NGINX Plus und dem NGINX-JavaScript-Modul
- Ankündigung von NGINX Plus R15 – Gleichzeitiges Senden einer HTTP-Anfrage an zwei verschiedene Backends, anschließendes Weiterleiten der ersten Antwort und Ignorieren der zweiten; Hinzufügen von Datenintegrität zu Anwendungscookies
- Skalieren der Änderungserkennung mit JavaScript-Hashing in „Erkennen von Manipulationen an der Startseite mit aktiven Integritätsprüfungen“
- Erweiterung des TCP.htmlUDP-Load-Balancings mit nginScript in „TCP/UDP-Load-Balancing mit NGINX: Überblick, Tipps und Tricks“
- Verwenden von Clientzertifikaten zur Authentifizierung von MQTT-Clients in „NGINX Plus für das IoT: Verschlüsselung und Authentifizierung von MQTT-Datenverkehr“
- MQTT-Lastverteilung für Sitzungspersistenz mit dem NGINX-JavaScript-Modul in „NGINX Plus für das IoT: MQTT-Lastverteilung“
- Datenmaskierung zum Schutz der Privatsphäre von Benutzern mit dem NGINX JavaScript-Modul
- Ankündigung von NGINX Plus R11 – Suche nach Schlüsselmustern in einer Nachricht innerhalb eines MySQL-Protokollstreams zur Identifizierung der SQL-Operation
- Verwendung des NGINX-JavaScript-Moduls zur schrittweisen Umstellung von Clients auf einen neuen Server
[ngx_snippet name=’njs-enable-instructions’]
Über den Autor

Ähnliche Blogbeiträge
Die Zukunft von NGINX: Zurück zu unseren Open-Source-Wurzeln
Beim NGINX Sprint 2022 besinnen wir uns auf unsere Open-Source-Wurzeln. Erfahren Sie mehr über die Initiativen, die wir im kommenden Jahr verfolgen, und teilen Sie uns mit, was Sie sich wünschen.

Ein Leitfaden zur Auswahl eines Ingress-Controllers, Teil 1: Ermitteln Sie Ihre Anforderungen
Ein Ingress-Controller kann eines der leistungsstärksten Tools in Ihrem Kubernetes-Stack sein. Erfahren Sie, wie Sie Ihre Ingress-Anforderungen ermitteln, um die beste Option auszuwählen.
Bereitstellung des NGINX Ingress Controllers auf Amazon EKS: So haben wir getestet
Wir haben kürzlich den Lösungsleitfaden zum NGINX Ingress Controller um Empfehlungen zur Dimensionierung für Amazon Elastic Kubernetes Service (EKS) ergänzt. In diesem Blogbeitrag erläutern wir, wie wir diese Empfehlungen erarbeitet haben, und stellen Ihnen alle Informationen zur Verfügung, die Sie benötigen, um selbst ähnliche Tests durchzuführen.

Protokollierung des Datenverkehrs zwischen NGINX und Upstream-Servern bei CDN77
Bei der Fehlersuche bei Datenverkehrsproblemen zwischen NGINX und Upstream-Servern konnte CDN77 die benötigten Daten nur aus dem Fehlerprotokoll mit aktivierter Debug-Ausgabe beziehen, was die Leistung beeinträchtigt und riesige Dateien erzeugt. Daher entwickelte das Team ein neues benutzerdefiniertes Modul, das ausschließlich die benötigten Daten protokolliert.
Ankündigung von NGINX Plus R16
NGINX Plus R16 ist eine einheitliche, elastische Ingress- und Egress-Schicht für Anwendungen, die die Funktionen eines Load Balancers, API-Gateways und einer WAF vereint und neue Features wie clusterfähige Ratenbegrenzung, Schlüssel-Wert-Speicher, „Random with Two Choices“, verbessertes UDP-Load-Balancing und vieles mehr bietet.
5 Gründe für den Umstieg auf softwarebasiertes Load Balancing
Entdecken Sie fünf Gründe für den Wechsel zu einem softwarebasierten Load Balancer wie NGINX Plus, darunter Kosteneinsparungen, die Einführung von DevOps und eine einheitliche Lösung für alle Umgebungen.