Problem

Ihr nutzt NGINX als Application Server, Load Balancer, etc. aber die Möglichkeiten der normalen Konfiguration reichen nicht aus? Beispielsweise wollt ihr durch den accept-language-Header eine Weiterleitung auf eine sprachspezifische URL vornehmen?

Lösung

NGINX hat ein Modul, welches es erlaubt, ein Subset von JavaScript (NJS) zu nutzen, um Anfragen zu verarbeiten. Dabei wird eine eigene Engine genutzt, da V8 & Co nicht schnell genug sind. Der NJS-Code wird dabei zu Bytecode gewandelt, was die Ausführung sehr schnell macht (Das Beispiel "accept-language"-Weiterleitung habe ich im Netzwerktab mit 0ms gemessen).

Beispiel

Da die offizielle Doku leider unvollständig oder veraltet ist, hier kurz die wichtigsten Punkte in Form eines Docker Setups:

Zuerst braucht es eine JavaScript-Datei. Da es sich bei NJS um ein Subset von JS handelt, muss man teilweise mit älteren JS Konstrukten arbeiten (alte for loop, kein const/let, etc.). Fat Arrow Functions funktionieren lustigerweise jedoch. Also einfach mal ausprobieren, was geht!
nginxLib.js

function hello(r) {
    r.return(200, "Hello world!");
}
 
export default { hello };
Als nächstes muss die nginx.conf diese Datei laden und an einer Location ausführen:
default.conf

js_import /etc/nginx/conf.d/nginxLib.js;
 
server {
    # ...
    location = / {
        js_content nginxLib.hello;
    }
    # ...
}

Im Dockerfile kopiert man diese Dateien und ergänzt zusätzlich die root nginx.conf um ein load_module Statement.

Dockerfile

FROM nginx:1.21.1-alpine
 
# ...
COPY ./default.conf /etc/nginx/conf.d/default.conf
COPY ./nginxLib.js /etc/nginx/conf.d/nginxLib.js
 
# Load njs module for nginx by inserting a line at the top of the root nginx.conf
RUN echo -e "load_module modules/ngx_http_js_module.so;\n$(cat /etc/nginx/nginx.conf)" > /etc/nginx/nginx.conf
# ...

Das load_module Statement muss leider in die root nginx.conf, da die Konfiguration hierarchisch aufgebaut ist (z. B. global - http - server). Da die root nginx.conf im Bereich http unsere default.conf importiert, sind all unsere Statements auch im Bereich http. Das load_module Statement muss jedoch im globalen Bereich definiert werden.

Extending-NGINX-with-JavaScript-NJS-Visual

Weiterführende Aspekte

---

Autor: Santo Pfingsten / Senior Software Architect / Standort Leipzig

SCHREIB UNS

* Pflichtfeld

SCHREIB UNS

* Pflichtfeld

Cookie-Einstellungen

Diese Website verwendet Cookies, um Inhalte und Anzeigen zu personalisieren, Funktionen für soziale Medien anbieten zu können und Zugriffe auf die Website zu analysieren. Zudem werden Informationen zu Ihrer Verwendung der Website an Partner für soziale Medien, Werbung und Analysen weitergegeben. Die Partner führen diese Informationen möglicherweise mit weiteren Daten zusammen, die Sie ihnen bereitgestellt haben oder die sie im Rahmen Ihrer Nutzung der Dienste gesammelt haben.

Weitere Informationen finden Sie in unserer Datenschutzerklärung. Dort können Sie nachträglich auch Ihre Cookie-Einstellungen ändern.

contact icon

Kontakt aufnehmen