JS#

El módulo se utiliza para implementar manejadores en njs — un subconjunto del lenguaje JavaScript.

En nuestros repositorios, el módulo se construye de forma dinámica dinámicamente y está disponible como un paquete separado llamado angie-module-njs o angie-pro-module-njs.

Nota

También está disponible una versión ligera del paquete, llamada ...-njs-light; sin embargo, no puede usarse junto con la versión regular.

Ejemplo de Configuración#

http {
    js_import http.js;

    js_set $foo     http.foo;
    js_set $summary http.summary;
    js_set $hash    http.hash;

    resolver 127.0.0.53;

    server {
        listen 8000;

        location / {
            add_header X-Foo $foo;
            js_content http.baz;
        }

        location = /summary {
            return 200 $summary;
        }

        location = /hello {
            js_content http.hello;
        }

        location = /fetch {
            js_content                   http.fetch;
            js_fetch_trusted_certificate /path/to/ISRG_Root_X1.pem;
        }

        location = /crypto {
            add_header Hash $hash;
            return     200;
        }
    }
}

El archivo http.js:

function foo(r) {
    r.log("hello from foo() handler");
    return "foo";
}

function summary(r) {
    var a, s, h;

    s = "JS summary\n\n";

    s += "Method: " + r.method + "\n";
    s += "HTTP version: " + r.httpVersion + "\n";
    s += "Host: " + r.headersIn.host + "\n";
    s += "Remote Address: " + r.remoteAddress + "\n";
    s += "URI: " + r.uri + "\n";

    s += "Headers:\n";
    for (h in r.headersIn) {
        s += "  header '" + h + "' is '" + r.headersIn[h] + "'\n";
    }

    s += "Args:\n";
    for (a in r.args) {
        s += "  arg '" + a + "' is '" + r.args[a] + "'\n";
    }

    return s;
}

function baz(r) {
    r.status = 200;
    r.headersOut.foo = 1234;
    r.headersOut['Content-Type'] = "text/plain; charset=utf-8";
    r.headersOut['Content-Length'] = 15;
    r.sendHeader();
    r.send("nginx");
    r.send("java");
    r.send("script");

    r.finish();
}

function hello(r) {
    r.return(200, "Hello world!");
}

async function fetch(r) {
    let results = await Promise.all([ngx.fetch('https://google.com/'),
                                     ngx.fetch('https://google.ru/')]);

    r.return(200, JSON.stringify(results, undefined, 4));
}

async function hash(r) {
    let hash = await crypto.subtle.digest('SHA-512', r.headersIn.host);
    r.setReturnValue(Buffer.from(hash).toString('hex'));
}

export default {foo, summary, baz, hello, fetch, hash};

Directivas#

js_body_filter#

Sintaxis

js_body_filter function | module.function [buffer_type=string | buffer];

Predeterminado

Contexto

location, if in location, limit_except

Establece una función njs como filtro del cuerpo de la respuesta. La función de filtrado se llama para cada fragmento de datos del cuerpo de la respuesta con los siguientes argumentos:

r

el objeto de HTTP request <https://nginx.org/en/docs/njs/reference.html#http>

data

el fragmento de datos entrante, puede ser una cadena o Buffer dependiendo del valor de buffer_type, por defecto es una cadena.

flags

un objeto con las siguientes propiedades: - last — un valor booleano, true si los datos son el último buffer

La función de filtrado puede pasar su propia versión modificada del fragmento de datos de entrada al siguiente filtro de cuerpo llamando r.sendBuffer(). Por ejemplo, para transformar todas las letras minúsculas en el cuerpo de la respuesta:

function filter(r, data, flags) {
    r.sendBuffer(data.toLowerCase(), flags);
}

Para detener el filtrado (los siguientes fragmentos de datos serán enviados al cliente sin llamar a js_body_filter), se puede usar r.done().

Si la longitud del cuerpo de la respuesta cambia, es necesario limpiar la cabecera de respuesta Content-Length (si existe) en js_header_filter para forzar la codificación de transferencia por fragmentos.

Nota

Como el manejador js_body_filter devuelve su resultado de forma inmediata, solo admite operaciones sincrónicas. Por lo tanto, no se admiten operaciones asíncronas como r.subrequest() o setTimeout().

js_content#

Sintaxis

js_content function | module.function;

Predeterminado

Contexto

location, if in location, limit_except

Establece una función njs como manejador de contenido de la ubicación. Se pueden referenciar funciones de módulos.

js_fetch_buffer_size#

Sintaxis

js_fetch_buffer_size size;

Predeterminado

js_fetch_buffer_size 16k;

Contexto

http, server, location

Establece el tamaño del búfer utilizado para leer y escribir con Fetch API.

js_fetch_ciphers#

Sintaxis

js_fetch_ciphers ciphers;

Predeterminado

js_fetch_ciphers HIGH:!aNULL:!MD5;

Contexto

http, server, location

Especifica los cifrados habilitados para conexiones HTTPS con Fetch API. Los cifrados se especifican en el formato entendido por la biblioteca OpenSSL.

La lista de cifrados depende de la versión de OpenSSL instalada. La lista completa se puede ver utilizando el comando openssl ciphers.

js_fetch_max_response_buffer_size#

Sintaxis

js_fetch_max_response_buffer_size size;

Predeterminado

js_fetch_max_response_buffer_size 1m;

Contexto

http, server, location

Establece el tamaño máximo de la respuesta recibida con Fetch API.

js_fetch_protocols#

Sintaxis

js_fetch_protocols [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3];

Predeterminado

js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;

Contexto

http, server, location

Habilita los protocolos especificados para conexiones HTTPS con Fetch API.

js_fetch_timeout#

Sintaxis

js_fetch_timeout time;

Predeterminado

js_fetch_timeout 60s;

Contexto

http, server, location

Define un tiempo de espera para lectura y escritura para Fetch API. El tiempo de espera se establece solo entre dos operaciones sucesivas de lectura/escritura, no para toda la respuesta. Si no se transmiten datos dentro de este tiempo, la conexión se cierra.

js_fetch_trusted_certificate#

Sintaxis

js_fetch_trusted_certificate file;

Predeterminado

Contexto

http, server, location

Especifica un archivo con certificados CA de confianza en formato PEM utilizados para verificar el certificado HTTPS con Fetch API.

js_fetch_verify#

Sintaxis

js_fetch_verify on | off;

Predeterminado

js_fetch_verify on;

Contexto

http, server, location

Enables or disables verification of the HTTPS server certificate with Fetch API.

js_fetch_verify_depth#

Sintaxis

js_fetch_verify_depth number;

Predeterminado

js_fetch_verify_depth 100;

Contexto

http, server, location

Establece la profundidad de verificación en la cadena de certificados del servidor HTTPS con Fetch API.

js_header_filter#

Sintaxis

js_header_filter function | module.function;

Predeterminado

Contexto

location, if in location, limit_except

Establece una función njs como filtro de cabecera de respuesta. La directiva permite cambiar campos de cabecera arbitrarios de una cabecera de respuesta.

Nota

Como el manejador js_header_filter devuelve su resultado inmediatamente, solo admite operaciones síncronas. Por lo tanto, no se admiten operaciones asíncronas como r.subrequest() o setTimeout().

js_import#

Sintaxis

js_import module.js | export_name from module.js;

Predeterminado

Contexto

http, server, location

Importa un módulo que implementa manejadores de ubicación y variables en njs. El export_name se utiliza como un espacio de nombres para acceder a las funciones del módulo. Si no se especifica export_name, el nombre del módulo se utilizará como espacio de nombres.

js_import http.js;

Aquí, el nombre del módulo http se utiliza como espacio de nombres al acceder a las exportaciones. Si el módulo importado exporta foo(), se utiliza http.foo para referirse a ella.

Se pueden especificar varias directivas js_import.

js_path#

Sintaxis

js_path path;

Predeterminado

Contexto

http, server, location

Establece una ruta adicional para los módulos njs.

js_preload_object#

Sintaxis

js_preload_object name.json | name from file.json;

Predeterminado

Contexto

http, server, location

Precarga un objeto inmutable en el momento de la configuración. El name se utiliza como nombre de la variable global a través de la cual el objeto está disponible en el código njs. Si no se especifica name, se utilizará el nombre del archivo.

js_preload_object map.json;

Aquí, map se utiliza como nombre al acceder al objeto precargado.

Se pueden especificar varias directivas js_preload_object.

js_set#

Sintaxis

js_set $variable function | module.function;

Predeterminado

Contexto

http, server, locatio

Establece una función njs para la variable especificada. Se pueden referenciar funciones de módulos.

La función se llama cuando la variable se referencia por primera vez para una solicitud dada. El momento exacto depende de la fase en la que se referencia la variable. Esto se puede utilizar para realizar alguna lógica no relacionada con la evaluación de variables. Por ejemplo, si la variable solo se referencia en la directiva log_format, su manejador no se ejecutará hasta la fase de registro. Este manejador se puede utilizar para realizar alguna limpieza justo antes de que se libere la solicitud.

Nota

Como el manejador js_set devuelve su resultado de forma inmediata, solo admite devoluciones de llamada sincrónicas. Por lo tanto, no se admiten devoluciones de llamada asincrónicas como r.subrequest() o setTimeout().

js_shared_dict_zone#

Sintaxis

js_shared_dict_zone zone=name:size [timeout=time] [type=string | number] [evict];

Predeterminado

Contexto

http

Establece el nombre y tamaño de la zona de memoria compartida que mantiene el diccionario clave-valor compartido entre los procesos de trabajo.

type

parámetro opcional, que permite redefinir el tipo de valor a number; por defecto, el diccionario compartido utiliza cadenas para claves y valores

timeout

parámetro opcional, establece el tiempo después del cual todas las entradas del diccionario compartido se eliminan de la zona

evict

parámetro opcional, elimina el par clave-valor más antiguo cuando el espacio de la zona se agota

Ejemplos:

example.conf:
    # Crea un diccionario con 1MB de tamaño para valores de cadena,
    # las parejas clave-valor se eliminan después de 60 segundos de inactividad:
    js_shared_dict_zone zone=foo:1M timeout=60s;

    # Crea un diccionario con 512KB de tamaño para valores de cadena,
    # la pareja clave-valor más antigua se elimina cuando la zona se desborda:
    js_shared_dict_zone zone=bar:512K timeout=30s evict;

    # Crea un diccionario persistente con 32KB de tamaño para valores numéricos:
    js_shared_dict_zone zone=num:32k type=number;
example.js:
    function get(r) {
        r.return(200, ngx.shared.foo.get(r.args.key));
    }

    function set(r) {
        r.return(200, ngx.shared.foo.set(r.args.key, r.args.value));
    }

    function delete(r) {
        r.return(200, ngx.shared.bar.delete(r.args.key));
    }

    function increment(r) {
        r.return(200, ngx.shared.num.incr(r.args.key, 2));
    }

js_var#

Sintaxis

js_var $variable [value];

Predeterminado

Contexto

http, server, location

Declara una variable escribible. El valor puede contener texto, variables y su combinación. La variable no se sobrescribe después de una redirección, a diferencia de las variables creadas con la directiva set.

Solicitud Argumento#

Cada manejador HTTP njs recibe un argumento, un objeto request.