Editor – La entrada de blog titulada «Introducción al módulo JavaScript de NGINX» redirige aquí. La entrada se ha actualizado con las directivas y funcionalidades del módulo JavaScript de NGINX compatibles a fecha de abril de 2021.

El módulo JavaScript de NGINX (njs) pasó a estar disponible de forma general como módulo estable en NGINX Open Source 1.11.10 y NGINX Plus R12. [El módulo se llamaba originalmente nginScript, y ese nombre aparece en algunas publicaciones antiguas.] Hemos trabajado de forma constante en NGINX JavaScript desde su lanzamiento en septiembre de 2015, incorporando las funcionalidades y la compatibilidad con el lenguaje incluidas en el módulo estable.
NGINX JavaScript es una implementación única de JavaScript para NGINX y NGINX Plus, diseñada específicamente para casos de uso del lado del servidor y el procesamiento de cada solicitud. Amplía la sintaxis de configuración de NGINX con código JavaScript para implementar soluciones de configuración avanzadas.
Los casos de uso son numerosos, especialmente porque el módulo NGINX JavaScript está disponible tanto para HTTP como para los protocolos TCP/UDP. Algunos ejemplos de casos de uso de NGINX JavaScript son:
- Generación de formatos de registro personalizados con valores que no están disponibles en las variables habituales de NGINX (por ejemplo, registro de diagnóstico)
- Modificar las respuestas de los servidores proxy (filtrado de respuestas)
- Implementación de esquemas de autenticación personalizados (por ejemplo, introspección de tokens de OAuth 2.0)
- Análisis de protocolos TCP/UDP para sesiones persistentes a nivel de aplicación (por ejemplo, equilibrio de carga de MQTT)
Antes de analizar NGINX JavaScript con más detalle, aclaremos primero dos ideas erróneas habituales.
NGINX JavaScript no es Lua
La comunidad de NGINX ha creado varias extensiones programáticas a lo largo de los años. En el momento de redactar este texto, Lua es la más popular; está disponible como un módulo para NGINX y como un módulo dinámico de terceros precompilado y con soporte para NGINX Plus. El módulo de Lua y las bibliotecas complementarias ofrecen una estrecha integración con el núcleo de NGINX y un amplio conjunto de funcionalidades, incluido un controlador para Redis.
Lua es un potente lenguaje de scripting. Sin embargo, su adopción sigue siendo bastante minoritaria y no suele formar parte del «conjunto de competencias» de los desarrolladores frontend ni de los ingenieros de DevOps.
NGINX JavaScript no pretende sustituir a Lua y aún pasará algún tiempo antes de que NGINX JavaScript alcance un nivel de funcionalidad comparable. El objetivo de NGINX JavaScript es ofrecer soluciones de configuración programática a la comunidad más amplia posible mediante el uso de un lenguaje de programación popular.
NGINX JavaScript no es Node.js
NGINX JavaScript no pretende convertir NGINX ni NGINX Plus en un servidor de aplicaciones. En pocas palabras, los casos de uso de NGINX JavaScript son similares a los del middleware, ya que la ejecución del código JavaScript tiene lugar entre el cliente y el contenido. Desde un punto de vista técnico, aunque Node.js comparte dos aspectos con la combinación de NGINX JavaScript y NGINX o NGINX Plus —una arquitectura basada en eventos y el lenguaje de programación JavaScript—, las similitudes terminan ahí.
Node.js utiliza el motor de JavaScript V8 de Google, mientras que NGINX JavaScript es una implementación específica de los estándares ECMAScript, diseñada expresamente para NGINX y NGINX Plus. Node.js mantiene en memoria una máquina virtual (VM) de JavaScript persistente y realiza periódicamente la recolección de elementos no utilizados para gestionar la memoria, mientras que NGINX JavaScript inicializa una nueva VM de JavaScript y la memoria necesaria para cada solicitud, y libera la memoria cuando esta finaliza.
JavaScript como lenguaje del lado del servidor
Como se ha mencionado anteriormente, NGINX JavaScript es una implementación específica del lenguaje JavaScript. Todos los demás motores de ejecución de JavaScript existentes están diseñados para ejecutarse en un navegador web. La naturaleza de la ejecución de código del lado del cliente difiere de la ejecución de código del lado del servidor en muchos aspectos, desde la disponibilidad de recursos del sistema hasta el posible número de entornos de ejecución simultáneos.
Decidimos implementar nuestro propio entorno de ejecución de JavaScript para satisfacer los requisitos de la ejecución de código en el servidor e integrarlo de forma elegante en la arquitectura de procesamiento de solicitudes de NGINX. Estos son nuestros principios de diseño para NGINX JavaScript:
- El entorno de ejecución nace y muere con la solicitudEl módulo JavaScript de NGINX utiliza la ejecución de bytecode en un único hilo, diseñada para permitir una inicialización y una eliminación rápidas. El entorno de ejecución se inicializa para cada solicitud. El arranque es extremadamente rápido, ya que no hay ningún estado complejo ni funciones auxiliares que inicializar. Durante la ejecución, la memoria se acumula en bloques y, al finalizar, se libera eliminando dichos bloques. Este sistema de gestión de memoria evita tener que realizar un seguimiento de cada objeto y liberarlo individualmente, así como utilizar un recolector de basura.
- Ejecución de código sin bloqueoEl modelo basado en eventos de NGINX y NGINX Plus programa la ejecución de cada entorno de ejecución de NGINX JavaScript. Cuando una regla de NGINX JavaScript realiza una operación de bloqueo (como leer datos de red o emitir una subsolicitud externa), NGINX y NGINX Plus suspenden de forma transparente la ejecución de la máquina virtual de NGINX JavaScript asociada y la reprograman cuando finaliza el evento. Esto permite escribir reglas de forma sencilla y lineal, mientras NGINX y NGINX Plus las programan sin bloqueos internos.
- Implementar únicamente la compatibilidad con el lenguaje que necesitamosLas especificaciones de JavaScript están definidas por los estándares ECMAScript. NGINX JavaScript sigue ECMAScript 5.1 e incorpora algunas características de ECMAScript 6 para funciones matemáticas. Implementar nuestro propio entorno de ejecución de JavaScript nos permite priorizar la compatibilidad con el lenguaje para casos de uso del lado del servidor e ignorar lo que no necesitamos. Mantenemos una lista de los elementos del lenguaje compatibles actualmente.
- Integración estrecha con las fases de procesamiento de solicitudesNGINX y NGINX Plus procesan las solicitudes en distintas fases. Las directivas de configuración suelen actuar en una fase específica, y los módulos nativos de NGINX a menudo aprovechan la posibilidad de inspeccionar o modificar una solicitud en una fase determinada. NGINX JavaScript expone algunas de las fases de procesamiento mediante directivas de configuración para permitir controlar cuándo se ejecuta el código JavaScript. Esta integración con la sintaxis de configuración ofrece la potencia y flexibilidad de los módulos nativos de NGINX con la sencillez del código JavaScript. La tabla siguiente indica qué fases de procesamiento están disponibles mediante NGINX JavaScript en el momento de redactar este texto y las directivas de configuración que permiten acceder a ellas.
| Fase de procesamiento | Módulo HTTP | Módulo Stream |
|---|---|---|
Acceso – Autenticación y control de acceso | auth_request y js_content | js_access |
Lectura previa – Lectura/escritura de la carga útil | N/D | js_preread |
Filtrado – Lectura/escritura de la respuesta durante el proxy | js_body_filterjs_header_filter | js_filter |
Contenido – Envío de la respuesta al cliente | js_content | N/D |
Registro / Variables – Evaluación bajo demanda | js_set | js_set |
Primeros pasos con NGINX JavaScript – Un ejemplo real
NGINX JavaScript se implementa como un módulo que puede compilar en un binario de NGINX Open Source o cargar dinámicamente en NGINX o NGINX Plus. Instrucciones para habilitar NGINX JavaScript con NGINX y NGINX Plus se encuentran al final de este artículo.
En este ejemplo, utilizamos NGINX o NGINX Plus como un proxy inverso sencillo y NGINX JavaScript para crear entradas del registro de acceso en un formato especializado que:
- Incluye las cabeceras de solicitud enviadas por el cliente
- Incluye las cabeceras de respuesta devueltas por el backend
- Utiliza pares clave-valor para facilitar una ingesta y búsqueda eficientes con herramientas de procesamiento de registros como ELK Stack (ahora denominada Elastic Stack), Graylog y Splunk
La configuración de NGINX para este ejemplo es extremadamente sencilla.
Cargando ejemplo de código…
Como puede ver, el código JavaScript de NGINX no se incluye directamente en la sintaxis de configuración. En su lugar, utilizamos la directiva js_import para especificar el archivo que contiene todo nuestro código JavaScript. La directiva js_set define una nueva variable de NGINX, $access_log_headers, y la función JavaScript que la rellena. La directiva log_format define un nuevo formato denominado kvpairs, que escribe cada línea del registro con el valor de $access_log_headers.
El bloque server define un proxy inverso HTTP sencillo que reenvía todas las solicitudes a https://www.example.com. La directiva access_log especifica que todas las solicitudes se registrarán con el formato kvpairs.
Veamos ahora el código JavaScript que prepara una entrada de registro.
Cargando ejemplo de código…
El valor devuelto por la función kvAccess —una entrada de registro— se pasa a la directiva de configuración js_set en rawheader_logging.conf. Tenga en cuenta que las variables de NGINX se evalúan bajo demanda, lo que a su vez significa que la función JavaScript definida mediante js_set se ejecuta cuando se necesita el valor de la variable. En este ejemplo, $access_log_headers se utiliza en la directiva log_format, por lo que kvAccess() se ejecuta en el momento de registrar la entrada. Las variables utilizadas como parte de las directivas map o rewrite (que no se muestran en este ejemplo) activan la ejecución del código JavaScript correspondiente en una fase anterior del procesamiento.
Podemos ver en acción esta solución de registro de NGINX mejorada con JavaScript enviando una solicitud a través de nuestro proxy inverso y observando la entrada resultante en el archivo de registro, que incluye las cabeceras de la solicitud con el prefijo «in.» y las cabeceras de la respuesta con el prefijo «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=bytesGran parte de la utilidad de NGINX JavaScript se debe a su acceso a los componentes internos de NGINX. Este ejemplo utiliza varias propiedades del objeto de solicitud (r). El módulo Stream de NGINX JavaScript (para aplicaciones TCP y UDP) utiliza un objeto de sesión (s) con su propio conjunto de propiedades. Para ver otros ejemplos de soluciones de NGINX JavaScript tanto para HTTP como para TCP/UDP, consulte Casos de uso del módulo JavaScript de NGINX.
Nos encantaría conocer los casos de uso que se os ocurran para NGINX JavaScript. Contádnoslos en la sección de comentarios que aparece a continuación.
Casos de uso del módulo JavaScript de NGINX
Consulta estas entradas de blog para descubrir otros casos de uso de HTTP y TCP/UDP para el módulo JavaScript de NGINX:
- Declaración de código JavaScript y variables en contextos locales en «Haz que tu configuración de NGINX sea aún más modular y reutilizable con njs 0.7.7»
- Uso de NGINX como puerta de enlace DoT o DoH
- Presentamos NGINX Plus R26 – Uso de funciones asíncronas y de la API WebCrypto para generar números aleatorios seguros y calcular el hash de cadenas de texto
- Mitigación de la vulnerabilidad de log4j con NGINX
- Registro avanzado con el módulo JavaScript de NGINX en «Escalado de MySQL con balanceo de carga TCP y Galera Cluster»
- Presentamos NGINX Plus R24 – Filtrado de respuestas tanto para el cuerpo como para las cabeceras; uso del cliente HTTP integrado para autenticar conexiones TCP/UDP
- Validación de los cuerpos de las solicitudes en «Implementación de NGINX Plus como puerta de enlace de API, parte 2: protección de los servicios de backend»
- Registro de diagnóstico con el módulo JavaScript de NGINX<.htmla>
- Presentamos NGINX Plus R22 – Registro del conjunto exacto de encabezados enviados por el cliente cada vez que se produce un error
- Presentamos NGINX Plus R21 – Encadenamiento de subsolicitudes en una única secuencia de código sin usar funciones de devolución de llamada; envío de una copia de las cabeceras de la solicitud a un sistema de gestión de eventos e información de seguridad (SIEM)
- Un solo POST: cómo habilitar el DNS declarativo con F5 y el módulo JavaScript de NGINX
- Ampliación de
auth_requestcon el módulo JavaScript de NGINX en «Validación de tokens de acceso OAuth 2.0 con NGINX y NGINX Plus» - Actualizaciones inalámbricas de dispositivos IoT con NGINX
- Presentamos NGINX Plus R18 – Registro de una versión con hash (enmascarada) de la dirección IP del cliente en lugar de la dirección real
- Aplicación de parches virtuales con el módulo JavaScript de NGINX
- Agrupación de solicitudes de API con NGINX Plus y el módulo JavaScript de NGINX
- Presentamos NGINX Plus R15 – Envío simultáneo de una solicitud HTTP a dos backends diferentes para, a continuación, reenviar la primera respuesta e ignorar la segunda; incorporación de integridad de datos a las cookies de la aplicación
- Escalado de la detección de cambios mediante hash con JavaScript en «Detección de la alteración de la página de inicio mediante comprobaciones de estado activas»
- Ampliación del balanceo de carga TCP.htmlUDP con nginScript en «Balanceo de carga TCP/UDP con NGINX: descripción general, consejos y trucos»
- Uso de certificados de cliente para autenticar clientes MQTT en «NGINX Plus para el IoT: cifrado y autenticación del tráfico MQTT»
- Equilibrado de carga de MQTT para la persistencia de sesiones con el módulo JavaScript de NGINX en «NGINX Plus para el IoT: equilibrado de carga de MQTT»
- Enmascaramiento de datos para proteger la privacidad de los usuarios con el módulo JavaScript de NGINX
- Presentamos NGINX Plus R11 – Búsqueda de patrones clave en un mensaje de un flujo del protocolo MySQL para identificar la operación SQL
- Uso del módulo JavaScript de NGINX para migrar progresivamente los clientes a un nuevo servidor
[ngx_snippet name=’njs-enable-instructions’]
Sobre el autor

