ngx_http_lua_module: integra el poder de Lua en los servidores HTTP Nginx.
Este módulo es un componente central de OpenResty. Si estás usando este módulo, entonces básicamente estás usando OpenResty :)
Este módulo no se distribuye con la fuente Nginx. Consulte las instrucciones de instalación.
Listo para la producción.
Este documento describe ngx_lua v0.10.25, que se lanzó el 19 de junio de 2023.
Vídeo de YouTube "Hola mundo, ejemplo HTTP con OpenResty/Lua"
Vídeo de YouTube "Escriba sus propios módulos Lua en aplicaciones OpenResty/Nginx"
Vídeo de YouTube "Demostración de la utilidad de línea de comandos resty de OpenResty"
Vídeo de YouTube "Mida correctamente el tiempo de ejecución del código Lua en OpenResty"
Vídeo de YouTube "Precompila módulos Lua en LuaJIT Bytecode para acelerar el inicio de OpenResty"
Le invitamos a suscribirse a nuestro canal oficial de YouTube, OpenResty.
Volver al índice
# 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
}
}
Volver al índice
Este módulo integra LuaJIT 2.0/2.1 en Nginx. Es un componente central de OpenResty. Si está utilizando este módulo, básicamente está utilizando OpenResty.
Desde la versión v0.10.16
de este módulo, el intérprete Lua estándar (también conocido como "PUC-Rio Lua") ya no es compatible. Este documento utiliza indistintamente los términos "Lua" y "LuaJIT" para referirse al intérprete de LuaJIT.
Al aprovechar las subsolicitudes de Nginx, este módulo permite la integración de los potentes subprocesos de Lua (conocidos como "corrutinas" de Lua) en el modelo de eventos de Nginx.
A diferencia de mod_lua de Apache y mod_magnet de Lighttpd, el código Lua ejecutado usando este módulo puede ser 100% sin bloqueo en el tráfico de red siempre que la API Nginx para Lua proporcionada por este módulo se use para manejar solicitudes a servicios ascendentes como MySQL, PostgreSQL, Memcached. , Redis o servicios web HTTP ascendentes.
Con este módulo se pueden utilizar al menos las siguientes bibliotecas Lua y módulos Nginx:
Casi cualquier módulo Nginx se puede usar con este módulo ngx_lua mediante ngx.location.capture o ngx.location.capture_multi, pero se recomienda usar esas bibliotecas lua-resty-*
en lugar de crear subsolicitudes para acceder a los módulos ascendentes de Nginx porque El primero suele ser mucho más flexible y eficiente en memoria.
El intérprete de Lua (también conocido como "estado de Lua" o "instancia de VM LuaJIT") se comparte entre todas las solicitudes en un único proceso de trabajo de Nginx para minimizar el uso de memoria. Los contextos de solicitud se segregan mediante corrutinas ligeras de Lua.
Los módulos Lua cargados persisten en el nivel del proceso de trabajo de Nginx, lo que genera una pequeña huella de memoria en Lua incluso cuando se encuentran bajo cargas pesadas.
Este módulo está conectado al subsistema "http" de Nginx, por lo que solo puede hablar protocolos de comunicación descendentes en la familia HTTP (HTTP 0.9/1.0/1.1/2.0, WebSockets, etc...). Si desea realizar comunicaciones TCP genéricas con los clientes posteriores, debe utilizar el módulo ngx_stream_lua, que ofrece una API Lua compatible.
Volver al índice
Sólo por nombrar algunos:
Las posibilidades son ilimitadas ya que el módulo permite reunir varios elementos dentro de Nginx así como exponer el poder del lenguaje Lua al usuario. El módulo proporciona total flexibilidad de secuencias de comandos al tiempo que ofrece niveles de rendimiento comparables con los programas nativos en lenguaje C tanto en términos de tiempo de CPU como de uso de memoria gracias a LuaJIT 2.x.
Otras implementaciones de lenguajes de script suelen tener dificultades para igualar este nivel de rendimiento.
Volver al índice
La última versión de este módulo es compatible con las siguientes versiones de Nginx:
No se admiten núcleos Nginx anteriores a 1.6.0 (exclusivo).
Volver al índice
Se recomienda encarecidamente utilizar las versiones de OpenResty que incluyen Nginx, ngx_lua (este módulo), LuaJIT, así como otros potentes módulos complementarios de Nginx y bibliotecas de Lua.
Se desaconseja crear este módulo con Nginx usted mismo, ya que es complicado configurarlo exactamente correctamente.
Tenga en cuenta que las versiones oficiales de Nginx, LuaJIT y OpenSSL tienen varias limitaciones y errores de larga data que pueden provocar que algunas de las funciones de este módulo se deshabiliten, no funcionen correctamente o se ejecuten más lentamente. Se recomiendan las versiones oficiales de OpenResty porque incluyen la bifurcación LuaJIT 2.1 optimizada de OpenResty y los parches Nginx/OpenSSL.
Alternativamente, ngx_lua se puede compilar manualmente en Nginx:
Construya la fuente con 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;; " ;
Volver al índice
A partir de NGINX 1.9.11, también puede compilar este módulo como un módulo dinámico, utilizando la opción --add-dynamic-module=PATH
en lugar de --add-module=PATH
en la línea de comando ./configure
anterior. Y luego puedes cargar explícitamente el módulo en tu nginx.conf
a través de la directiva load_module, por ejemplo,
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;
Volver al índice
Mientras construye este módulo a través de OpenResty o con el núcleo de Nginx, puede definir las siguientes macros de C a través de las opciones del compilador de C:
NGX_LUA_USE_ASSERT
Cuando se define, habilitará aserciones en el código base de ngx_lua C. Recomendado para depurar o probar compilaciones. Puede introducir cierta sobrecarga de tiempo de ejecución (pequeña) cuando está habilitado. Esta macro se introdujo por primera vez en la versión v0.9.10
.NGX_LUA_ABORT_AT_PANIC
Cuando la máquina virtual LuaJIT entra en pánico, ngx_lua indicará al proceso de trabajo nginx actual que se cierre correctamente de forma predeterminada. Al especificar esta macro de C, ngx_lua abortará el proceso de trabajo nginx actual (que generalmente resulta en un archivo de volcado de núcleo) inmediatamente. Esta opción es útil para depurar pánicos de VM. Esta opción se introdujo por primera vez en la versión v0.9.8
. Para habilitar una o más de estas macros, simplemente pase opciones adicionales del compilador de C al script ./configure
de Nginx u OpenResty. Por ejemplo,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
Volver al índice
Volver al índice
La lista de correo de openresty-en es para angloparlantes.
Volver al índice
La lista de correo de openresty es para hablantes de chino.
Volver al índice
El repositorio de código de este proyecto está alojado en GitHub en openresty/lua-nginx-module.
Volver al índice
Envíe informes de errores, listas de deseos o parches antes de
Volver al índice
Mire el vídeo de YouTube "Mida correctamente el tiempo de ejecución del código Lua en OpenResty"
A partir de la versión v0.5.0rc32
, todas las directivas de configuración *_by_lua_file
(como content_by_lua_file) admiten la carga de archivos de código de bytes sin formato LuaJIT 2.0/2.1 directamente:
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
La opción -bg
se puede utilizar para incluir información de depuración en el archivo de código de bytes LuaJIT:
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Consulte la documentación oficial de LuaJIT sobre la opción -b
para obtener más detalles:
https://luajit.org/running.html#opt_b
Tenga en cuenta que los archivos de código de bytes generados por LuaJIT 2.1 no son compatibles con LuaJIT 2.0 y viceversa. La compatibilidad con el código de bytes LuaJIT 2.1 se agregó por primera vez en ngx_lua v0.9.3.
Los intentos de cargar archivos de código de bytes estándar de Lua 5.1 en instancias ngx_lua vinculadas a LuaJIT 2.0/2.1 (o viceversa) generarán un mensaje de error de Nginx como el siguiente:
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
La carga de archivos de código de bytes a través de las primitivas de Lua como require
y dofile
siempre debería funcionar como se esperaba.
Volver al índice
Si desea acceder a la variable de entorno del sistema, digamos, foo
, en Lua a través de la API estándar de Lua os.getenv, entonces también debe incluir el nombre de esta variable de entorno en su archivo nginx.conf
a través de la directiva env. Por ejemplo,
env foo;
Volver al índice
El protocolo HTTP 1.0 no admite salida fragmentada y requiere un encabezado Content-Length
explícito cuando el cuerpo de la respuesta no está vacío para admitir el mantenimiento de HTTP 1.0. Entonces, cuando se realiza una solicitud HTTP 1.0 y la directiva lua_http10_buffering está on
, ngx_lua almacenará en búfer la salida de las llamadas ngx.say y ngx.print y también pospondrá el envío de encabezados de respuesta hasta que se reciba toda la salida del cuerpo de la respuesta. En ese momento, ngx_lua puede calcular la longitud total del cuerpo y construir un encabezado Content-Length
adecuado para regresar al cliente HTTP 1.0. Sin embargo, si el encabezado de respuesta Content-Length
está configurado en el código Lua en ejecución, este almacenamiento en búfer se deshabilitará incluso si la directiva lua_http10_buffering está on
.
Para respuestas de salida de transmisión de gran tamaño, es importante deshabilitar la directiva lua_http10_buffering para minimizar el uso de memoria.
Tenga en cuenta que las herramientas de referencia HTTP comunes, como ab
y http_load
emiten solicitudes HTTP 1.0 de forma predeterminada. Para forzar curl
a enviar solicitudes HTTP 1.0, utilice la opción -0
.
Volver al índice
Con LuaJIT 2.x, es posible vincular estáticamente el código de bytes de módulos Lua puros al ejecutable de Nginx.
Puede usar el ejecutable luajit
para compilar archivos del módulo .lua
Lua en archivos de objetos .o
que contienen los datos del código de bytes exportados y luego vincular los archivos .o
directamente en su compilación de Nginx.
A continuación se muestra un ejemplo trivial para demostrar esto. Considere que tenemos el siguiente archivo .lua
llamado foo.lua
:
-- foo.lua
local _M = {}
function _M . go ()
print ( " Hello from foo " )
end
return _M
Y luego compilamos este archivo .lua
en el archivo foo.o
:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
Lo que importa aquí es el nombre del archivo .lua
, que determina cómo utilizará este módulo más adelante en Lua. El nombre del archivo foo.o
no importa en absoluto excepto la extensión del archivo .o
(que le indica luajit
qué formato de salida se utiliza). Si desea eliminar la información de depuración de Lua del código de bytes resultante, puede especificar la opción -b
anterior en lugar de -bg
.
Luego, cuando construyas Nginx u OpenResty, pasa la opción --with-ld-opt="foo.o"
al script ./configure
:
./configure --with-ld-opt= " /path/to/foo.o " ...
Finalmente, puedes hacer lo siguiente en cualquier código Lua ejecutado por ngx_lua:
local foo = require " foo "
foo . go ()
Y este fragmento de código ya no depende del archivo externo foo.lua
porque ya ha sido compilado en el ejecutable nginx
.
Si desea utilizar un punto en el nombre del módulo Lua al llamar require
, como en
local foo = require " resty.foo "
luego debe cambiar el nombre del archivo foo.lua
a resty_foo.lua
antes de compilarlo en un archivo .o
con la utilidad de línea de comandos luajit
.
Es importante utilizar exactamente la misma versión de LuaJIT al compilar archivos .lua
en archivos .o
que al compilar nginx + ngx_lua. Esto se debe a que el formato de código de bytes de LuaJIT puede ser incompatible entre diferentes versiones de LuaJIT. Cuando el formato del código de bytes es incompatible, verá un error de tiempo de ejecución de Lua que indica que no se encuentra el módulo Lua.
Cuando tenga varios archivos .lua
para compilar y vincular, simplemente especifique sus archivos .o
al mismo tiempo en el valor de la opción --with-ld-opt
. Por ejemplo,
./configure --with-ld-opt= " /path/to/foo.o /path/to/bar.o " ...
Si tiene demasiados archivos .o
, es posible que no sea posible nombrarlos a todos en un solo comando. En este caso, puede crear una biblioteca estática (o archivo) para sus archivos .o
, como en
ar rcus libmyluafiles.a * .o
luego puedes vincular el archivo myluafiles
en su totalidad a tu ejecutable nginx:
./configure
--with-ld-opt= " -L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive "
donde /path/to/lib
es la ruta del directorio que contiene el archivo libmyluafiles.a
. Cabe señalar que aquí se requiere la opción del vinculador --whole-archive
porque, de lo contrario, nuestro archivo se omitirá porque no se mencionan símbolos en nuestro archivo en las partes principales del ejecutable de nginx.
Volver al índice
Para compartir datos globalmente entre todas las solicitudes manejadas por el mismo proceso de trabajo de Nginx, encapsule los datos compartidos en un módulo Lua, use el require
integrado de Lua para importar el módulo y luego manipule los datos compartidos en Lua. Esto funciona porque los módulos Lua requeridos se cargan solo una vez y todas las corrutinas compartirán la misma copia del módulo (tanto su código como sus datos).
Tenga en cuenta que se desaconseja encarecidamente el uso de variables globales de Lua, ya que puede generar condiciones de carrera inesperadas entre solicitudes simultáneas.
Aquí hay un pequeño ejemplo sobre cómo compartir datos dentro de un trabajador de Nginx a través de un 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
y luego acceder a él desde nginx.conf
:
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
}
El módulo mydata
en este ejemplo solo se cargará y ejecutará en la primera solicitud a la ubicación /lua
, y todas las solicitudes posteriores al mismo proceso de trabajo de Nginx utilizarán la instancia recargada del módulo, así como la misma copia de los datos en hasta que se envíe una señal HUP
al proceso maestro de Nginx para forzar una recarga. Esta técnica de intercambio de datos es esencial para aplicaciones Lua de alto rendimiento basadas en este módulo.
Tenga en cuenta que este intercambio de datos se realiza por trabajador y no por servidor . Es decir, cuando hay varios procesos de trabajo de Nginx bajo un maestro de Nginx, el intercambio de datos no puede cruzar los límites del proceso entre estos trabajadores.
Generalmente se recomienda compartir datos de solo lectura de esta manera. También puede compartir datos modificables entre todas las solicitudes simultáneas de cada proceso de trabajo de Nginx siempre que no haya operaciones de E/S sin bloqueo (incluido ngx.sleep) en medio de sus cálculos. Mientras no le devuelvas el control al bucle de eventos de Nginx y al programador de subprocesos ligeros de ngx_lua (ni siquiera implícitamente), nunca podrá haber condiciones de carrera en el medio. Por este motivo, tenga siempre mucho cuidado cuando quiera compartir datos modificables a nivel de trabajador. Las optimizaciones con errores pueden conducir fácilmente a condiciones de carrera difíciles de depurar bajo carga.
Si es necesario compartir datos en todo el servidor, utilice uno o más de los siguientes enfoques:
memcached
, redis
, MySQL
o PostgreSQL
. Los lanzamientos oficiales de OpenResty vienen con un conjunto de módulos Nginx complementarios y bibliotecas Lua que proporcionan interfaces con estos mecanismos de almacenamiento de datos.Volver al índice
Volver al índice
El método tcpsock:connect puede indicar success
a pesar de fallas de conexión, como errores Connection Refused
.
Sin embargo, los intentos posteriores de manipular el objeto cosocket fallarán y devolverán el mensaje de estado de error real generado por la operación de conexión fallida.
Este problema se debe a limitaciones en el modelo de eventos de Nginx y solo parece afectar a Mac OS X.
Volver al índice
dofile
de Lua y las funciones integradas require
se implementan actualmente como funciones C en LuaJIT 2.0/2.1, si el archivo Lua que se carga mediante dofile
o require
invoca ngx.location.capture*, ngx.exec, ngx.exit u otras funciones API que requieren rendimiento en el alcance de nivel superior del archivo Lua, se generará el error de Lua "intento de ceder el paso a través del límite de llamada C". Para evitar esto, coloque estas llamadas que requieren ceder en sus propias funciones Lua en el archivo Lua en lugar del alcance de nivel superior del archivo.Volver al índice
Se debe tener cuidado al importar módulos y se debe utilizar este formulario:
local xxx = require ( ' xxx ' )
en lugar de la antigua forma obsoleta:
require ( ' xxx ' )
Esta es la razón: por diseño, el entorno global tiene exactamente la misma vida útil que el controlador de solicitudes Nginx asociado a él. Cada controlador de solicitudes tiene su propio conjunto de variables globales de Lua y esa es la idea del aislamiento de solicitudes. El módulo Lua en realidad lo carga el primer controlador de solicitudes de Nginx y se almacena en caché mediante require()
integrado en la tabla package.loaded
para referencia posterior, y el module()
incorporado utilizado por algunos módulos Lua tiene el efecto secundario de configurar una variable global a la tabla del módulo cargado. Pero esta variable global se borrará al final del controlador de solicitudes, y cada controlador de solicitudes posterior tendrá su propio entorno global (limpio). Entonces se obtendrá la excepción de Lua al acceder al valor nil
.
El uso de variables globales de Lua generalmente no es aconsejable en el contexto ngx_lua como:
Por lo tanto, se recomienda encarecidamente declararlo siempre dentro de un ámbito local apropiado.
-- Avoid
foo = 123
-- Recommended
local foo = 123
-- Avoid
function foo () return 123 end
-- Recommended
local function foo () return 123 end
Para encontrar todas las instancias de variables globales de Lua en su código Lua, ejecute la herramienta lua-releng en todos los archivos fuente .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
El resultado dice que la línea 1489 del archivo lib/foo/bar.lua
escribe en una variable global llamada contains
, la línea 1506 lee de la variable global setvar
y la línea 1545 lee el varexpand
global.
Esta herramienta garantizará que todas las variables locales en las funciones del módulo Lua se declaren con la palabra clave local
; de lo contrario, se generará una excepción de tiempo de ejecución. Previene condiciones de carrera no deseadas al acceder a dichas variables. Consulte Intercambio de datos dentro de un trabajador Nginx para conocer los motivos detrás de esto.
Volver al índice
Las directivas ngx.location.capture y ngx.location.capture_multi no pueden capturar ubicaciones que incluyan las directivas add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest o 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
no funcionará como se esperaba.
Volver al índice
Debido a limitaciones internas en el núcleo de Nginx, la API cosocket está deshabilitada en los siguientes contextos: set_by_lua*, log_by_lua*, header_filter_by_lua* y body_filter_by_lua.
Actualmente, los cosockets también están deshabilitados en los contextos directivos init_by_lua* e init_worker_by_lua*, pero podemos agregar soporte para estos contextos en el futuro porque no hay limitación en el núcleo de Nginx (o la limitación podría solucionarse).
Sin embargo, existe una solución alternativa cuando el contexto original no necesita esperar los resultados del cosocket. Es decir, crear un temporizador de retardo cero a través de la API ngx.timer.at y hacer que el cosocket dé como resultado el controlador del temporizador, que se ejecuta de forma asíncrona en cuanto al contexto original que crea el temporizador.
Volver al índice
NOTA Después del lanzamiento v0.9.17
, este problema se puede evitar utilizando las directivas de configuración *_by_lua_block {}
.
Las secuencias PCRE como d
, s
o w
, requieren especial atención porque en las cadenas literales, el carácter de barra invertida, , es eliminado tanto por el analizador del lenguaje Lua como por el analizador del archivo de configuración de Nginx antes de procesarlo, si no está dentro de un
*_by_lua_block {}
. Por lo tanto, el siguiente fragmento no funcionará como se esperaba:
# 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 esto, escape dos veces la 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"
Aquí, \\d+
se reduce a \d+
mediante el analizador de archivos de configuración de Nginx y el analizador de lenguaje Lua lo reduce aún más a d+
antes de ejecutarlo.
Alternativamente, el patrón de expresiones regulares se puede presentar como un literal de cadena Lua con corchetes largos encerrándolo entre "corchetes largos", [[...]]
, en cuyo caso las barras invertidas solo deben escaparse una vez para el analizador de archivos de configuración de 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"
Aquí, [[\d+]]
se reduce a [[d+]]
mediante el analizador de archivos de configuración de Nginx y esto se procesa correctamente.
Tenga en cuenta que es posible que se requiera una forma más larga del corchete largo, [=[...]=]
si el patrón de expresiones regulares contiene [...]
secuencias. El formulario [=[...]=]
se puede utilizar como formulario predeterminado si se desea.
# 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"
Un enfoque alternativo para escapar de secuencias PCRE es garantizar que el código Lua se coloque en archivos de script externos y se ejecute utilizando las diversas directivas *_by_lua_file
. Con este enfoque, el analizador de lenguaje Lua solo elimina las barras invertidas y, por lo tanto, solo es necesario escapar una vez cada una.
-- 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"
Dentro de los archivos de script externos, las secuencias PCRE presentadas como literales de cadena Lua entre corchetes largos no requieren modificación.
-- 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"
Como se señaló anteriormente, las secuencias PCRE presentadas dentro de las directivas *_by_lua_block {}
(disponibles después de la versión v0.9.17
) no requieren modificación.
# 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 Se recomienda utilizar by_lua_file
cuando el código Lua sea muy largo.
Volver al índice
No se admite en absoluto mezclar SSI con ngx_lua en la misma solicitud de Nginx. Simplemente use ngx_lua exclusivamente. Todo lo que puede hacer con SSI se puede hacer encima de ngx_lua de todos modos y puede ser más eficiente cuando se usa ngx_lua.
Volver al índice
Ciertas API de Lua proporcionadas por ngx_lua aún no funcionan en el modo SPDY de Nginx: ngx.location.capture, ngx.location.capture_multi y ngx.req.socket.
Volver al índice
Nginx puede cancelar una solicitud anticipadamente con (al menos):
Esto significa que se omiten fases que normalmente se ejecutan, como la fase de reescritura o acceso. Esto también significa que las fases posteriores que se ejecutan independientemente, por ejemplo, log_by_lua, no tendrán acceso a la información que normalmente se establece en esas fases.
Volver al índice
bsdrecv
.ngx_hash_t
para optimizar el proceso de búsqueda de encabezado integrado para ngx.req.set_header, etc.ignore_resp_headers
, ignore_resp_body
e ignore_resp
a los métodos ngx.location.capture y ngx.location.capture_multi, para permitir el microajuste del rendimiento en el lado del usuario.stat
similar a mod_lua.Volver al índice
Los cambios realizados en cada versión de este módulo se enumeran en los registros de cambios del paquete OpenResty:
https://openresty.org/#Changes
Volver al índice
Se requieren las siguientes dependencias para ejecutar el conjunto de pruebas:
Versión de Nginx >= 1.4.2
Módulos Perl:
Módulos Nginx:
El orden en el que se agregan estos módulos durante la configuración es importante porque la posición de cualquier módulo de filtro en la cadena de filtrado determina el resultado final, por ejemplo. El orden de adición correcto se muestra arriba.
Bibliotecas Lua de terceros:
Aplicaciones: