ngx_http_lua_module – Incorpore o poder de Lua em servidores HTTP Nginx.
Este módulo é um componente central do OpenResty. Se você estiver usando este módulo, então você está essencialmente usando o OpenResty :)
Este módulo não é distribuído com a fonte Nginx. Consulte as instruções de instalação.
Produção pronta.
Este documento descreve o ngx_lua v0.10.25, lançado em 19 de junho de 2023.
Vídeo do YouTube "Exemplo HTTP Hello World com OpenResty/Lua"
Vídeo do YouTube "Escreva seus próprios módulos Lua em aplicativos OpenResty/Nginx"
Vídeo do YouTube "Demonstração do utilitário de linha de comando resty do OpenResty"
Vídeo do YouTube "Medir o tempo de execução do código Lua corretamente no OpenResty"
Vídeo do YouTube "Pré-compile módulos Lua em bytecode LuaJIT para acelerar a inicialização do OpenResty"
Você está convidado a se inscrever em nosso canal oficial no YouTube, OpenResty.
Voltar ao sumário
# set search paths for pure Lua external libraries (';;' is the default path):
lua_package_path '/foo/bar/?.lua;/blah/?.lua;;' ;
# set search paths for Lua external libraries written in C (can also use ';;'):
lua_package_cpath '/bar/baz/?.so;/blah/blah/?.so;;' ;
server {
location /lua_content {
# MIME type determined by default_type:
default_type 'text/plain' ;
content_by_lua_block {
ngx.say('Hello,world!')
}
}
location /nginx_var {
# MIME type determined by default_type:
default_type 'text/plain' ;
# try access /nginx_var?a=hello,world
content_by_lua_block {
ngx.say(ngx.var.arg_a)
}
}
location = /request_body {
client_max_body_size 50k ;
client_body_buffer_size 50k ;
content_by_lua_block {
ngx.req.read_body() -- explicitly read the req body
local data = ngx.req.get_body_data()
if data then
ngx.say(" body data: ")
ngx.print(data)
return
end
-- body may get buffered in a temp file:
local file = ngx.req.get_body_file()
if file then
ngx.say(" body is in file ", file)
else
ngx.say(" no body found ")
end
}
}
# transparent non-blocking I/O in Lua via subrequests
# (well, a better way is to use cosockets)
location = /lua {
# MIME type determined by default_type:
default_type 'text/plain';
content_by_lua_block {
local res = ngx.location.capture(" /some_other_location ")
if res then
ngx.say(" status: ", res.status)
ngx.say(" body: ")
ngx.print(res.body)
end
}
}
location = /foo {
rewrite_by_lua_block {
res = ngx.location.capture(" /memc ",
{ args = { cmd = " incr ", key = ngx.var.uri } }
)
}
proxy_pass http://blah.blah.com;
}
location = /mixed {
rewrite_by_lua_file /path/to/rewrite.lua;
access_by_lua_file /path/to/access.lua;
content_by_lua_file /path/to/content.lua;
}
# use nginx var in code path
# CAUTION: contents in nginx var must be carefully filtered,
# otherwise there'll be great security risk!
location ~ ^/app/([-_a-zA-Z0-9/]+) {
set $path $1 ;
content_by_lua_file /path/to/lua/app/root/ $path .lua;
}
location / {
client_max_body_size 100k;
client_body_buffer_size 100k;
access_by_lua_block {
-- check the client IP address is in our black list
if ngx.var.remote_addr == " 132.5.72.3 " then
ngx.exit(ngx.HTTP_FORBIDDEN)
end
-- check if the URI contains bad words
if ngx.var.uri and
string.match(ngx.var.request_body, " evil ")
then
return ngx.redirect(" /terms_of_use.html ")
end
-- tests passed
}
# proxy_pass/fastcgi_pass/etc settings
}
}
Voltar ao sumário
Este módulo incorpora LuaJIT 2.0/2.1 no Nginx. É um componente central do OpenResty. Se você estiver usando este módulo, estará essencialmente usando o OpenResty.
Desde a versão v0.10.16
deste módulo, o interpretador Lua padrão (também conhecido como "PUC-Rio Lua") não é mais suportado. Este documento usa alternadamente os termos "Lua" e "LuaJIT" para se referir ao interpretador LuaJIT.
Ao aproveitar as subsolicitações do Nginx, este módulo permite a integração dos poderosos threads Lua (conhecidos como "co-rotinas" Lua) no modelo de eventos Nginx.
Ao contrário do mod_lua do Apache e do mod_magnet do Lighttpd, o código Lua executado usando este módulo pode ser 100% sem bloqueio no tráfego de rede, desde que a API Nginx para Lua fornecida por este módulo seja usada para lidar com solicitações para serviços upstream, como MySQL, PostgreSQL, Memcached , Redis ou serviços web HTTP upstream.
Pelo menos as seguintes bibliotecas Lua e módulos Nginx podem ser usados com este módulo:
Quase todos os módulos Nginx podem ser usados com este módulo ngx_lua por meio de ngx.location.capture ou ngx.location.capture_multi mas é recomendado usar essas bibliotecas lua-resty-*
em vez de criar subsolicitações para acessar os módulos upstream do Nginx porque o o primeiro geralmente é muito mais flexível e eficiente em termos de memória.
O interpretador Lua (também conhecido como "Lua State" ou "LuaJIT VM instance") é compartilhado entre todas as solicitações em um único processo de trabalho Nginx para minimizar o uso de memória. Os contextos de solicitação são segregados usando corrotinas Lua leves.
Os módulos Lua carregados persistem no nível do processo de trabalho Nginx, resultando em um pequeno consumo de memória em Lua, mesmo quando sob cargas pesadas.
Este módulo está conectado ao subsistema "http" do Nginx para que ele possa falar apenas protocolos de comunicação downstream na família HTTP (HTTP 0.9/1.0/1.1/2.0, WebSockets, etc...). Se você deseja fazer comunicações TCP genéricas com os clientes downstream, você deve usar o módulo ngx_stream_lua, que oferece uma API Lua compatível.
Voltar ao sumário
Só para citar alguns:
As possibilidades são ilimitadas pois o módulo permite reunir diversos elementos dentro do Nginx além de expor ao usuário o poder da linguagem Lua. O módulo fornece flexibilidade total de scripts, ao mesmo tempo que oferece níveis de desempenho comparáveis aos programas nativos da linguagem C, tanto em termos de tempo de CPU quanto de consumo de memória, graças ao LuaJIT 2.x.
Outras implementações de linguagem de script normalmente lutam para atingir esse nível de desempenho.
Voltar ao sumário
A versão mais recente deste módulo é compatível com as seguintes versões do Nginx:
Núcleos Nginx anteriores a 1.6.0 (exclusivo) não são suportados.
Voltar ao sumário
É altamente recomendado usar versões OpenResty que agrupam Nginx, ngx_lua (este módulo), LuaJIT, bem como outros módulos Nginx complementares poderosos e bibliotecas Lua.
É desencorajado construir este módulo com Nginx você mesmo, pois é complicado configurá-lo exatamente da maneira certa.
Observe que as versões oficiais do Nginx, LuaJIT e OpenSSL têm várias limitações e bugs de longa data que podem fazer com que alguns dos recursos deste módulo sejam desativados, não funcionem corretamente ou fiquem mais lentos. Lançamentos oficiais do OpenResty são recomendados porque agrupam o fork LuaJIT 2.1 otimizado do OpenResty e patches Nginx/OpenSSL.
Alternativamente, ngx_lua pode ser compilado manualmente no Nginx:
Construa a fonte com este módulo:
wget ' https://openresty.org/download/nginx-1.19.3.tar.gz '
tar -xzvf nginx-1.19.3.tar.gz
cd nginx-1.19.3/
# tell nginx's build system where to find LuaJIT 2.0:
export LUAJIT_LIB=/path/to/luajit/lib
export LUAJIT_INC=/path/to/luajit/include/luajit-2.0
# tell nginx's build system where to find LuaJIT 2.1:
export LUAJIT_LIB=/path/to/luajit/lib
export LUAJIT_INC=/path/to/luajit/include/luajit-2.1
# Here we assume Nginx is to be installed under /opt/nginx/.
./configure --prefix=/opt/nginx
--with-ld-opt= " -Wl,-rpath,/path/to/luajit/lib "
--add-module=/path/to/ngx_devel_kit
--add-module=/path/to/lua-nginx-module
# Note that you may also want to add `./configure` options which are used in your
# current nginx build.
# You can get usually those options using command nginx -V
# you can change the parallelism number 2 below to fit the number of spare CPU cores in your
# machine.
make -j2
make install
# Note that this version of lug-nginx-module not allow to set `lua_load_resty_core off;` any more.
# So, you have to install `lua-resty-core` and `lua-resty-lrucache` manually as below.
cd lua-resty-core
make install PREFIX=/opt/nginx
cd lua-resty-lrucache
make install PREFIX=/opt/nginx
# add necessary `lua_package_path` directive to `nginx.conf`, in the http context
lua_package_path " /opt/nginx/lib/lua/?.lua;; " ;
Voltar ao sumário
A partir do NGINX 1.9.11, você também pode compilar este módulo como um módulo dinâmico, usando a opção --add-dynamic-module=PATH
em vez de --add-module=PATH
na linha de comando ./configure
acima. E então você pode carregar explicitamente o módulo em seu nginx.conf
por meio da diretiva load_module, por exemplo,
load_module /path/to/modules/ndk_http_module.so; # assuming NDK is built as a dynamic module too
load_module /path/to/modules/ngx_http_lua_module.so;
Voltar ao sumário
Ao construir este módulo via OpenResty ou com o núcleo Nginx, você pode definir as seguintes macros C por meio das opções do compilador C:
NGX_LUA_USE_ASSERT
Quando definido, habilitará asserções na base de código C ngx_lua. Recomendado para depuração ou teste de compilações. Ele pode introduzir alguma (pequena) sobrecarga de tempo de execução quando ativado. Esta macro foi introduzida pela primeira vez na versão v0.9.10
.NGX_LUA_ABORT_AT_PANIC
Quando a VM LuaJIT entra em pânico, ngx_lua instruirá o processo de trabalho nginx atual a encerrar normalmente por padrão. Ao especificar esta macro C, ngx_lua abortará o processo de trabalho nginx atual (que geralmente resulta em um arquivo de dump principal) imediatamente. Esta opção é útil para depurar pânicos de VM. Esta opção foi introduzida pela primeira vez na versão v0.9.8
. Para habilitar uma ou mais dessas macros, basta passar opções extras do compilador C para o script ./configure
do Nginx ou OpenResty. Por exemplo,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
Voltar ao sumário
Voltar ao sumário
A lista de discussão openresty-en é para falantes de inglês.
Voltar ao sumário
A lista de discussão openresty é para falantes de chinês.
Voltar ao sumário
O repositório de código deste projeto está hospedado no GitHub em openresty/lua-nginx-module.
Voltar ao sumário
Envie relatórios de bugs, listas de desejos ou patches até
Voltar ao sumário
Assista ao vídeo do YouTube "Medir corretamente o tempo de execução do código Lua no OpenResty"
A partir da versão v0.5.0rc32
, todas as diretivas de configuração *_by_lua_file
(como content_by_lua_file) suportam o carregamento de arquivos de bytecode brutos LuaJIT 2.0/2.1 diretamente:
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
A opção -bg
pode ser usada para incluir informações de depuração no arquivo de bytecode LuaJIT:
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Consulte a documentação oficial do LuaJIT sobre a opção -b
para obter mais detalhes:
https://luajit.org/running.html#opt_b
Observe que os arquivos de bytecode gerados pelo LuaJIT 2.1 não são compatíveis com o LuaJIT 2.0 e vice-versa. O suporte para bytecode LuaJIT 2.1 foi adicionado pela primeira vez em ngx_lua v0.9.3.
As tentativas de carregar arquivos de bytecode Lua 5.1 padrão em instâncias ngx_lua vinculadas ao LuaJIT 2.0/2.1 (ou vice-versa) resultarão em uma mensagem de erro Nginx como a abaixo:
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
Carregar arquivos de bytecode por meio de primitivas Lua como require
e dofile
deve sempre funcionar conforme o esperado.
Voltar ao sumário
Se você deseja acessar a variável de ambiente do sistema, digamos, foo
, em Lua por meio da API Lua padrão os.getenv, você também deve listar o nome dessa variável de ambiente em seu arquivo nginx.conf
por meio da diretiva env. Por exemplo,
env foo;
Voltar ao sumário
O protocolo HTTP 1.0 não oferece suporte à saída em partes e requer um cabeçalho Content-Length
explícito quando o corpo da resposta não está vazio para oferecer suporte ao keep-alive do HTTP 1.0. Portanto, quando uma solicitação HTTP 1.0 é feita e a diretiva lua_http10_buffering está on
, ngx_lua irá armazenar em buffer a saída das chamadas ngx.say e ngx.print e também adiar o envio de cabeçalhos de resposta até que toda a saída do corpo de resposta seja recebida. Nesse momento, ngx_lua pode calcular o comprimento total do corpo e construir um cabeçalho Content-Length
adequado para retornar ao cliente HTTP 1.0. Entretanto, se o cabeçalho de resposta Content-Length
estiver definido no código Lua em execução, esse buffer será desativado mesmo se a diretiva lua_http10_buffering estiver on
.
Para grandes respostas de saída de streaming, é importante desabilitar a diretiva lua_http10_buffering para minimizar o uso de memória.
Observe que ferramentas comuns de benchmark HTTP, como ab
e http_load
emitem solicitações HTTP 1.0 por padrão. Para forçar curl
a enviar solicitações HTTP 1.0, use a opção -0
.
Voltar ao sumário
Com LuaJIT 2.x, é possível vincular estaticamente o bytecode de módulos Lua puros ao executável Nginx.
Você pode usar o executável luajit
para compilar arquivos do módulo .lua
Lua para arquivos de objeto .o
contendo os dados de bytecode exportados e, em seguida, vincular os arquivos .o
diretamente em sua compilação Nginx.
Abaixo está um exemplo trivial para demonstrar isso. Considere que temos o seguinte arquivo .lua
chamado foo.lua
:
-- foo.lua
local _M = {}
function _M . go ()
print ( " Hello from foo " )
end
return _M
E então compilamos este arquivo .lua
no arquivo foo.o
:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
O que importa aqui é o nome do arquivo .lua
, que determina como você usará este módulo posteriormente na terra Lua. O nome do arquivo foo.o
não importa, exceto a extensão do arquivo .o
(que informa luajit
qual formato de saída é usado). Se você quiser retirar as informações de depuração de Lua do bytecode resultante, basta especificar a opção -b
acima em vez de -bg
.
Então, ao construir o Nginx ou o OpenResty, passe a opção --with-ld-opt="foo.o"
para o script ./configure
:
./configure --with-ld-opt= " /path/to/foo.o " ...
Finalmente, você pode fazer o seguinte em qualquer código Lua executado por ngx_lua:
local foo = require " foo "
foo . go ()
E esse trecho de código não depende mais do arquivo foo.lua
externo porque já foi compilado no executável nginx
.
Se você quiser usar ponto no nome do módulo Lua ao chamar require
, como em
local foo = require " resty.foo "
então você precisa renomear o arquivo foo.lua
para resty_foo.lua
antes de compilá-lo em um arquivo .o
com o utilitário de linha de comando luajit
.
É importante usar exatamente a mesma versão do LuaJIT ao compilar arquivos .lua
para arquivos .o
ao construir nginx + ngx_lua. Isso ocorre porque o formato de bytecode LuaJIT pode ser incompatível entre diferentes versões do LuaJIT. Quando o formato do bytecode for incompatível, você verá um erro de tempo de execução Lua informando que o módulo Lua não foi encontrado.
Quando você tiver vários arquivos .lua
para compilar e vincular, basta especificar seus arquivos .o
ao mesmo tempo no valor da opção --with-ld-opt
. Por exemplo,
./configure --with-ld-opt= " /path/to/foo.o /path/to/bar.o " ...
Se você tiver muitos arquivos .o
, talvez não seja viável nomeá-los todos em um único comando. Neste caso, você pode construir uma biblioteca estática (ou arquivo) para seus arquivos .o
, como em
ar rcus libmyluafiles.a * .o
então você pode vincular o arquivo myluafiles
como um todo ao seu executável nginx:
./configure
--with-ld-opt= " -L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive "
onde /path/to/lib
é o caminho do diretório que contém o arquivo libmyluafiles.a
. Deve-se observar que a opção do vinculador --whole-archive
é necessária aqui porque, caso contrário, nosso arquivo será ignorado porque nenhum símbolo em nosso arquivo é mencionado nas partes principais do executável nginx.
Voltar ao sumário
Para compartilhar dados globalmente entre todas as solicitações tratadas pelo mesmo processo de trabalho Nginx, encapsule os dados compartilhados em um módulo Lua, use o Lua require
embutido para importar o módulo e, em seguida, manipule os dados compartilhados em Lua. Isso funciona porque os módulos Lua necessários são carregados apenas uma vez e todas as corrotinas compartilharão a mesma cópia do módulo (tanto seu código quanto seus dados).
Observe que o uso de variáveis Lua globais é fortemente desencorajado , pois pode levar a condições de corrida inesperadas entre solicitações simultâneas.
Aqui está um pequeno exemplo de compartilhamento de dados dentro de um trabalhador Nginx por meio de um módulo Lua:
-- mydata.lua
local _M = {}
local data = {
dog = 3 ,
cat = 4 ,
pig = 5 ,
}
function _M . get_age ( name )
return data [ name ]
end
return _M
e acessando-o em nginx.conf
:
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
}
O módulo mydata
neste exemplo só será carregado e executado na primeira solicitação para o local /lua
, e todas as solicitações subsequentes para o mesmo processo de trabalho Nginx usarão a instância recarregada do módulo, bem como a mesma cópia dos dados em até que um sinal HUP
seja enviado ao processo mestre Nginx para forçar uma recarga. Esta técnica de compartilhamento de dados é essencial para aplicações Lua de alto desempenho baseadas neste módulo.
Observe que esse compartilhamento de dados ocorre por trabalhador e não por servidor . Ou seja, quando há vários processos de trabalho Nginx em um mestre Nginx, o compartilhamento de dados não pode cruzar a fronteira do processo entre esses trabalhadores.
Geralmente é recomendado compartilhar dados somente leitura dessa forma. Você também pode compartilhar dados alteráveis entre todas as solicitações simultâneas de cada processo de trabalho Nginx, desde que não haja operações de E/S sem bloqueio (incluindo ngx.sleep) no meio de seus cálculos. Contanto que você não devolva o controle ao loop de eventos Nginx e ao agendador de threads leves do ngx_lua (mesmo que implicitamente), nunca poderá haver condições de corrida entre eles. Por esse motivo, tenha sempre muito cuidado ao compartilhar dados alteráveis no nível do trabalhador. Otimizações com erros podem facilmente levar a condições de corrida difíceis de depurar sob carga.
Se for necessário o compartilhamento de dados em todo o servidor, use uma ou mais das seguintes abordagens:
memcached
, redis
, MySQL
ou PostgreSQL
. Os lançamentos oficiais do OpenResty vêm com um conjunto de módulos Nginx complementares e bibliotecas Lua que fornecem interfaces com esses mecanismos de armazenamento de dados.Voltar ao sumário
Voltar ao sumário
O método tcpsock:connect pode indicar success
apesar de falhas de conexão, como erros Connection Refused
.
No entanto, tentativas posteriores de manipular o objeto cosocket falharão e retornarão a mensagem de status de erro real gerada pela operação de conexão com falha.
Esse problema ocorre devido a limitações no modelo de eventos Nginx e parece afetar apenas o Mac OS X.
Voltar ao sumário
dofile
e require
de Lua são atualmente implementados como funções C em LuaJIT 2.0/2.1, se o arquivo Lua sendo carregado por dofile
ou require
invoca ngx.location.capture*, ngx.exec, ngx.exit ou outras funções de API que exigem produção no escopo de nível superior do arquivo Lua, então o erro Lua "tentativa de rendimento através do limite da chamada C" será gerado. Para evitar isso, coloque essas chamadas que exigem rendimento em suas próprias funções Lua no arquivo Lua, em vez do escopo de nível superior do arquivo.Voltar ao sumário
Deve-se ter cuidado ao importar módulos, devendo ser utilizado este formulário:
local xxx = require ( ' xxx ' )
em vez do antigo formato obsoleto:
require ( ' xxx ' )
Aqui está o motivo: por design, o ambiente global tem exatamente o mesmo tempo de vida que o manipulador de solicitação Nginx associado a ele. Cada manipulador de solicitações possui seu próprio conjunto de variáveis globais Lua e essa é a ideia do isolamento de solicitações. O módulo Lua é realmente carregado pelo primeiro manipulador de solicitação Nginx e é armazenado em cache pelo require()
integrado na tabela package.loaded
para referência posterior, e o module()
integrado usado por alguns módulos Lua tem o efeito colateral de definir uma variável global para a tabela do módulo carregado. Mas esta variável global será limpa no final do manipulador de solicitações, e cada manipulador de solicitações subsequente terá seu próprio ambiente global (limpo). Portanto, obteremos uma exceção Lua para acessar o valor nil
.
O uso de variáveis globais Lua é geralmente desaconselhável no contexto ngx_lua como:
Portanto, é altamente recomendável sempre declará-los dentro de um escopo local apropriado.
-- Avoid
foo = 123
-- Recommended
local foo = 123
-- Avoid
function foo () return 123 end
-- Recommended
local function foo () return 123 end
Para encontrar todas as instâncias de variáveis globais Lua em seu código Lua, execute a ferramenta lua-releng em todos os arquivos de origem .lua
:
$ lua-releng
Checking use of Lua global variables in file lib/foo/bar.lua ...
1 [1489] SETGLOBAL 7 -1 ; contains
55 [1506] GETGLOBAL 7 -3 ; setvar
3 [1545] GETGLOBAL 3 -4 ; varexpand
A saída diz que a linha 1489 do arquivo lib/foo/bar.lua
grava em uma variável global chamada contains
, a linha 1506 lê a variável global setvar
e a linha 1545 lê o varexpand
global .
Esta ferramenta garantirá que as variáveis locais nas funções do módulo Lua sejam todas declaradas com a palavra-chave local
, caso contrário, uma exceção de tempo de execução será lançada. Evita condições de corrida indesejáveis ao acessar tais variáveis. Consulte Compartilhamento de dados em um Nginx Worker para saber os motivos por trás disso.
Voltar ao sumário
As diretivas ngx.location.capture e ngx.location.capture_multi não podem capturar locais que incluem as diretivas add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest ou echo_subrequest_async.
location /foo {
content_by_lua_block {
res = ngx.location.capture( "/bar" )
}
}
location /bar {
echo_location /blah;
}
location /blah {
echo "Success!" ;
}
$ curl -i http://example.com/foo
não funcionará como esperado.
Voltar ao sumário
Devido a limitações internas no núcleo Nginx, a API cosocket está desabilitada nos seguintes contextos: set_by_lua*, log_by_lua*, header_filter_by_lua* e body_filter_by_lua.
Os cosockets atualmente também estão desabilitados nos contextos das diretivas init_by_lua* e init_worker_by_lua* mas podemos adicionar suporte para esses contextos no futuro porque não há limitação no núcleo Nginx (ou a limitação pode ser contornada).
Existe uma solução alternativa, entretanto, quando o contexto original não precisa esperar pelos resultados do cosocket. Ou seja, criar um timer de atraso zero por meio da API ngx.timer.at e fazer o cosocket resulta no manipulador do timer, que é executado de forma assíncrona em relação ao contexto original que cria o timer.
Voltar ao sumário
NOTA Após a versão v0.9.17
, essa armadilha pode ser evitada usando as diretivas de configuração *_by_lua_block {}
.
Sequências PCRE como d
, s
ou w
, requerem atenção especial porque em literais de string, o caractere de barra invertida, , é removido pelo analisador de linguagem Lua e pelo analisador de arquivo de configuração Nginx antes do processamento, se não estiver dentro de um
*_by_lua_block {}
diretiva. Portanto, o seguinte trecho não funcionará conforme o esperado:
# nginx.conf
? location /test {
? content_by_lua '
? local regex = "d+" -- THIS IS WRONG OUTSIDE OF A *_by_lua_block DIRECTIVE
? local m = ngx.re.match("hello, 1234", regex)
? if m then ngx.say(m[0]) else ngx.say("not matched!") end
? ' ;
? }
# evaluates to "not matched!"
Para evitar isso, escape duas vezes da barra invertida:
# nginx.conf
location /test {
content_by_lua '
local regex = "\\d+"
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Aqui, \\d+
é reduzido para \d+
pelo analisador do arquivo de configuração Nginx e é ainda reduzido para d+
pelo analisador de linguagem Lua antes da execução.
Alternativamente, o padrão regex pode ser apresentado como uma string Lua literal entre colchetes longos, colocando-o entre "colchetes longos", [[...]]
, caso em que as barras invertidas devem ser escapadas apenas uma vez para o analisador do arquivo de configuração Nginx.
# nginx.conf
location /test {
content_by_lua '
local regex = [[\d+]]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Aqui, [[\d+]]
é reduzido para [[d+]]
pelo analisador do arquivo de configuração Nginx e é processado corretamente.
Observe que um from do colchete longo, [=[...]=]
, pode ser necessário se o padrão regex contiver [...]
sequências. O formulário [=[...]=]
pode ser usado como formulário padrão, se desejado.
# nginx.conf
location /test {
content_by_lua '
local regex = [=[[0-9]+]=]
local m = ngx.re.match("hello, 1234", regex)
if m then ngx.say(m[0]) else ngx.say("not matched!") end
' ;
}
# evaluates to "1234"
Uma abordagem alternativa para escapar de sequências PCRE é garantir que o código Lua seja colocado em arquivos de script externos e executado usando as várias diretivas *_by_lua_file
. Com esta abordagem, as barras invertidas são removidas apenas pelo analisador da linguagem Lua e, portanto, só precisam ser escapadas uma vez cada.
-- test.lua
local regex = " \ d+ "
local m = ngx . re . match ( " hello, 1234 " , regex )
if m then ngx . say ( m [ 0 ]) else ngx . say ( " not matched! " ) end
-- evaluates to "1234"
Em arquivos de script externos, as sequências PCRE apresentadas como literais de string Lua entre colchetes longos não requerem modificação.
-- test.lua
local regex = [[ d+ ]]
local m = ngx . re . match ( " hello, 1234 " , regex )
if m then ngx . say ( m [ 0 ]) else ngx . say ( " not matched! " ) end
-- evaluates to "1234"
Conforme observado anteriormente, as sequências PCRE apresentadas nas diretivas *_by_lua_block {}
(disponíveis após a versão v0.9.17
) não requerem modificação.
# nginx.conf
location /test {
content_by_lua_block {
local regex = [[d+]]
local m = ngx.re.match( "hello, 1234" , regex)
if m then ngx.say(m[0]) else ngx.say( "not matched!" ) end
}
}
# evaluates to "1234"
NOTA É recomendado usar by_lua_file
quando o código Lua for muito longo.
Voltar ao sumário
A mistura de SSI com ngx_lua na mesma solicitação Nginx não é suportada. Basta usar exclusivamente ngx_lua. Tudo o que você pode fazer com SSI pode ser feito sobre ngx_lua de qualquer maneira e pode ser mais eficiente ao usar ngx_lua.
Voltar ao sumário
Certas APIs Lua fornecidas por ngx_lua ainda não funcionam no modo SPDY do Nginx: ngx.location.capture, ngx.location.capture_multi e ngx.req.socket.
Voltar ao sumário
O Nginx pode encerrar uma solicitação antecipadamente com (pelo menos):
Isso significa que as fases normalmente executadas são ignoradas, como a fase de reescrita ou de acesso. Isso também significa que as fases posteriores executadas independentemente, por exemplo, log_by_lua, não terão acesso às informações normalmente definidas nessas fases.
Voltar ao sumário
bsdrecv
.ngx_hash_t
para otimizar o processo de pesquisa de cabeçalho integrado para ngx.req.set_header e etc.ignore_resp_headers
, ignore_resp_body
e ignore_resp
aos métodos ngx.location.capture e ngx.location.capture_multi, para permitir o ajuste de micro desempenho no lado do usuário.stat
semelhante ao mod_lua.Voltar ao sumário
As alterações feitas em cada versão deste módulo estão listadas nos logs de alterações do pacote OpenResty:
https://openresty.org/#Changes
Voltar ao sumário
As seguintes dependências são necessárias para executar o conjunto de testes:
Versão Nginx >= 1.4.2
Módulos Perl:
Módulos Nginx:
A ordem em que esses módulos são adicionados durante a configuração é importante porque a posição de qualquer módulo de filtro na cadeia de filtragem determina a saída final, por exemplo. A ordem de adição correta é mostrada acima.
Bibliotecas Lua de terceiros:
Aplicações: