nginx njs : installer le module, configurer js_set et appliquer un reload pour créer des variables JavaScript

nginx njs est un module officiel de nginx qui traite les requêtes ou crée des valeurs de variables avec des fonctions JavaScript dans la configuration de nginx. Sur un serveur en configuration Nginx + Apache, pour harmoniser la casse des URL de requête, que la configuration de nginx seule ne peut pas modifier, le module njs a été installé dans la même version que le nginx en place, puis une variable créée avec js_set a été placée dans le chemin du fichier de cache et appliquée par un reload, sans redémarrage.
La fonction d'exemple tient en une ligne et met en minuscules l'encodage pourcentage des URL en coréen ; créer des variables en lisant les en-têtes ou les arguments de l'objet requête fonctionne de la même façon.
1️⃣ nginx njs, c'est quoi : un module qui étend nginx en JavaScript
njs n'est pas un environnement d'exécution JavaScript autonome comme Node.js : il n'a ni script de démarrage ni boucle d'événements propre, et le code ne s'exécute que lorsque nginx appelle une fonction indiquée dans sa configuration, après quoi le traitement revient à nginx.
Les points où nginx appelle des fonctions JavaScript sont fixés : les phases de traitement des requêtes et réponses HTTP, celles des sessions TCP·UDP, le calcul des valeurs de variables et les minuteurs périodiques. La fonction lit l'URL, les en-têtes et les arguments de l'objet requête que lui passe nginx, puis renvoie le résultat sous forme de réponse ou de valeur de variable.
Côté HTTP, [js_import] charge un fichier de script, [js_set] crée la valeur d'une variable, [js_content] crée le corps de la réponse, et [js_header_filter] et [js_body_filter] modifient les en-têtes et le corps de la réponse. Cette mise en place a utilisé deux directives : [js_import] et [js_set].
Le moteur par défaut du module njs implémente ECMAScript 5.1 (strict mode) plus certaines fonctionnalités d'ECMAScript 6 et suivants. Le traitement de chaînes du niveau des remplacements par expressions régulières et des fonctions fonctionne dans ce cadre.
2️⃣ Quand njs est nécessaire : des valeurs de variables que la configuration de nginx seule ne peut pas changer
L'extension WordPress WP Rocket nomme les dossiers de cache des articles aux URL coréennes en encodage pourcentage minuscule, alors que les navigateurs demandent la même URL encodée en majuscules. Un site WordPress tourne sur ce serveur.
Si nginx construit le chemin du fichier de cache avec l'URL de la requête telle quelle, la casse ne correspond pas, le fichier n'est pas trouvé et la requête passe à Apache et PHP.
La configuration de nginx seule ne permet pas de mettre cette valeur en minuscules. [map] ne fait que choisir une valeur parmi celles définies et ne transforme pas les chaînes, et avant l'installation ni la sortie de [nginx -V] ni le dossier des modules ne contenaient de module perl ou lua.
S'il n'y a que quelques URL à changer, une table de correspondance [map] suffit, mais il faut la refaire et faire un reload à chaque nouvel article. Quand chaque URL doit voir sa propre valeur convertie selon la même règle, une seule fonction [js_set] couvre aussi les nouveaux articles, les étiquettes et les URL de catégories.

