nginx njs: instalar o módulo, configurar js_set e aplicar com reload para criar variáveis JavaScript

O nginx njs é um módulo oficial do nginx que trata requisições ou cria valores de variáveis com funções JavaScript dentro da configuração do nginx. Num servidor com Nginx + Apache, para acertar maiúsculas e minúsculas das URLs requisitadas, o que a configuração do nginx sozinha não consegue mudar, o módulo njs foi instalado na mesma versão do nginx instalado, e uma variável criada com js_set foi colocada no caminho do arquivo de cache e aplicada com um reload, sem reiniciar.
A função de exemplo é uma linha só que passa para minúsculas a codificação percentual de URLs em coreano, e criar variáveis lendo cabeçalhos ou valores de argumentos do objeto de requisição funciona do mesmo jeito.
1️⃣ O que é o nginx njs: um módulo que estende o nginx com JavaScript
O njs não é um runtime JavaScript independente como o Node.js: não tem script de inicialização nem event loop próprio, e o código só roda quando o nginx chama uma função indicada na configuração, depois do que o processamento volta para o nginx.
Os pontos em que o nginx chama funções JavaScript são fixos: as fases de processamento de requisições e respostas HTTP, as fases de processamento de sessões TCP/UDP, o cálculo de valores de variáveis e timers periódicos. A função lê a URL, os cabeçalhos e os argumentos do objeto de requisição que o nginx passa e devolve o resultado como resposta ou como valor de variável.
No lado HTTP, [js_import] carrega um arquivo de script, [js_set] cria um valor de variável, [js_content] cria o corpo da resposta, e [js_header_filter] e [js_body_filter] modificam os cabeçalhos e o corpo da resposta. Esta configuração usou duas diretivas: [js_import] e [js_set].
O motor padrão do módulo njs implementa o ECMAScript 5.1 (strict mode) mais alguns recursos do ECMAScript 6 e posteriores. Tratamento de strings no nível de substituição por regex e funções funciona dentro desse escopo.
2️⃣ Quando você precisa do njs: valores de variáveis que a configuração do nginx sozinha não muda
O plugin de WordPress WP Rocket nomeia as pastas de cache de posts com URL em coreano com codificação percentual em minúsculas, enquanto os navegadores requisitam a mesma URL codificada em maiúsculas. Este servidor roda um site WordPress.
Se o nginx monta o caminho do arquivo de cache a partir da URL requisitada como está, maiúsculas e minúsculas não batem, o arquivo não é encontrado e a requisição segue para o Apache e o PHP.
Só com a configuração do nginx não dá para passar esse valor para minúsculas. O [map] apenas escolhe um dos valores que você definiu e não transforma strings, e antes da instalação nem a saída de [nginx -V] nem a pasta de módulos mostravam um módulo perl ou lua.
Se poucas URLs precisam mudar, uma tabela de [map] dá conta, mas é preciso refazer a tabela e dar reload sempre que surge um post novo. Quando cada URL precisa ter o próprio valor convertido pela mesma regra, uma única função [js_set] cobre também posts novos, tags e URLs de categoria.

O [perl_set] do módulo perl pode ser usado no mesmo lugar, e o repositório tem um pacote combinando com o nginx, mas a documentação oficial do nginx descreve o módulo perl como experimental.
3️⃣ Instalar o nginx njs: na mesma versão do nginx instalado
Instalar só pelo nome do pacote parece que vai apenas adicionar o njs, mas o njs mais novo do repositório exige o nginx mais novo, então o nginx também é atualizado. Na verificação antes da instalação, o comando sem versão mostrou um plano de levar o nginx de 1.28.0 para 1.30.6.
Por isso, comece conferindo a versão do nginx instalada agora.
rpm -q nginxnginx-1.28.0-1.el9.ngx.x86_64O repositório tem um pacote njs separado combinando com cada versão do nginx; no número da versão, a parte antes do + é a versão do nginx e a parte depois é a do 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-stableSeis versões, de 0.8.10 a 0.9.4, combinam com o nginx 1.28.0, e a linha @nginx-stable no topo é a que já está instalada. Instale a mais nova delas, 0.9.4, escrevendo o número de versão completo.
dnf install nginx-module-njs-1:1.28.0+0.9.4-1.el9.ngxCom o rpm, você pode conferir qual versão do nginx o pacote instalado 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/COPYRIGHTOs arquivos instalados são o módulo HTTP, o módulo stream que trata TCP/UDP, uma versão de depuração de cada um e a ferramenta de linha de comando njs. Esta configuração carrega um único arquivo, o módulo HTTP [ngx_http_js_module.so].
4️⃣ Configurar o js_set: de carregar o módulo ao caminho do arquivo de cache
Instalar o pacote não faz o nginx carregar o módulo sozinho: o nginx.conf precisa de uma linha [load_module] bem no topo. Pela documentação oficial, [load_module] é uma diretiva do contexto main, então fica fora dos blocos events e http.
# topo do /etc/nginx/nginx.conf (fora dos blocos events e http)
load_module modules/ngx_http_js_module.so;A função de conversão fica num arquivo .js separado dos arquivos de configuração, e a configuração do nginx importa a função exportada com export default na última linha.
// /etc/nginx/njs/rocket.js — só a codificação percentual %XX em minúsculas
function lc(r) {
return r.variables.request_uri.replace(/%[0-9A-F]{2}/g, function (m) { return m.toLowerCase(); });
}
export default { lc };A função lê a variável [request_uri] do objeto de requisição r, passa para minúsculas só os dois caracteres depois de cada sinal de porcentagem onde estão em maiúsculas e devolve o resultado. As letras latinas ficam como estão, então URLs em inglês com maiúsculas não mudam; é a mesma regra que o WP Rocket usa para nomear as pastas de cache.
# dentro do bloco http (um arquivo .conf em conf.d)
js_import rkt from /etc/nginx/njs/rocket.js;
js_set $rocket_uri rkt.lc;Em [js_import], rkt é o nome usado para chamar as funções dentro do módulo, e [js_set] transforma o resultado dessa função na variável [$rocket_uri]. Pela documentação oficial, a função roda quando a variável é referenciada pela primeira vez numa requisição e só aceita processamento síncrono.
# bloco server — o $request_uri no caminho do arquivo de cache vira $rocket_uri
set $rocket_file '/wp-content/cache/wp-rocket/example.com${rocket_uri}index$rocket_mobile-https.html';A única mudança é esta linha que monta o caminho do arquivo de cache; as verificações que excluem do cache cookies de login, queries e requisições POST continuam como estão.
5️⃣ Aplicar e conferir: log de erros e cabeçalhos de resposta depois do reload
Rode primeiro o teste de configuração e dê reload se passar.
nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successfulsystemctl reload nginxA nova linha [load_module] entrou em vigor com um reload, sem reiniciar. O log de erros registrou uma linha da inicialização da máquina virtual njs, e não houve erros de JavaScript.
grep 'js vm init' /var/log/nginx/error.log | head -12026/10/17 18:21:35 [notice] 27992#27992: js vm init njs: 0000559FDF6D0E00O njs no fim da linha é o nome do motor em uso. A mesma linha também é registrada quando você testa a configuração com [nginx -t], então compare com o horário do reload.
curl -sI 'https://example.com/-/' | grep -i 'x-rocket\|content-type'content-type: text/html
x-rocket-nginx-serving-file: HITMesmo numa URL em coreano codificada em maiúsculas, apareceu o cabeçalho que mostra que o nginx entregou o arquivo de cache. Requisições com queries ou cookies de login e requisições POST continuaram indo para o PHP sem esse cabeçalho depois da mudança.
6️⃣ Reverter o njs e atualizar o nginx
Para reverter, troque [$rocket_uri] no caminho do arquivo de cache de volta por [$request_uri], remova o arquivo de configuração de [js_import]/[js_set] e a linha [load_module], depois rode o teste de configuração e dê reload.
# bloco server — de volta à variável original
set $rocket_file '/wp-content/cache/wp-rocket/example.com${request_uri}index$rocket_mobile-https.html';Você pode deixar o pacote instalado: sem a linha [load_module], o nginx não o carrega, então remova o pacote só se quiser apagá-lo de vez.
dnf remove nginx-module-njsAo atualizar o nginx, o pacote njs precisa subir junto para a versão que combina com o novo nginx. Antes de atualizar, confira com [dnf list --showduplicates] se o repositório tem o njs correspondente à nova versão do nginx.
🔢 FAQ & conteúdo recomendado














ℹ️ Aviso de afiliados
O conteúdo deste site contém links de afiliados. Quando um visitante compra um produto ou serviço por meio de um desses links, o site recebe uma comissão do vendedor. O valor que o comprador paga (em promoções, ele diminui ↓) não aumenta por causa disso. Preços, descontos e informações de estoque valem para o momento em que o texto foi escrito e podem ter mudado, por isso confirme com o vendedor antes de comprar. Os produtos são escolhidos e avaliados por critérios próprios, e o recebimento de comissão não influencia a ordem de apresentação nem o conteúdo das avaliações.

