Exploitez la puissance et la simplicité de JavaScript pour chaque requête grâce au module JavaScript de NGINX

NGINX | 23 avril 2021

Note de la rédaction – L’article de blog intitulé « Introduction au module JavaScript de NGINX » redirige vers cette page. Cet article a été mis à jour pour inclure les directives et fonctionnalités du module JavaScript de NGINX prises en charge en avril 2021.

Le module JavaScript NGINX (njs) est devenu disponible pour tous en tant que module stable dans NGINX Open Source 1.11.10 et NGINX Plus R12. [À l’origine, le module s’appelait nginScript, et ce nom apparaît dans certains articles plus anciens.] Nous travaillons sans relâche sur NGINX JavaScript depuis son lancement en septembre 2015, en ajoutant les fonctionnalités et la prise en charge du langage incluses dans le module stable.

NGINX JavaScript est une implémentation unique de JavaScript pour NGINX et NGINX Plus, spécialement conçue pour les cas d’usage côté serveur et le traitement de chaque requête. Elle étend la syntaxe de configuration de NGINX avec du code JavaScript afin de mettre en œuvre des solutions de configuration sophistiquées.

Les cas d’utilisation sont nombreux, d’autant plus que le module NGINX JavaScript est disponible pour les protocoles HTTP et TCP/UDP. Voici quelques exemples de cas d’utilisation de NGINX JavaScript :

Avant d’aborder NGINX JavaScript plus en détail, commençons par clarifier deux idées reçues courantes.

NGINX JavaScript n’est pas Lua

Au fil des ans, la communauté NGINX a créé plusieurs extensions programmatiques. À l’heure où nous écrivons ces lignes, Lua est la plus populaire d’entre elles. Elle est disponible sous la forme d’un module pour NGINX et d’un module dynamique tiers précompilé et pris en charge pour NGINX Plus. Le module Lua et les bibliothèques complémentaires offrent une intégration étroite avec le cœur de NGINX ainsi qu’un riche éventail de fonctionnalités, notamment un pilote pour Redis.

Lua est un langage de script puissant. Son adoption reste toutefois assez limitée et il ne fait généralement pas partie de la « boîte à outils de compétences » des développeurs frontend ou des ingénieurs DevOps.

NGINX JavaScript ne vise pas à remplacer Lua, et il faudra encore du temps avant qu’il n’offre un niveau de fonctionnalités comparable. L’objectif de NGINX JavaScript est de proposer des solutions de configuration programmatique au plus grand nombre grâce à l’utilisation d’un langage de programmation populaire.

NGINX JavaScript n’est pas Node.js

NGINX JavaScript n’a pas vocation à transformer NGINX ou NGINX Plus en serveur d’applications. En termes simples, les cas d’utilisation de NGINX JavaScript s’apparentent à ceux d’un middleware, car l’exécution du code JavaScript intervient entre le client et le contenu. D’un point de vue technique, bien que Node.js ait deux points communs avec l’association de NGINX JavaScript et de NGINX ou NGINX Plus : une architecture événementielle et le langage de programmation JavaScript, les similitudes s’arrêtent là.

Node.js utilise le moteur JavaScript V8 de Google, tandis que NGINX JavaScript est une implémentation sur mesure des normes ECMAScript, conçue spécifiquement pour NGINX et NGINX Plus. Node.js conserve en mémoire une machine virtuelle JavaScript (VM) persistante et effectue régulièrement un ramasse-miettes pour gérer la mémoire, tandis que NGINX JavaScript initialise une nouvelle VM JavaScript et alloue la mémoire nécessaire pour chaque requête, puis libère cette mémoire une fois la requête traitée.

JavaScript en tant que langage côté serveur

Comme indiqué précédemment, NGINX JavaScript est une implémentation sur mesure du langage JavaScript. Tous les autres moteurs d’exécution JavaScript existants sont conçus pour fonctionner dans un navigateur web. La nature de l’exécution du code côté client diffère de celle du code côté serveur à bien des égards, qu’il s’agisse de la disponibilité des ressources système ou du nombre potentiel d’environnements d’exécution simultanés.

Nous avons décidé de développer notre propre environnement d’exécution JavaScript afin de répondre aux exigences de l’exécution de code côté serveur et de l’intégrer harmonieusement à l’architecture de traitement des requêtes de NGINX. Les principes de conception de NGINX JavaScript sont les suivants :

  • L’environnement d’exécution naît et disparaît avec la requêteLe module NGINX JavaScript exécute le bytecode dans un seul thread afin de permettre une initialisation et une libération rapides. L’environnement d’exécution est initialisé pour chaque requête. Le démarrage est extrêmement rapide, car aucun état complexe ni aucun utilitaire ne doit être initialisé. Pendant l’exécution, la mémoire est allouée dans des pools, puis libérée à la fin en supprimant ces pools. Ce mode de gestion de la mémoire évite d’avoir à suivre et à libérer chaque objet individuellement ou à utiliser un ramasse-miettes.
  • Exécution de code non bloquanteLe modèle événementiel de NGINX et NGINX Plus planifie l’exécution de chaque environnement d’exécution NGINX JavaScript. Lorsqu’une règle NGINX JavaScript effectue une opération bloquante (telle que la lecture de données réseau ou l’émission d’une sous-requête externe), NGINX et NGINX Plus suspendent de manière transparente l’exécution de la machine virtuelle NGINX JavaScript associée et la replanifient une fois l’événement terminé. Vous pouvez ainsi écrire des règles de manière simple et linéaire, tandis que NGINX et NGINX Plus planifient leur exécution sans blocage interne.
  • Implémentation limitée aux fonctionnalités du langage dont nous avons besoinLes spécifications de JavaScript sont définies par les normes ECMAScript. NGINX JavaScript est conforme à ECMAScript 5.1 et intègre certaines fonctionnalités d’ECMAScript 6 pour les fonctions mathématiques. Le fait d’implémenter notre propre environnement d’exécution JavaScript nous permet de donner la priorité aux fonctionnalités du langage adaptées aux cas d’utilisation côté serveur et d’ignorer celles dont nous n’avons pas besoin. Nous tenons à jour une liste des éléments du langage actuellement pris en charge.
  • Intégration étroite avec les phases de traitement des requêtesNGINX et NGINX Plus traitent les requêtes en plusieurs phases distinctes. Les directives de configuration interviennent généralement lors d’une phase précise, et les modules NGINX natifs tirent souvent parti de la possibilité d’examiner ou de modifier une requête à une phase donnée. NGINX JavaScript expose certaines phases de traitement au moyen de directives de configuration, ce qui permet de contrôler le moment où le code JavaScript est exécuté. Cette intégration à la syntaxe de configuration allie la puissance et la flexibilité des modules NGINX natifs à la simplicité du code JavaScript. Le tableau ci-dessous indique les phases de traitement accessibles via NGINX JavaScript au moment de la rédaction, ainsi que les directives de configuration correspondantes.
Phase de traitementModule HTTPModule Stream
Accès – Authentification et contrôle d’accèsauth_request et js_contentjs_access
Prélecture – Lecture/écriture de la charge utileN/Ajs_preread
Filtrage – Lecture/écriture de la réponse lors du traitement par le proxyjs_body_filter
js_header_filter
js_filter
Contenu – Envoi de la réponse au clientjs_contentN/A
Journalisation / Variables – Évaluation à la demandejs_setjs_set

Bien démarrer avec NGINX JavaScript : un exemple concret

NGINX JavaScript est implémenté sous la forme d’un module que vous pouvez compiler dans un binaire NGINX Open Source ou charger dynamiquement dans NGINX ou NGINX Plus. Instructions pour activer NGINX JavaScript avec NGINX et NGINX Plus figurent à la fin de cet article.

Dans cet exemple, nous utilisons NGINX ou NGINX Plus comme simple proxy inverse et NGINX JavaScript pour créer des entrées de journal d’accès dans un format spécialisé qui :

  • Inclut les en-têtes de requête envoyés par le client
  • Inclut les en-têtes de réponse renvoyés par le backend
  • Utilise des paires clé-valeur pour une ingestion et une recherche efficaces avec des outils de traitement des journaux tels que la pile ELK (désormais appelée Elastic Stack), Graylog et Splunk

La configuration de NGINX pour cet exemple est extrêmement simple.

Chargement de l’exemple de code…

Comme vous pouvez le constater, le code JavaScript NGINX n’est pas intégré directement à la syntaxe de configuration. Nous utilisons plutôt la directive js_import pour spécifier le fichier qui contient l’ensemble de notre code JavaScript. La directive js_set définit une nouvelle variable NGINX, $access_log_headers, ainsi que la fonction JavaScript qui lui attribue une valeur. La directive log_format définit un nouveau format appelé kvpairs, qui écrit chaque ligne du journal avec la valeur de $access_log_headers.

Le bloc server définit un simple proxy inverse HTTP qui transmet toutes les requêtes à https://www.example.com. La directive access_log indique que toutes les requêtes seront journalisées au format kvpairs.

Examinons maintenant le code JavaScript qui prépare une entrée de journal.

Chargement de l’exemple de code…

La valeur renvoyée par la fonction kvAccess — une entrée de journal — est transmise à la directive de configuration js_set dans rawheader_logging.conf. Gardez à l’esprit que les variables NGINX sont évaluées à la demande, ce qui signifie que la fonction JavaScript définie par js_set est exécutée lorsque la valeur de la variable est requise. Dans cet exemple, $access_log_headers est utilisée dans la directive log_format, de sorte que kvAccess() est exécutée au moment de la journalisation. Les variables utilisées dans les directives map ou rewrite (non illustrées dans cet exemple) déclenchent l’exécution du code JavaScript correspondant à une phase antérieure du traitement.

Nous pouvons voir cette solution de journalisation NGINX enrichie par JavaScript à l’œuvre en faisant transiter une requête par notre proxy inverse et en observant l’entrée correspondante dans le fichier journal, qui inclut les en-têtes de requête avec le préfixe « in. » et les en-têtes de réponse avec le préfixe « 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=bytes

L’utilité de NGINX JavaScript tient en grande partie à son accès aux mécanismes internes de NGINX. Cet exemple utilise plusieurs propriétés de l’objet de requête (r). Le module Stream de NGINX JavaScript (pour les applications TCP et UDP) utilise un objet de session (s) doté de son propre ensemble de propriétés. Pour découvrir d’autres exemples de solutions NGINX JavaScript pour HTTP et TCP/UDP, consultez Cas d’utilisation du module NGINX JavaScript.

Nous serions ravis de découvrir les cas d’usage que vous imaginez pour NGINX JavaScript. N’hésitez pas à nous en faire part dans la section des commentaires ci-dessous.

Cas d’utilisation du module JavaScript NGINX

Consultez ces articles de blog pour découvrir d’autres cas d’utilisation HTTP et TCP/UDP du module JavaScript NGINX :

[ngx_snippet name=’njs-enable-instructions’]


Partager
Mots-clés : F5 NGINX, 2021, Tech

À propos de l’auteur

Liam Crilly
Liam CrillyDirecteur senior de la gestion des produits

Autres articles de Liam Crilly

Articles de blog associés

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA
NGINX | 13/10/2025

Tendances actuelles des technologies cloud natives, de l’ingénierie de plateforme et de l’IA

Découvrez les principaux enseignements tirés des réponses à l’enquête annuelle F5 NGINX sur les dernières tendances en matière de technologies cloud natives, de sécurité, d’ingénierie de plateforme et d’IA.

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?
NGINX | 03/11/2023

Quels contrôleurs Ingress NGINX sont affectés par les vulnérabilités CVE-2022-4886, CVE-2023-5043 et CVE-2023-5044 ?

Lorsque de nouvelles CVE sont signalées, il est facile de ne plus savoir si elles concernent un outil de contrôleur Ingress NGINX particulier, car il existe plusieurs projets. Cet article présente les CVE et explique comment distinguer les différents projets de contrôleurs Ingress afin de dissiper toute confusion.

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX
NGINX | 11/03/2020

Votre API est-elle en temps réel ? Testez sa latence avec l’outil rtapi de NGINX

Votre API répond-elle aux requêtes en moins de 30 ms ? Si ce n’est pas le cas, il ne s’agit pas d’une API en temps réel offrant la faible latence exigée par la grande majorité des organisations. Mesurez la latence de votre API avec l’outil rtapi de NGINX et découvrez comment NGINX peut l’aider à offrir une réactivité en temps réel.

Un testeur d’expressions régulières pour NGINX et NGINX Plus
NGINX | 11/06/2019

Un testeur d’expressions régulières pour NGINX et NGINX Plus

Le testeur d’expressions régulières (regex) pour NGINX et NGINX Plus vous évite de tâtonner en vous indiquant si une expression régulière utilisée dans un bloc location ou map correspond aux valeurs comme prévu. Il génère la configuration appropriée et affiche les valeurs des groupes de capture.

Caches partagés avec les clusters de cache NGINX Plus, partie 1
NGINX | 24/01/2017

Caches partagés avec les clusters de cache NGINX Plus, partie 1

Optimisez la capacité de votre cache web en le répartissant entre plusieurs serveurs de cache web NGINX ou NGINX Plus. Découvrez comment procéder dans cet article.

Introduction aux microservices
NGINX | 19/05/2015

Introduction aux microservices

Les microservices suscitent actuellement beaucoup d’intérêt. Cet article de blog est le premier d’une série de sept consacrée à la conception, au développement et au déploiement de microservices.