JS#

O módulo é usado para implementar manipuladores em njs — um subconjunto da linguagem JavaScript.

Em nossos repositórios, o módulo é construído dinamicamente e está disponível como um pacote separado chamado angie-module-njs ou angie-pro-module-njs.

Nota

Uma versão leve do pacote, chamada ...-njs-light, também está disponível; no entanto, ela não pode ser usada junto com a versão regular.

Exemplo de Configuração#

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;
        }
    }
}

O arquivo 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};

Diretivas#

js_body_filter#

Sintaxe

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

Padrão

Contexto

location, if in location, limit_except

Define uma função njs como filtro do corpo da resposta. A função de filtro é chamada para cada bloco de dados do corpo da resposta com os seguintes argumentos:

r

o objeto requisição HTTP

data

o bloco de dados recebido, pode ser uma string ou Buffer dependendo do valor buffer_type, por padrão é uma string.

flags

um objeto com as seguintes propriedades: - last — um valor booleano, true se data é o último buffer

A função de filtro pode passar sua própria versão modificada do bloco de dados de entrada para o próximo filtro de corpo chamando r.sendBuffer(). Por exemplo, para transformar todas as letras minúsculas no corpo da resposta:

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

Para parar a filtragem (os blocos de dados seguintes serão passados para o cliente sem chamar js_body_filter), r.done() pode ser usado.

Se a função de filtro alterar o comprimento do corpo da resposta, então é necessário limpar o cabeçalho de resposta Content-Length (se houver) em js_header_filter para forçar a codificação de transferência em blocos.

Nota

Como o manipulador js_body_filter retorna seu resultado imediatamente, ele suporta apenas operações síncronas. Assim, operações assíncronas como r.subrequest() ou setTimeout() não são suportadas.

js_content#

Sintaxe

js_content function | module.function;

Padrão

Contexto

location, if in location, limit_except

Define uma função njs como manipulador de conteúdo de localização. Funções de módulo podem ser referenciadas.

js_fetch_buffer_size#

Sintaxe

js_fetch_buffer_size size;

Padrão

js_fetch_buffer_size 16k;

Contexto

http, server, location

Define o tamanho do buffer usado para leitura e escrita com Fetch API.

js_fetch_ciphers#

Sintaxe

js_fetch_ciphers ciphers;

Padrão

js_fetch_ciphers HIGH:!aNULL:!MD5;

Contexto

http, server, location

Especifica as cifras habilitadas para conexões HTTPS com Fetch API. As cifras são especificadas no formato compreendido pela biblioteca OpenSSL.

A lista de cifras depende da versão do OpenSSL instalada. A lista completa pode ser visualizada usando o comando openssl ciphers.

js_fetch_max_response_buffer_size#

Sintaxe

js_fetch_max_response_buffer_size size;

Padrão

js_fetch_max_response_buffer_size 1m;

Contexto

http, server, location

Define o tamanho máximo da resposta recebida com Fetch API.

js_fetch_protocols#

Sintaxe

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

Padrão

js_fetch_protocols TLSv1 TLSv1.1 TLSv1.2;

Contexto

http, server, location

Habilita os protocolos especificados para conexões HTTPS com Fetch API.

js_fetch_timeout#

Sintaxe

js_fetch_timeout time;

Padrão

js_fetch_timeout 60s;

Contexto

http, server, location

Define um timeout para leitura e escrita para Fetch API. O timeout é definido apenas entre duas operações sucessivas de leitura/escrita, não para toda a resposta. Se nenhum dado for transmitido dentro deste tempo, a conexão é fechada.

js_fetch_trusted_certificate#

Sintaxe

js_fetch_trusted_certificate file;

Padrão

Contexto

http, server, location

Especifica um arquivo com certificados CA confiáveis no formato PEM usado para verificar o certificado HTTPS com Fetch API.

js_fetch_verify#

Sintaxe

js_fetch_verify on | off;

Padrão

js_fetch_verify on;

Contexto

http, server, location

Habilita ou desabilita a verificação do certificado do servidor HTTPS com Fetch API.

js_fetch_verify_depth#

Sintaxe

js_fetch_verify_depth número;

Padrão

js_fetch_verify_depth 100;