Le [perl_set] du module perl peut s'utiliser au même endroit et le dépôt propose un paquet assorti à nginx, mais la documentation officielle de nginx présente le module perl comme expérimental.
3️⃣ Installer nginx njs : dans la même version que le nginx installé
Installer avec le seul nom du paquet semble n'ajouter que njs, mais le njs le plus récent du dépôt exige le nginx le plus récent : nginx est donc mis à jour lui aussi. Lors de la vérification avant installation, la commande sans numéro de version affichait un plan faisant passer nginx de 1.28.0 à 1.30.6.
On commence donc par vérifier la version de nginx installée.
rpm -q nginxnginx-1.28.0-1.el9.ngx.x86_64Le dépôt contient un paquet njs distinct pour chaque version de nginx ; dans le numéro de version, ce qui précède le + est la version de nginx et ce qui suit, celle de njs.
dnf list --showduplicates nginx-module-njs | grep '1.28.0+'nginx-module-njs.x86_64 1:1.28.0+0.9.4-1.el9.ngx @nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.8.10-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.0-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.1-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.2-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.3-1.el9.ngx nginx-stable
nginx-module-njs.x86_64 1:1.28.0+0.9.4-1.el9.ngx nginx-stableSix versions, de 0.8.10 à 0.9.4, vont avec nginx 1.28.0, et la ligne @nginx-stable du haut est celle déjà installée. On installe la plus récente, 0.9.4, en précisant le numéro de version complet.
dnf install nginx-module-njs-1:1.28.0+0.9.4-1.el9.ngxrpm permet de vérifier quelle version de nginx le paquet installé exige.
rpm -q --requires nginx-module-njs | grep nginxnginx-r1.28.0rpm -ql nginx-module-njs | grep -v build-id/usr/bin/njs
/usr/lib64/nginx/modules/ngx_http_js_module-debug.so
/usr/lib64/nginx/modules/ngx_http_js_module.so
/usr/lib64/nginx/modules/ngx_stream_js_module-debug.so
/usr/lib64/nginx/modules/ngx_stream_js_module.so
/usr/share/doc/nginx-module-njs
/usr/share/doc/nginx-module-njs/CHANGES
/usr/share/doc/nginx-module-njs/COPYRIGHTLes fichiers installés sont le module HTTP, le module stream qui gère TCP·UDP, une version de débogage de chacun et l'outil en ligne de commande njs. Cette configuration ne charge qu'un fichier, le module HTTP [ngx_http_js_module.so].
4️⃣ Configurer js_set : du chargement du module au chemin du fichier de cache
Installer le paquet ne suffit pas pour que nginx charge le module : nginx.conf doit contenir une ligne [load_module] tout en haut. Selon la documentation officielle, [load_module] est une directive du contexte main : elle se place donc hors des blocs events et http.
# tout en haut de /etc/nginx/nginx.conf (hors des blocs events et http)
load_module modules/ngx_http_js_module.so;La fonction de conversion se trouve dans un fichier .js distinct des fichiers de configuration, et la configuration de nginx importe la fonction exportée par export default à la dernière ligne.
// /etc/nginx/njs/rocket.js — met seulement l'encodage pourcentage %XX en minuscules
function lc(r) {
return r.variables.request_uri.replace(/%[0-9A-F]{2}/g, function (m) { return m.toLowerCase(); });
}
export default { lc };La fonction lit la variable [request_uri] de l'objet requête r et ne met en minuscules que les deux caractères qui suivent un signe pourcentage lorsqu'ils sont en majuscules, puis renvoie le résultat. Les lettres latines restent telles quelles, si bien que les URL anglaises comportant des majuscules ne changent pas ; c'est la même règle que celle de WP Rocket pour nommer les dossiers de cache.
# dans le bloc http (un fichier .conf de conf.d)
js_import rkt from /etc/nginx/njs/rocket.js;
js_set $rocket_uri rkt.lc;Dans [js_import], rkt est le nom qui sert à appeler les fonctions du module, et [js_set] fait du résultat de cette fonction la variable [$rocket_uri]. Selon la documentation officielle, la fonction s'exécute la première fois que la variable est référencée dans une requête et ne prend en charge que le traitement synchrone.
# bloc server — $request_uri du chemin du fichier de cache devient $rocket_uri
set $rocket_file '/wp-content/cache/wp-rocket/example.com${rocket_uri}index$rocket_mobile-https.html';Seule change cette ligne qui construit le chemin du fichier de cache ; les vérifications qui excluent du cache les cookies de connexion, les paramètres et les requêtes POST restent telles quelles.
5️⃣ Appliquer et vérifier : journal d'erreurs et en-têtes de réponse après le reload
Lancez d'abord le test de configuration, puis faites le reload s'il réussit.
nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulsystemctl reload nginxLa nouvelle ligne [load_module] a été prise en compte par un reload, sans redémarrage. Le journal d'erreurs a enregistré une ligne d'initialisation de la machine virtuelle njs, et il n'y a eu aucune erreur JavaScript.
grep 'js vm init' /var/log/nginx/error.log | head -12026/10/17 18:21:35 [notice] 27992#27992: js vm init njs: 0000559FDF6D0E00Le njs en fin de ligne est le nom du moteur utilisé. La même ligne est aussi consignée lors du test de configuration avec [nginx -t] : recoupez-la avec l'heure du reload.
curl -sI 'https://example.com/-/' | grep -i 'x-rocket\|content-type'content-type: text/html
x-rocket-nginx-serving-file: HITMême pour une URL coréenne encodée en majuscules, l'en-tête indiquant que nginx a servi le fichier de cache était présent. Les requêtes avec paramètres ou cookie de connexion et les requêtes POST passaient toujours à PHP sans cet en-tête après la modification.
6️⃣ Revenir en arrière avec njs et mettre à jour nginx
Pour revenir en arrière, remplacez [$rocket_uri] par [$request_uri] dans le chemin du fichier de cache, retirez le fichier de configuration [js_import]·[js_set] et la ligne [load_module], puis testez la configuration et faites le reload.
# bloc server — retour à la variable d'origine
set $rocket_file '/wp-content/cache/wp-rocket/example.com${request_uri}index$rocket_mobile-https.html';Le paquet peut rester installé : sans la ligne [load_module], nginx ne le charge pas ; ne supprimez le paquet que pour l'enlever complètement.
dnf remove nginx-module-njsLors d'une mise à jour de nginx, le paquet njs doit passer en même temps à la version assortie au nouveau nginx. Avant la mise à jour, vérifiez avec [dnf list --showduplicates] que le dépôt contient le njs correspondant à la nouvelle version de nginx.
🔢 FAQ & contenus recommandés
















ℹ️ Mention d'affiliation
Le contenu de ce site contient des liens d'affiliation. Lorsqu'un visiteur achète un produit ou un service via l'un de ces liens, le site perçoit une commission du vendeur. Le montant payé par l'acheteur(il baisse lors des promotions ↓), lui, n'augmente pas. Les prix, remises et stocks indiqués correspondent à la date de rédaction et peuvent différer ; vérifiez-les donc auprès du vendeur avant d'acheter. Les produits sont choisis et évalués selon nos propres critères, et les commissions n'influencent ni l'ordre de présentation ni le contenu des évaluations.