ngx_http_lua_module - Intégrez la puissance de Lua dans les serveurs HTTP Nginx.
Ce module est un composant essentiel d'OpenResty. Si vous utilisez ce module, alors vous utilisez essentiellement OpenResty :)
Ce module n'est pas distribué avec le source Nginx. Voir les instructions d'installation.
Production prête.
Ce document décrit ngx_lua v0.10.25, publié le 19 juin 2023.
Vidéo YouTube « Exemple HTTP Hello World avec OpenResty/Lua »
Vidéo YouTube « Écrivez vos propres modules Lua dans les applications OpenResty/Nginx »
Vidéo YouTube "Démo de l'utilitaire de ligne de commande resty d'OpenResty"
Vidéo YouTube "Mesurer correctement le temps d'exécution du code Lua dans OpenResty"
Vidéo YouTube « Précompiler les modules Lua dans le bytecode LuaJIT pour accélérer le démarrage d'OpenResty »
Vous êtes invités à vous abonner à notre chaîne YouTube officielle, OpenResty.
Retour à la table des matières
# 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
}
}
Retour à la table des matières
Ce module intègre LuaJIT 2.0/2.1 dans Nginx. C'est un composant essentiel d'OpenResty. Si vous utilisez ce module, vous utilisez essentiellement OpenResty.
Depuis la version v0.10.16
de ce module, l'interpréteur Lua standard (également connu sous le nom de "PUC-Rio Lua") n'est plus supporté. Ce document utilise de manière interchangeable les termes « Lua » et « LuaJIT » pour désigner l'interpréteur LuaJIT.
En exploitant les sous-requêtes de Nginx, ce module permet l'intégration des puissants threads Lua (appelés « coroutines » Lua) dans le modèle d'événement Nginx.
Contrairement à mod_lua d'Apache et mod_magnet de Lighttpd, le code Lua exécuté à l'aide de ce module peut être 100 % non bloquant sur le trafic réseau tant que l'API Nginx pour Lua fournie par ce module est utilisée pour gérer les requêtes adressées aux services en amont tels que MySQL, PostgreSQL, Memcached. , Redis ou des services Web HTTP en amont.
Au moins les bibliothèques Lua et modules Nginx suivants peuvent être utilisés avec ce module :
Presque tous les modules Nginx peuvent être utilisés avec ce module ngx_lua au moyen de ngx.location.capture ou ngx.location.capture_multi mais il est recommandé d'utiliser ces bibliothèques lua-resty-*
au lieu de créer des sous-requêtes pour accéder aux modules en amont de Nginx car le Le premier est généralement beaucoup plus flexible et économe en mémoire.
L'interpréteur Lua (également connu sous le nom de « Lua State » ou « LuaJIT VM instance ») est partagé entre toutes les requêtes d'un seul processus de travail Nginx afin de minimiser l'utilisation de la mémoire. Les contextes de requête sont séparés à l'aide de coroutines Lua légères.
Les modules Lua chargés persistent au niveau du processus de travail Nginx, ce qui entraîne une faible empreinte mémoire dans Lua, même sous de lourdes charges.
Ce module est branché sur le sous-système "http" de Nginx et ne peut donc parler que des protocoles de communication en aval de la famille HTTP (HTTP 0.9/1.0/1.1/2.0, WebSockets, etc...). Si vous souhaitez effectuer des communications TCP génériques avec les clients en aval, vous devez plutôt utiliser le module ngx_stream_lua, qui propose une API Lua compatible.
Retour à la table des matières
Pour n'en nommer que quelques-uns :
Les possibilités sont illimitées puisque le module permet de rassembler divers éléments au sein de Nginx ainsi que d'exposer la puissance du langage Lua à l'utilisateur. Le module offre toute la flexibilité du scripting tout en offrant des niveaux de performances comparables aux programmes natifs en langage C tant en termes de temps CPU que d'empreinte mémoire grâce à LuaJIT 2.x.
Les autres implémentations de langages de script ont généralement du mal à atteindre ce niveau de performances.
Retour à la table des matières
La dernière version de ce module est compatible avec les versions suivantes de Nginx :
Les cœurs Nginx antérieurs à 1.6.0 (exclusif) ne sont pas pris en charge.
Retour à la table des matières
Il est fortement recommandé d'utiliser les versions d'OpenResty qui regroupent Nginx, ngx_lua (ce module), LuaJIT, ainsi que d'autres modules Nginx compagnons puissants et bibliothèques Lua.
Il est déconseillé de construire vous-même ce module avec Nginx car il est difficile à configurer correctement.
Notez que les versions officielles de Nginx, LuaJIT et OpenSSL présentent diverses limitations et bogues de longue date qui peuvent entraîner la désactivation de certaines fonctionnalités de ce module, un dysfonctionnement ou un fonctionnement plus lent. Les versions officielles d'OpenResty sont recommandées car elles regroupent le fork LuaJIT 2.1 optimisé d'OpenResty et les correctifs Nginx/OpenSSL.
Alternativement, ngx_lua peut être compilé manuellement dans Nginx :
Construisez la source avec ce module :
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;; " ;
Retour à la table des matières
À partir de NGINX 1.9.11, vous pouvez également compiler ce module en tant que module dynamique, en utilisant l'option --add-dynamic-module=PATH
au lieu de --add-module=PATH
sur la ligne de commande ./configure
ci-dessus. Et puis vous pouvez charger explicitement le module dans votre nginx.conf
via la directive load_module, par exemple,
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;
Retour à la table des matières
Lors de la construction de ce module via OpenResty ou avec le noyau Nginx, vous pouvez définir les macros C suivantes via les options du compilateur C :
NGX_LUA_USE_ASSERT
Une fois défini, activera les assertions dans la base de code ngx_lua C. Recommandé pour le débogage ou le test des builds. Il peut introduire une (petite) surcharge d’exécution lorsqu’il est activé. Cette macro a été introduite pour la première fois dans la version v0.9.10
.NGX_LUA_ABORT_AT_PANIC
Lorsque la machine virtuelle LuaJIT panique, ngx_lua demandera au processus de travail nginx actuel de se fermer correctement par défaut. En spécifiant cette macro C, ngx_lua abandonnera immédiatement le processus de travail nginx actuel (ce qui aboutit généralement à un fichier de vidage de mémoire). Cette option est utile pour déboguer les paniques de VM. Cette option a été introduite pour la première fois dans la version v0.9.8
. Pour activer une ou plusieurs de ces macros, transmettez simplement les options supplémentaires du compilateur C au script ./configure
de Nginx ou d'OpenResty. Par exemple,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
Retour à la table des matières
Retour à la table des matières
La liste de diffusion openresty-en est destinée aux anglophones.
Retour à la table des matières
La liste de diffusion openresty est destinée aux personnes parlant chinois.
Retour à la table des matières
Le référentiel de code de ce projet est hébergé sur GitHub à openresty/lua-nginx-module.
Retour à la table des matières
Veuillez soumettre des rapports de bogues, des listes de souhaits ou des correctifs par
Retour à la table des matières
Regardez la vidéo YouTube « Mesurer correctement le temps d'exécution du code Lua dans OpenResty »
À partir de la version v0.5.0rc32
, toutes les directives de configuration *_by_lua_file
(telles que content_by_lua_file) prennent en charge le chargement direct des fichiers de bytecode bruts LuaJIT 2.0/2.1 :
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
L'option -bg
peut être utilisée pour inclure des informations de débogage dans le fichier de bytecode LuaJIT :
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Veuillez vous référer à la documentation officielle de LuaJIT sur l'option -b
pour plus de détails :
https://luajit.org/running.html#opt_b
Notez que les fichiers de bytecode générés par LuaJIT 2.1 ne sont pas compatibles avec LuaJIT 2.0, et vice versa. La prise en charge du bytecode LuaJIT 2.1 a été ajoutée pour la première fois dans ngx_lua v0.9.3.
Les tentatives de chargement de fichiers de bytecode Lua 5.1 standard dans des instances ngx_lua liées à LuaJIT 2.0/2.1 (ou vice versa) entraîneront un message d'erreur Nginx tel que celui ci-dessous :
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
Le chargement de fichiers de bytecode via les primitives Lua comme require
et dofile
devrait toujours fonctionner comme prévu.
Retour à la table des matières
Si vous souhaitez accéder à la variable d'environnement système, par exemple foo
, dans Lua via l'API Lua standard os.getenv, vous devez également répertorier le nom de cette variable d'environnement dans votre fichier nginx.conf
via la directive env. Par exemple,
env foo;
Retour à la table des matières
Le protocole HTTP 1.0 ne prend pas en charge la sortie fragmentée et nécessite un en-tête Content-Length
explicite lorsque le corps de la réponse n'est pas vide afin de prendre en charge le keep-alive HTTP 1.0. Ainsi, lorsqu'une requête HTTP 1.0 est effectuée et que la directive lua_http10_buffering est on
, ngx_lua mettra en mémoire tampon la sortie des appels ngx.say et ngx.print et reportera également l'envoi des en-têtes de réponse jusqu'à ce que toute la sortie du corps de la réponse soit reçue. À ce moment-là, ngx_lua peut calculer la longueur totale du corps et construire un en-tête Content-Length
approprié pour revenir au client HTTP 1.0. Cependant, si l'en-tête de réponse Content-Length
est défini dans le code Lua en cours d'exécution, cette mise en mémoire tampon sera désactivée même si la directive lua_http10_buffering est on
.
Pour les réponses de sortie de streaming volumineuses, il est important de désactiver la directive lua_http10_buffering pour minimiser l'utilisation de la mémoire.
Notez que les outils de référence HTTP courants tels que ab
et http_load
émettent des requêtes HTTP 1.0 par défaut. Pour forcer curl
à envoyer des requêtes HTTP 1.0, utilisez l'option -0
.
Retour à la table des matières
Avec LuaJIT 2.x, il est possible de lier statiquement le bytecode de modules Lua purs dans l'exécutable Nginx.
Vous pouvez utiliser l'exécutable luajit
pour compiler les fichiers du module .lua
Lua en fichiers objets .o
contenant les données de bytecode exportées, puis lier les fichiers .o
directement dans votre build Nginx.
Vous trouverez ci-dessous un exemple trivial pour le démontrer. Considérons que nous avons le fichier .lua
suivant nommé foo.lua
:
-- foo.lua
local _M = {}
function _M . go ()
print ( " Hello from foo " )
end
return _M
Et puis nous compilons ce fichier .lua
en fichier foo.o
:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
Ce qui compte ici, c'est le nom du fichier .lua
, qui détermine la manière dont vous utiliserez ce module plus tard sur Lua Land. Le nom du fichier foo.o
n'a aucune importance, sauf l'extension de fichier .o
(qui indique luajit
quel format de sortie est utilisé). Si vous souhaitez supprimer les informations de débogage Lua du bytecode résultant, vous pouvez simplement spécifier l'option -b
ci-dessus au lieu de -bg
.
Ensuite, lors de la construction de Nginx ou OpenResty, transmettez l'option --with-ld-opt="foo.o"
au script ./configure
:
./configure --with-ld-opt= " /path/to/foo.o " ...
Enfin, vous pouvez simplement faire ce qui suit dans n'importe quel code Lua exécuté par ngx_lua :
local foo = require " foo "
foo . go ()
Et ce morceau de code ne dépend plus du fichier foo.lua
externe car il a déjà été compilé dans l'exécutable nginx
.
Si vous souhaitez utiliser un point dans le nom du module Lua lors de l'appel require
, comme dans
local foo = require " resty.foo "
alors vous devez renommer le fichier foo.lua
en resty_foo.lua
avant de le compiler en un fichier .o
avec l'utilitaire de ligne de commande luajit
.
Il est important d'utiliser exactement la même version de LuaJIT lors de la compilation de fichiers .lua
en fichiers .o
lors de la construction de nginx + ngx_lua. En effet, le format de bytecode LuaJIT peut être incompatible entre les différentes versions de LuaJIT. Lorsque le format du bytecode est incompatible, vous verrez une erreur d'exécution Lua indiquant que le module Lua n'est pas trouvé.
Lorsque vous avez plusieurs fichiers .lua
à compiler et à lier, spécifiez simplement leurs fichiers .o
en même temps dans la valeur de l'option --with-ld-opt
. Par exemple,
./configure --with-ld-opt= " /path/to/foo.o /path/to/bar.o " ...
Si vous avez trop de fichiers .o
, il n'est peut-être pas possible de tous les nommer en une seule commande. Dans ce cas, vous pouvez créer une bibliothèque (ou une archive) statique pour vos fichiers .o
, comme dans
ar rcus libmyluafiles.a * .o
vous pouvez alors lier l'archive myluafiles
dans son ensemble à votre exécutable nginx :
./configure
--with-ld-opt= " -L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive "
où /path/to/lib
est le chemin du répertoire contenant le fichier libmyluafiles.a
. Il convient de noter que l'option de l'éditeur de liens --whole-archive
est requise ici car sinon notre archive sera ignorée car aucun symbole de notre archive n'est mentionné dans les parties principales de l'exécutable nginx.
Retour à la table des matières
Pour partager globalement des données entre toutes les requêtes traitées par le même processus de travail Nginx, encapsulez les données partagées dans un module Lua, utilisez la fonction intégrée Lua require
pour importer le module, puis manipulez les données partagées dans Lua. Cela fonctionne car les modules Lua requis ne sont chargés qu'une seule fois et toutes les coroutines partageront la même copie du module (à la fois son code et ses données).
Notez que l'utilisation de variables Lua globales est fortement déconseillée , car cela peut conduire à des conditions de concurrence inattendues entre des requêtes simultanées.
Voici un petit exemple de partage de données au sein d'un worker Nginx via un module Lua :
-- mydata.lua
local _M = {}
local data = {
dog = 3 ,
cat = 4 ,
pig = 5 ,
}
function _M . get_age ( name )
return data [ name ]
end
return _M
puis y accéder depuis nginx.conf
:
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
}
Le module mydata
dans cet exemple ne sera chargé et exécuté que lors de la première requête adressée à l'emplacement /lua
, et toutes les requêtes ultérieures adressées au même processus de travail Nginx utiliseront l'instance rechargée du module ainsi que la même copie des données dans jusqu'à ce qu'un signal HUP
soit envoyé au processus maître Nginx pour forcer un rechargement. Cette technique de partage de données est essentielle pour les applications Lua hautes performances basées sur ce module.
Notez que ce partage de données s'effectue par travailleur et non par serveur . Autrement dit, lorsqu'il existe plusieurs processus de travail Nginx sous un maître Nginx, le partage de données ne peut pas franchir la frontière des processus entre ces travailleurs.
Il est généralement recommandé de partager les données en lecture seule de cette manière. Vous pouvez également partager des données modifiables entre toutes les requêtes simultanées de chaque processus de travail Nginx tant qu'il n'y a pas d'opérations d'E/S non bloquantes (y compris ngx.sleep) au milieu de vos calculs. Tant que vous ne redonnez pas le contrôle à la boucle d'événements Nginx et au planificateur de threads légers de ngx_lua (même implicitement), il ne peut jamais y avoir de conditions de concurrence entre les deux. Pour cette raison, soyez toujours très prudent lorsque vous souhaitez partager des données modifiables au niveau du travailleur. Les optimisations de buggy peuvent facilement conduire à des conditions de concurrence difficiles à déboguer sous charge.
Si le partage de données à l’échelle du serveur est requis, utilisez une ou plusieurs des approches suivantes :
memcached
, redis
, MySQL
ou PostgreSQL
. Les versions officielles d'OpenResty sont livrées avec un ensemble de modules Nginx et de bibliothèques Lua qui fournissent des interfaces avec ces mécanismes de stockage de données.Retour à la table des matières
Retour à la table des matières
La méthode tcpsock:connect peut indiquer success
malgré des échecs de connexion tels que des erreurs Connection Refused
.
Cependant, les tentatives ultérieures de manipulation de l'objet cosocket échoueront et renverront le message d'état d'erreur réel généré par l'échec de l'opération de connexion.
Ce problème est dû aux limitations du modèle d'événement Nginx et semble affecter uniquement Mac OS X.
Retour à la table des matières
dofile
et require
de Lua sont actuellement implémentées en tant que fonctions C dans LuaJIT 2.0/2.1, si le fichier Lua chargé par dofile
ou require
invoque ngx.location.capture*, ngx.exec, ngx.exit ou d'autres fonctions API nécessitant un rendement dans la portée de niveau supérieur du fichier Lua, l'erreur Lua "tentative de céder au-delà de la limite de l'appel C" sera générée. Pour éviter cela, placez ces appels nécessitant une cession dans vos propres fonctions Lua dans le fichier Lua au lieu de la portée de niveau supérieur du fichier.Retour à la table des matières
Des précautions doivent être prises lors de l'importation de modules, et ce formulaire doit être utilisé :
local xxx = require ( ' xxx ' )
au lieu de l'ancien formulaire obsolète :
require ( ' xxx ' )
Voici la raison : de par sa conception, l'environnement global a exactement la même durée de vie que le gestionnaire de requêtes Nginx qui lui est associé. Chaque gestionnaire de requêtes possède son propre ensemble de variables globales Lua et c'est l'idée de l'isolation des requêtes. Le module Lua est en fait chargé par le premier gestionnaire de requêtes Nginx et est mis en cache par le require()
intégré dans la table package.loaded
pour référence ultérieure, et le module()
intégré utilisé par certains modules Lua a pour effet secondaire de définir une variable globale à la table du module chargé. Mais cette variable globale sera effacée à la fin du gestionnaire de requêtes, et chaque gestionnaire de requêtes ultérieur possède son propre environnement global (propre). Ainsi, on obtiendra une exception Lua pour accéder à la valeur nil
.
L'utilisation de variables globales Lua est généralement déconseillée dans le contexte ngx_lua car :
Il est donc fortement recommandé de toujours le déclarer dans une portée locale appropriée.
-- Avoid
foo = 123
-- Recommended
local foo = 123
-- Avoid
function foo () return 123 end
-- Recommended
local function foo () return 123 end
Pour trouver toutes les instances de variables globales Lua dans votre code Lua, exécutez l'outil lua-releng sur tous les fichiers source .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
La sortie indique que la ligne 1489 du fichier lib/foo/bar.lua
écrit dans une variable globale nommée contains
, la ligne 1506 lit la variable globale setvar
et la ligne 1545 lit la variable globale varexpand
.
Cet outil garantira que les variables locales dans les fonctions du module Lua sont toutes déclarées avec le mot-clé local
, sinon une exception d'exécution sera levée. Il évite les conditions de concurrence indésirables lors de l’accès à ces variables. Voir Partage de données au sein d'un travailleur Nginx pour les raisons derrière cela.
Retour à la table des matières
Les directives ngx.location.capture et ngx.location.capture_multi ne peuvent pas capturer les emplacements qui incluent les directives 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
ne fonctionnera pas comme prévu.
Retour à la table des matières
En raison de limitations internes au cœur de Nginx, l'API cosocket est désactivée dans les contextes suivants : set_by_lua*, log_by_lua*, header_filter_by_lua* et body_filter_by_lua.
Les cosockets sont actuellement également désactivés dans les contextes de directive init_by_lua* et init_worker_by_lua*, mais nous pourrions ajouter la prise en charge de ces contextes à l'avenir car il n'y a aucune limitation dans le noyau Nginx (ou la limitation pourrait être contournée).
Il existe cependant une solution de contournement lorsque le contexte d'origine n'a pas besoin d'attendre les résultats du cosocket. Autrement dit, créez un minuteur sans délai via l'API ngx.timer.at et effectuez les résultats du cosocket dans le gestionnaire de minuteur, qui s'exécute de manière asynchrone par rapport au contexte d'origine créant le minuteur.
Retour à la table des matières
REMARQUE Suite à la version v0.9.17
, cet écueil peut être évité en utilisant les directives de configuration *_by_lua_block {}
.
Les séquences PCRE telles que d
, s
, ou w
, nécessitent une attention particulière car dans les chaînes littérales, la barre oblique inverse, , est supprimée à la fois par l'analyseur du langage Lua et par l'analyseur du fichier de configuration Nginx avant le traitement si ce n'est dans un délai. Directive
*_by_lua_block {}
. L'extrait suivant ne fonctionnera donc pas comme prévu :
# 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!"
Pour éviter cela, échappez deux fois la barre oblique inverse :
# 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"
Ici, \\d+
est réduit à \d+
par l'analyseur de fichier de configuration Nginx et ceci est ensuite réduit à d+
par l'analyseur du langage Lua avant l'exécution.
Alternativement, le modèle d'expression régulière peut être présenté sous la forme d'une chaîne Lua littérale entre crochets longs en le plaçant entre "parenthèses longues", [[...]]
, auquel cas les barres obliques inverses ne doivent être échappées qu'une seule fois pour l'analyseur du fichier de configuration 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"
Ici, [[\d+]]
est réduit à [[d+]]
par l'analyseur de fichier de configuration Nginx et cela est traité correctement.
Notez qu'un from plus long du crochet long, [=[...]=]
, peut être requis si le modèle d'expression régulière contient [...]
des séquences. Le formulaire [=[...]=]
peut être utilisé comme formulaire par défaut si vous le souhaitez.
# 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"
Une approche alternative pour échapper aux séquences PCRE consiste à garantir que le code Lua est placé dans des fichiers de script externes et exécuté à l'aide des différentes directives *_by_lua_file
. Avec cette approche, les barres obliques inverses ne sont supprimées que par l'analyseur du langage Lua et ne doivent donc être échappées qu'une seule fois chacune.
-- 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"
Dans les fichiers de script externes, les séquences PCRE présentées sous forme de chaînes littérales Lua entre crochets longs ne nécessitent aucune modification.
-- 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"
Comme indiqué précédemment, les séquences PCRE présentées dans les directives *_by_lua_block {}
(disponibles après la version v0.9.17
) ne nécessitent pas de modification.
# 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"
REMARQUE Il est recommandé d'utiliser by_lua_file
lorsque le code Lua est très long.
Retour à la table des matières
Mélanger SSI avec ngx_lua dans la même requête Nginx n'est pas du tout pris en charge. Utilisez simplement ngx_lua exclusivement. Tout ce que vous pouvez faire avec SSI peut de toute façon être fait sur ngx_lua et cela peut être plus efficace lorsque vous utilisez ngx_lua.
Retour à la table des matières
Certaines API Lua fournies par ngx_lua ne fonctionnent pas encore en mode SPDY de Nginx : ngx.location.capture, ngx.location.capture_multi et ngx.req.socket.
Retour à la table des matières
Nginx peut mettre fin à une requête plus tôt avec (au moins) :
Cela signifie que les phases qui s'exécutent normalement sont ignorées, comme la phase de réécriture ou d'accès. Cela signifie également que les phases ultérieures exécutées indépendamment, par exemple log_by_lua, n'auront pas accès aux informations normalement définies dans ces phases.
Retour à la table des matières
bsdrecv
.ngx_hash_t
pour optimiser le processus de recherche d'en-tête intégré pour ngx.req.set_header, etc.ignore_resp_headers
, ignore_resp_body
et ignore_resp
aux méthodes ngx.location.capture et ngx.location.capture_multi, pour permettre le réglage des micro-performances du côté utilisateur.stat
similaire à mod_lua.Retour à la table des matières
Les modifications apportées dans chaque version de ce module sont répertoriées dans les journaux de modifications du bundle OpenResty :
https://openresty.org/#Changes
Retour à la table des matières
Les dépendances suivantes sont requises pour exécuter la suite de tests :
Version Nginx >= 1.4.2
Modules Perl :
Modules Nginx :
L'ordre dans lequel ces modules sont ajoutés lors de la configuration est important car la position de tout module de filtre dans la chaîne de filtrage détermine le résultat final, par exemple. L’ordre d’ajout correct est indiqué ci-dessus.
Bibliothèques Lua tierces :
Applications :