Artículos relacionados del blog
Únete a F5 NGINX en AppWorld 2024
Descubre las numerosas razones para asistir al evento insignia de F5, que incluirá un emocionante anuncio sobre la cartera de productos NGINX.
Rotación de certificados SSL/TLS sin reinicios en NGINX Open Source
La función de diccionario compartido permite configurar NGINX sin necesidad de reiniciarlo al renovar los certificados SSL/TLS.
Exposición de APIs en Kubernetes
La unidad 2 de Microservices March 2022 se centra en cómo exponer tus API en Kubernetes. Aquí tienes enlaces a los recursos que necesitas: la retransmisión en directo del 14 de marzo, artículos de blog y otros recursos de preparación, y el laboratorio práctico «Protege las API de Kubernetes mediante la limitación de solicitudes».
NGINX Sprint 2.0: visión clara, código renovado y nuevos compromisos con el código abierto
Hoy, en NGINX Sprint 2.0, anunciamos cómo respaldaremos nuestra visión del futuro de las aplicaciones modernas con una mayor presencia en la comunidad de código abierto, incluida la participación en el proyecto comunitario Kubernetes, nuevos proyectos de software de código abierto y la arquitectura de referencia para aplicaciones modernas.
Presentamos NGINX Plus R22
NGINX Plus R22 incorpora nuevas funcionalidades, como la compatibilidad con OCSP para verificar la revocación de certificados en TLS mutuo, el uso de varios proveedores de identidad OIDC en una configuración, el seguimiento en tiempo real de la limitación de solicitudes y conexiones en el panel de NGINX Plus y mejoras en NGINX JavaScript.
Presentamos NGINX Plus R17
NGINX Plus R17 incorpora compatibilidad con la limitación de velocidad en dos fases y con TLS 1.3, la versión más reciente del protocolo Transport Layer Security. La configuración de OpenID Connect es más sencilla y NGINX ModSecurity WAF es el doble de rápido que antes. También se ha actualizado el módulo JavaScript de NGINX.