Contexto

http, server, location

Define a profundidade de verificação na cadeia de certificados do servidor HTTPS com Fetch API.

js_header_filter#

Sintaxe

js_header_filter função | módulo.função;

Padrão

Contexto

location, if in location, limit_except

Define uma função njs como filtro de cabeçalho de resposta. A diretiva permite alterar campos de cabeçalho arbitrários de um cabeçalho de resposta.

Nota

Como o manipulador js_header_filter retorna seu resultado imediatamente, ele suporta apenas operações síncronas. Assim, operações assíncronas como r.subrequest() ou setTimeout() não são suportadas.

js_import#

Sintaxe

js_import módulo.js | nome_exportação from módulo.js;

Padrão

Contexto

http, server, location

Importa um módulo que implementa manipuladores de location e variável em njs. O nome_exportação é usado como namespace para acessar funções do módulo. Se o nome_exportação não for especificado, o nome do módulo será usado como namespace.

js_import http.js;

Aqui, o nome do módulo http é usado como namespace ao acessar exportações. Se o módulo importado exporta foo(), http.foo é usado para se referir a ele.

Várias diretivas js_import podem ser especificadas.

js_path#

Sintaxe

js_path caminho;

Padrão

Contexto

http, server, location

Define um caminho adicional para módulos njs.

js_preload_object#

Sintaxe

js_preload_object nome.json | nome from arquivo.json;

Padrão

Contexto

http, server, location

Pré-carrega um objeto imutável no momento da configuração. O nome é usado como nome da variável global através da qual o objeto está disponível no código njs. Se o nome não for especificado, o nome do arquivo será usado em seu lugar.

js_preload_object map.json;

Aqui, o map é usado como nome ao acessar o objeto pré-carregado.

Várias diretivas js_preload_object podem ser especificadas.

js_set#

Sintaxe

js_set $variável função | módulo.função;

Padrão

Contexto

http, server, locatio

Define uma função njs para a variável especificada. Funções de módulo podem ser referenciadas.

A função é chamada quando a variável é referenciada pela primeira vez para uma determinada requisição. O momento exato depende de uma fase na qual a variável é referenciada. Isso pode ser usado para executar alguma lógica não relacionada à avaliação de variável. Por exemplo, se a variável é referenciada apenas na diretiva log_format, seu manipulador não será executado até a fase de log. Este manipulador pode ser usado para fazer alguma limpeza logo antes da requisição ser liberada.

Nota

Como o manipulador js_set retorna seu resultado imediatamente, ele suporta apenas callbacks síncronos. Assim, callbacks assíncronos como r.subrequest() ou setTimeout() não são suportados.

js_shared_dict_zone#

Sintaxe

js_shared_dict_zone zone=nome:tamanho [timeout=tempo] [type=string | number] [evict];

Padrão

Contexto

http

Define o nome e tamanho da zona de memória compartilhada que mantém o dicionário chave-valor compartilhado entre processos worker.

type

parâmetro opcional, permite redefinir o tipo de valor para number; por padrão, o dicionário compartilhado usa string para chaves e valores

timeout

parâmetro opcional, define o tempo após o qual todas as entradas do dicionário compartilhado são removidas da zona

evict

parâmetro opcional, remove o par chave-valor mais antigo quando o armazenamento da zona está esgotado

Exemplos:

example.conf:
    # Cria um dicionário com tamanho de 1MB para valores string,
    # pares chave-valor são removidos após 60 segundos de inatividade:
    js_shared_dict_zone zone=foo:1M timeout=60s;

    # Cria um dicionário com tamanho de 512KB para valores string,
    # par chave-valor mais antigo é removido quando a zona transborda:
    js_shared_dict_zone zone=bar:512K timeout=30s evict;

    # Cria um dicionário persistente com tamanho de 32KB 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#

Sintaxe

js_var $variável [valor];

Padrão

Contexto

http, server, location

Declara uma variável gravável. O valor pode conter texto, variáveis e sua combinação. A variável não é sobrescrita após um redirecionamento, diferentemente de variáveis criadas com a diretiva set.

Argumento de Requisição#

Cada manipulador HTTP njs recebe um argumento, um objeto request.