ngx_http_lua_модуль
Имя
ngx_http_lua_модуль — Встраивание возможностей Lua в серверы Nginx HTTP.
Этот модуль не входит в дистрибутив исходного кода Nginx. См. инструкции по установке.
Содержание
- Имя
- Статус
- Версия
- Синопсис
- Описание
- Типичные применения
- Совместимость с Nginx
- Установка
- Сообщество
- Репозиторий кода
- Ошибки и исправления
- Поддержка байт-кода Lua/LuaJIT
- Поддержка системных переменных среды
- Поддержка HTTP 1.0
- Статическая компоновка чистых модулей Lua
- Обмен данными внутри процесса Nginx Worker
-
Известные проблемы
- Проблемы с операцией соединения TCP сокетов
- Вызов/восстановление корутин Lua
- Область видимости переменных Lua
- Локации, сконфигурированные директивами дочерних запросов других модулей
- Cosockets недоступны везде
- Специальные последовательности экранирования
- Смешивание с SSI не поддерживается
- Режим SPDY не полностью поддерживается
- Отсутствие данных в запросах с короткой цепочкой
- TODO
- Изменения
- Набор тестов
- Авторские права и лицензия
- См. также
- Директивы
- API Nginx для Lua
- Устаревшие разделы
Статус
Готово к использованию в производстве.
Версия
Этот документ описывает ngx_lua v0.10.13, выпущенный 22 апреля 2018 года.
Синопсис
# 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
}
} Описание
Этот модуль встраивает Lua, через стандартный интерпретатор Lua 5.1 или LuaJIT 2.0/2.1, в Nginx. С помощью дочерних запросов Nginx, он позволяет интегрировать мощные потоки Lua (корутины Lua) в модель событий Nginx.
В отличие от mod_lua Apache и mod_magnet Lighttpd, код Lua, выполняемый с помощью этого модуля, может быть на 100% неблокирующим для сетевого трафика, если используется предоставленный этим модулем API Nginx для Lua для обработки запросов к таким сервисам, как MySQL, PostgreSQL, Memcached, Redis или HTTP веб-сервисам.
С этим модулем ngx_lua можно использовать, по крайней мере, следующие библиотеки Lua и модули Nginx:
- lua-resty-memcached
- lua-resty-mysql
- lua-resty-redis
- lua-resty-dns
- lua-resty-upload
- lua-resty-websocket
- lua-resty-lock
- lua-resty-logger-socket
- lua-resty-lrucache
- lua-resty-string
- ngx_memc
- ngx_postgres
- ngx_redis2
- ngx_redis
- ngx_proxy
- ngx_fastcgi
Практически все модули Nginx можно использовать с этим модулем ngx_lua с помощью ngx.location.capture или ngx.location.capture_multi, но рекомендуется использовать эти lua-resty-* библиотеки вместо создания дочерних запросов для доступа к модулям Nginx upstream, так как в первом случае обычно достигается большая гибкость и эффективность использования памяти.
Интерпретатор Lua или экземпляр LuaJIT совместно используются для всех запросов в одном рабочем процессе nginx, но контексты запросов изолированы с помощью лёгких корутин Lua.
Загруженные модули Lua сохраняются на уровне рабочего процесса nginx, что приводит к небольшому объёму используемой памяти Lua, даже при больших нагрузках.
Этот модуль подключён к подсистеме «http» NGINX, поэтому он может общаться только с протоколами в семействе HTTP (HTTP 0.9/1.0/1.1/2.0, WebSocket и т. д.). Если вам необходимо выполнять общие TCP-связи с клиентами по направлению вниз (downstream), используйте модуль ngx_stream_lua, который имеет совместимый API Lua.
Типичные применения
Вот лишь несколько:
- Объединение и обработка вывода различных потоков nginx upstream (proxy, drizzle, postgres, redis, memcached и т. д.) в Lua,
- выполнение произвольно сложных проверок доступа и безопасности в Lua перед тем, как запросы фактически достигнут backends,
- манипулирование заголовками ответа произвольным способом (с помощью Lua)
- получение информации о backend из внешних хранилищ данных (например, redis, memcached, mysql, postgresql) и использование этой информации для выбора целевого backend на лету,
- разработка произвольно сложных веб-приложений в обработчике содержимого с использованием синхронного, но всё ещё неблокирующего доступа к базам данных и другим хранилищам,
- выполнение очень слотной маршрутизации URL в Lua на фазе перенаправления,
- использование Lua для реализации продвинутой механизма кеширования для дочерних запросов Nginx и произвольных локаций.
Возможности безграничны, так как модуль позволяет объединять различные элементы в Nginx, а также предоставляет пользователю возможности языка Lua. Модуль обеспечивает полную гибкость сценариев, сохраняя при этом производительность, сопоставимую с программами на чистом C, как по времени выполнения CPU, так и по объёму используемой памяти. Это особенно актуально при включении LuaJIT 2.x.
Другие реализации языков сценариев обычно не достигают такого уровня производительности.
Состояние Lua (экземпляр виртуальной машины Lua) совместно используется для всех запросов, обрабатываемых одним рабочим процессом nginx, чтобы свести к минимуму использование памяти.
Совместимость с Nginx
Последняя версия этого модуля совместима со следующими версиями Nginx:
- 1.13.x (последнее тестирование: 1.13.6)
- 1.12.x
- 1.11.x (последнее тестирование: 1.11.2)
- 1.10.x
- 1.9.x (последнее тестирование: 1.9.15)
- 1.8.x
- 1.7.x (последнее тестирование: 1.7.10)
- 1.6.x
Ядра Nginx, более старые, чем 1.6.0 (исключительно), не поддерживаются.
Установка
Сильно рекомендуется использовать релизы OpenResty, которые интегрируют Nginx, ngx_lua, LuaJIT 2.1, а также другие мощные модули Nginx и библиотеки Lua. Не рекомендуется самостоятельно собирать этот модуль с nginx, так как это сложно сделать правильно. Также в стандартных ядрах nginx есть различные ограничения и давно известные ошибки, которые могут привести к отключению некоторых функций этого модуля, неправильной работе или замедлению. То же самое относится и к LuaJIT. OpenResty включает собственную версию LuaJIT, которая оптимизирована и улучшена для среды OpenResty.
В качестве альтернативы, ngx_lua можно скомпилировать вручную в Nginx:
- Установите LuaJIT 2.0 или 2.1 (рекомендуется) или Lua 5.1 (Lua 5.2 не поддерживается ещё). LuaJIT можно загрузить с сайта проекта LuaJIT, а Lua 5.1 — с сайта проекта Lua. Некоторые менеджеры пакетов дистрибутивов также распространяют LuaJIT и/или Lua.
- Загрузите последнюю версию модуля ngx_devel_kit (NDK) ЗДЕСЬ.
- Загрузите последнюю версию ngx_lua ЗДЕСЬ.
- Загрузите последнюю версию Nginx ЗДЕСЬ (См. Совместимость с Nginx)
Соберите исходный код с этим модулем:
wget 'http://nginx.org/download/nginx-1.13.6.tar.gz'
tar -xzvf nginx-1.13.6.tar.gz
cd nginx-1.13.6/
# 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
# or tell where to find Lua if using Lua instead:
#export LUA_LIB=/path/to/lua/lib
#export LUA_INC=/path/to/lua/include
# Here we assume Nginx is to be installed under /opt/nginx/.
./configure --prefix=/opt/nginx \
--with-ld-opt="-Wl,-rpath,/path/to/luajit-or-lua/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 parallism number 2 below to fit the number of spare CPU cores in your
# machine.
make -j2
make install Компиляция как динамического модуля
Начиная с NGINX 1.9.11, вы также можете скомпилировать этот модуль как динамический модуль, используя параметр --add-dynamic-module=PATH вместо --add-module=PATH в команде ./configure выше. Затем вы можете явно загрузить модуль в ваш файл nginx.conf с помощью директивы load_module, например,
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;
Конфигурации макросов C
При сборке этого модуля, либо через OpenResty, либо с ядром NGINX, вы можете определить следующие макросы C через параметры компилятора C:
-
NGX_LUA_USE_ASSERTПри определении включит проверки в коде ngx_lua. Рекомендуется для отладки или тестирования сборок. Может вносить небольшую задержку во время выполнения при включении. Эта макрос была впервые представлена вv0.9.10релизе. -
NGX_LUA_ABORT_AT_PANICПри аварийном завершении виртуальной машины Lua/LuaJIT, ngx_lua по умолчанию сообщит текущему процессу nginx worker о плавном завершении. Указав эту C-макрос, ngx_lua немедленно прервет текущий процесс nginx worker (что обычно приводит к файлу core dump). Этот параметр полезен для отладки аварий виртуальной машины. Этот параметр был впервые представлен вv0.9.8релизе. -
NGX_LUA_NO_FFI_APIИсключает чистые функции API C для API Lua на основе FFI для NGINX (как требуется, например, lua-resty-core). Включение этой макроса может уменьшить размер двоичного кода.
Чтобы включить одну или несколько из этих макросов, просто передайте дополнительные параметры компилятора C скрипту ./configure NGINX или OpenResty. Например,
./configure --with-cc-opt="-DNGX_LUA_USE_ASSERT -DNGX_LUA_ABORT_AT_PANIC"
Установка на Ubuntu 11.10
Рекомендуется использовать LuaJIT 2.0 или LuaJIT 2.1 вместо стандартного интерпретатора Lua 5.1, где это возможно.
Если требуется стандартный интерпретатор Lua 5.1, выполните следующую команду для его установки из репозитория Ubuntu:
apt-get install -y lua5.1 liblua5.1-0 liblua5.1-0-dev
Всё должно быть установлено правильно, кроме одной небольшой настройки.
Имя библиотеки liblua.so было изменено в пакете liblua5.1, он поставляется только с liblua5.1.so, который необходимо создать символическую ссылку на /usr/lib, чтобы он был найден во время процесса конфигурации.
ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/liblua.so
Сообщество
Список рассылки по-английски
Список рассылки openresty-en предназначен для англоговорящих пользователей.
Список рассылки по-китайски
Список рассылки openresty предназначен для китайских пользователей.
Репозиторий кода
Репозиторий кода этого проекта размещен на github по адресу openresty/lua-nginx-module.
Отчеты об ошибках и исправления
Пожалуйста, отправляйте отчеты об ошибках, списки пожеланий или исправления, выполнив
- создание тикета в GitHub Issue Tracker,
- или публикацией в сообществе OpenResty.
Поддержка байткода Lua/LuaJIT
Начиная с v0.5.0rc32 релиза, все *_by_lua_file директивы конфигурации (такие как content_by_lua_file) поддерживают прямое загрузку сырых файлов байткода Lua 5.1 и LuaJIT 2.0/2.1.
Обратите внимание, что формат байткода, используемый LuaJIT 2.0/2.1, несовместим с форматом, используемым стандартным интерпретатором Lua 5.1. Поэтому, если вы используете LuaJIT 2.0/2.1 с ngx_lua, файлы байткода, совместимые с LuaJIT, должны быть сгенерированы следующим образом:
/path/to/luajit/bin/luajit -b /path/to/input_file.lua /path/to/output_file.ljbc
Параметр -bg может использоваться для включения отладочной информации в файл байткода LuaJIT:
/path/to/luajit/bin/luajit -bg /path/to/input_file.lua /path/to/output_file.ljbc
Дополнительные сведения см. в официальной документации LuaJIT по параметру -b:
http://luajit.org/running.html#opt_b
Кроме того, файлы байткода, сгенерированные LuaJIT 2.1, не совместимы с LuaJIT 2.0 и наоборот. Поддержка байткода LuaJIT 2.1 была добавлена в ngx_lua v0.9.3.
Аналогично, если вы используете стандартный интерпретатор Lua 5.1 с ngx_lua, файлы байткода, совместимые со стандартным Lua 5.1, должны быть сгенерированы с помощью утилиты командной строки luac, как показано:
luac -o /path/to/output_file.luac /path/to/input_file.lua
В отличие от LuaJIT, отладочная информация включается в файлы байткода стандартного Lua 5.1 по умолчанию. Ее можно удалить, указав параметр -s, как показано:
luac -s -o /path/to/output_file.luac /path/to/input_file.lua
Попытки загрузить файлы байткода стандартного Lua 5.1 в экземпляры ngx_lua, связанные с LuaJIT 2.0/2.1 или наоборот, приведут к записи сообщения об ошибке в файл Nginx error.log:
[error] 13909#0: *1 failed to load Lua inlined code: bad byte-code header in /path/to/test_file.luac
Загрузка файлов байткода с помощью Lua-примитивов, таких как require и dofile, должна всегда работать как ожидается.
Поддержка переменных среды системы
Если вы хотите получить доступ к переменной среды системы, скажем, foo, в Lua через стандартный Lua API os.getenv, то вам также следует указать имя этой переменной в файле nginx.conf с помощью директивы env. Например,
env foo;
Поддержка HTTP 1.0
Протокол HTTP 1.0 не поддерживает фрагментацию вывода и требует явного заголовка Content-Length, когда тело ответа не пусто, чтобы поддерживать HTTP 1.0 keep-alive. Поэтому, когда выполняется запрос HTTP 1.0 и директива lua_http10_buffering включена on, ngx_lua будет буферизовать вывод вызовов ngx.say и ngx.print, а также отложить отправку заголовков ответа до получения всего вывода тела ответа. В этот момент ngx_lua может вычислить общую длину тела и сгенерировать правильный заголовок Content-Length для возврата HTTP 1.0 клиенту. Однако, если заголовок ответа Content-Length установлен в выполняемом Lua коде, эта буферизация будет отключена, даже если директива lua_http10_buffering включена on.
Для больших потоковых ответов важно отключить директиву lua_http10_buffering, чтобы минимизировать использование памяти.
Обратите внимание, что такие инструменты для тестирования производительности HTTP, как ab и http_load, по умолчанию отправляют запросы HTTP 1.0. Чтобы заставить curl отправлять запросы HTTP 1.0, используйте параметр -0.
Статическая компоновка чистых Lua-модулей
При использовании LuaJIT 2.x можно статически связать байт-код чистых Lua-модулей в исполняемый файл Nginx.
В основном вы используете исполняемый файл luajit для компиляции файлов Lua-модулей .lua в файлы-объекты .o, содержащие экспортированные данные байткода, а затем связываете файлы .o напрямую в вашей сборке Nginx.
Ниже приведен тривиальный пример, демонстрирующий это. Предположим, что у нас есть следующий .lua файл с именем foo.lua:
-- foo.lua
local _M = {}
function _M.go()
print("Hello from foo")
end
return _M Затем мы компилируем этот файл .lua в файл foo.o:
/path/to/luajit/bin/luajit -bg foo.lua foo.o
Важным здесь является имя файла .lua, которое определяет, как вы будете использовать этот модуль позже в Lua. Имя файла foo.o не имеет значения, за исключением расширения файла .o (которое указывает luajit, какой формат вывода используется). Если вы хотите удалить отладочную информацию Lua из результирующего байткода, вы можете просто указать параметр -b вместо -bg.
Затем, при построении Nginx или OpenResty, передайте параметр --with-ld-opt="foo.o" скрипту ./configure:
./configure --with-ld-opt="/path/to/foo.o" ...
Наконец, в любом Lua-коде, выполняемом ngx_lua, можно сделать следующее:
local foo = require "foo" foo.go()
Этот фрагмент кода больше не зависит от внешнего файла foo.lua, так как он уже был скомпилирован в исполняемый файл nginx.
Если вы хотите использовать точку в имени Lua-модуля при вызове require, как в
local foo = require "resty.foo"
тогда вам необходимо переименовать файл foo.lua в resty_foo.lua перед компиляцией в файл .o с помощью утилиты командной строки luajit.
Важно использовать точно ту же версию LuaJIT при компиляции файлов .lua в файлы .o, что и при построении nginx + ngx_lua. Это связано с тем, что формат байткода LuaJIT может быть несовместим между различными версиями LuaJIT. При несовместимости формата байткода вы увидите ошибку выполнения Lua, указывающую, что Lua-модуль не найден.
Если у вас несколько файлов .lua, которые необходимо скомпилировать и связать, укажите их файлы .o одновременно в значении параметра --with-ld-opt. Например,
./configure --with-ld-opt="/path/to/foo.o /path/to/bar.o" ...
Если у вас слишком много файлов .o, то их может быть невозможно перечислить в одной команде. В этом случае можно создать статическую библиотеку (или архив) для ваших файлов .o, как в
ar rcus libmyluafiles.a *.o
затем можно связать архив myluafiles целиком со своим исполняемым файлом nginx:
./configure \ --with-ld-opt="-L/path/to/lib -Wl,--whole-archive -lmyluafiles -Wl,--no-whole-archive"
где /path/to/lib - путь к каталогу, содержащему файл libmyluafiles.a. Следует отметить, что параметр компоновщика --whole-archive требуется здесь, иначе наш архив будет пропущен, так как нет упоминаний о символах в нашем архиве в основных частях исполняемого файла nginx.
Обмен данными внутри процесса Nginx worker
Чтобы обмениваться данными между всеми запросами, обрабатываемыми одним процессом nginx worker, инкапсулируйте общие данные в Lua-модуль, используйте встроенную функцию Lua require для импорта модуля, а затем манипулируйте общими данными в Lua. Это работает, потому что необходимые Lua-модули загружаются только один раз, и все сопрограммы будут использовать одну и ту же копию модуля (как его код, так и данные). Однако обратите внимание, что переменные глобальные Lua (не переменные уровня модуля) НЕ будут сохраняться между запросами из-за изоляции одной сопрограммы на запрос.
Вот небольшой пример:
-- mydata.lua
local _M = {}
local data = {
dog = 3,
cat = 4,
pig = 5,
}
function _M.get_age(name)
return data[name]
end
return _M а затем доступ к нему из nginx.conf:
location /lua {
content_by_lua_block {
local mydata = require "mydata"
ngx.say(mydata.get_age("dog"))
}
} Модуль mydata в этом примере будет загружен и запущен только при первом запросе к местоположению /lua, и все последующие запросы к тому же процессу nginx worker будут использовать перезагруженный экземпляр модуля, а также ту же копию данных в нём, пока не будет отправлен сигнал HUP мастер-процессу Nginx для принудительной перезагрузки. Этот метод обмена данными имеет важное значение для высокопроизводительных Lua-приложений, основанных на этом модуле.
Обратите внимание, что этот обмен данными осуществляется на уровне процесса worker, а не на уровне сервера. То есть, когда существует несколько процессов nginx worker под управлением мастер-процесса Nginx, обмен данными не может переходить через границу процесса между этими рабочими процессами.
END_OF_DOCUMENT_MARKERОбычно рекомендуется таким образом обмениваться данными только для чтения. Вы также можете обмениваться изменяемыми данными между всеми одновременными запросами каждого процесса worker nginx, если в середине ваших вычислений нет операций ввода-вывода без блокировки (включая ngx.sleep). Пока вы не отдадите контроль обратно циклу событий nginx и планировщику лёгких потоков ngx_lua (даже неявно), между запросами не может быть никаких гонок. По этой причине всегда будьте очень осторожны, когда хотите обмениваться изменяемыми данными на уровне worker. Неправильно оптимизированный код может легко привести к трудноотлажимым гонкам при высокой нагрузке.
Если требуется совместное использование данных на уровне сервера, воспользуйтесь одним или несколькими из следующих подходов:
- Используйте API ngx.shared.DICT, предоставляемый этим модулем.
- Используйте только один процесс worker nginx и один сервер (однако это не рекомендуется, когда имеется многоядерный процессор или несколько процессоров на одном компьютере).
- Используйте механизмы хранения данных, такие как
memcached,redis,MySQLилиPostgreSQL. Пакет OpenResty, связанный с этим модулем, поставляется с набором дополнительных модулей Nginx и Lua-библиотек, которые предоставляют интерфейсы с этими механизмами хранения данных.
Известные проблемы
Проблемы с операциями подключения TCP-сокетов
Метод tcpsock:connect может указывать success, несмотря на сбои подключения, такие как с ошибками Connection Refused.
Однако последующие попытки манипулировать объектом cosocket завершатся ошибкой и вернут фактическое сообщение об ошибке, сгенерированное неудачной операцией подключения.
Эта проблема вызвана ограничениями модели событий Nginx и, как представляется, затрагивает только Mac OS X.
Выдача/Возобновление корутин Lua
- Поскольку встроенные функции Lua
dofileиrequireв настоящее время реализованы как C-функции как в Lua 5.1, так и в LuaJIT 2.0/2.1, если Lua-файл, загружаемыйdofileилиrequire, вызывает ngx.location.capture*, ngx.exec, ngx.exit или другие API-функции, требующие выдачи в глобальной области Lua-файла, то будет поднята ошибка Lua «попытка выдать за пределами границы C-вызова». Чтобы избежать этого, поместите эти вызовы, требующие выдачи, в свои собственные Lua-функции в Lua-файле вместо глобальной области файла. - Поскольку виртуальная машина стандартного интерпретатора Lua 5.1 не полностью возобновляема, методы ngx.location.capture, ngx.location.capture_multi, ngx.redirect, ngx.exec и ngx.exit не могут использоваться в контексте Lua pcall() или xpcall(), или даже в первой строке оператора
for ... in ..., когда используется стандартный интерпретатор Lua 5.1, и будет генерироваться ошибкаattempt to yield across metamethod/C-call boundary. Используйте LuaJIT 2.x, который поддерживает полностью возобновляемую виртуальную машину, чтобы избежать этого.
Область видимости переменных Lua
Необходимо соблюдать осторожность при импорте модулей, и следует использовать такую форму:
local xxx = require('xxx') вместо устаревшей формы:
require('xxx') Причина в том, что по дизайну глобальная среда имеет такой же жизненный цикл, как и обработчик запросов Nginx, связанный с ним. Каждый обработчик запросов имеет свой собственный набор Lua-глобальных переменных, и в этом заключается идея изоляции запросов. Модуль Lua фактически загружается первым обработчиком запросов Nginx и кэшируется встроенной функцией require() в таблице package.loaded для последующего использования, а встроенная функция module(), используемая некоторыми Lua-модулями, имеет побочный эффект установки глобальной переменной в таблицу загруженного модуля. Но эта глобальная переменная будет очищена по завершении обработчика запросов, а каждый последующий обработчик запросов будет иметь свою собственную (чистую) глобальную среду. Таким образом, будет возникать исключение Lua при доступе к значению nil.
Использование Lua-глобальных переменных в контексте ngx_lua в целом не рекомендуется, так как:
- неправильное использование Lua-глобалей оказывает негативное влияние на одновременные запросы, когда такие переменные должны быть локальными по области видимости,
- Lua-глобальные переменные требуют обращений к таблицам Lua в глобальной среде, что является вычислительно дорогостоящим, и
- некоторые ссылки на Lua-глобальные переменные могут содержать ошибки типизации, что затрудняет отладку.
Поэтому настоятельно рекомендуется всегда объявлять такие переменные в соответствующей локальной области видимости.
-- Avoid foo = 123 -- Recommended local foo = 123 -- Avoid function foo() return 123 end -- Recommended local function foo() return 123 end
Чтобы найти все случаи Lua-глобальных переменных в вашем Lua-коде, запустите инструмент lua-releng по всем .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
Вывод говорит о том, что строка 1489 файла lib/foo/bar.lua записывает в глобальную переменную с именем contains, строка 1506 считывает из глобальной переменной setvar, а строка 1545 считывает глобальную переменную varexpand.
Этот инструмент гарантирует, что все локальные переменные в функциях Lua-модуля объявлены с ключевым словом local, в противном случае будет выброшено исключение во время выполнения. Это предотвращает нежелательные гонки при доступе к таким переменным. См. раздел Совместное использование данных в процессе Nginx Worker для объяснения причин.
Локации, настроенные директивами подзапросов других модулей
Директивы ngx.location.capture и ngx.location.capture_multi не могут захватить локации, включающие директивы add_before_body, add_after_body, auth_request, echo_location, echo_location_async, echo_subrequest или 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
не будут работать должным образом.
Cosockets недоступны во всех контекстах
Из-за внутренних ограничений ядра nginx, API cosocket отключён в следующих контекстах: set_by_lua*, log_by_lua*, header_filter_by_lua* и body_filter_by_lua.
Cosockets также в настоящее время отключены в директивах init_by_lua* и init_worker_by_lua*, но мы можем добавить поддержку для этих контекстов в будущем, так как в ядре nginx нет ограничений (или ограничение можно обойти).
Однако существует обходной путь, когда исходному контексту не нужно ждать результатов cosocket. То есть создание таймера нулевого задержки с помощью API ngx.timer.at и выполнение обработки результатов cosocket в обработчике таймера, который выполняется асинхронно по отношению к исходному контексту, создавшему таймер.
Специальные последовательности экранирования
ПРИМЕЧАНИЕ После выпуска v0.9.17 эту проблему можно избежать, используя директивы конфигурации *_by_lua_block {}.
Последовательности PCRE, такие как \d, \s или \w, требуют особого внимания, потому что в строковых литералах символ обратной косой черты, \, удаляется как парсером языка Lua, так и парсером файла конфигурации nginx до обработки, если он не находится внутри директивы *_by_lua_block {}. Поэтому следующий фрагмент не будет работать должным образом:
# 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!" Чтобы избежать этого, удвойте экранирование обратной косой черты:
# 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" Здесь, \\\\d+ сводится к \\d+ парсером файла конфигурации Nginx и далее к \d+ парсером языка Lua перед выполнением.
В качестве альтернативы, шаблон регулярного выражения можно представить как строковый литерал Lua в длинных квадратных скобках, [[...]], в этом случае обратные косые черты нужно экранировать только один раз для парсера файла конфигурации 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" Здесь, [[\\d+]] сводится к [[\d+]] парсером файла конфигурации Nginx и обрабатывается правильно.
Обратите внимание, что более длинная форма длинных скобок, [=[...]=], может потребоваться, если шаблон регулярного выражения содержит [...] последовательности. Форма [=[...]=] может быть использована в качестве стандартной, если это необходимо.
# 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" Альтернативный подход к экранированию последовательностей PCRE заключается в том, чтобы убедиться, что Lua-код размещён во внешних скриптовых файлах и выполнялся с помощью различных директив *_by_lua_file. С этим подходом обратные косые черты удаляются только парсером языка Lua и, следовательно, их нужно экранировать только один раз.
-- 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" Во внешних скриптовых файлах шаблоны регулярных выражений, представленные как строковые литералы Lua в длинных квадратных скобках, не требуют изменений.
-- 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" Как отмечалось ранее, последовательности PCRE, представленные в директивах *_by_lua_block {} (доступные после выпуска v0.9.17), не требуют модификаций.
# 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" Смешивание с SSI не поддерживается
Смешивание SSI с ngx_lua в одном запросе Nginx не поддерживается. Используйте только ngx_lua. Всё, что можно сделать с SSI, можно сделать и с ngx_lua, и это может быть более эффективным при использовании ngx_lua.
Режим SPDY не полностью поддерживается
Некоторые API Lua, предоставляемые ngx_lua, пока не работают в режиме SPDY Nginx: ngx.location.capture, ngx.location.capture_multi и ngx.req.socket.
Отсутствующие данные при прерванных запросах
Nginx может прервать запрос преждевременно (по крайней мере) с:
- 400 (Ошибка запроса)
- 405 (Запрещено)
- 408 (Тайм-аут запроса)
- 413 (Запрос слишком большой)
- 414 (URI запроса слишком большой)
- 494 (Заголовок запроса слишком большой)
- 499 (Клиент закрыл запрос)
- 500 (Внутренняя ошибка сервера)
- 501 (Не реализовано)
Это означает, что фазы, которые обычно выполняются, пропускаются, такие как фаза переписывания или доступа. Это также означает, что последующие фазы, которые выполняются независимо, например, log_by_lua, не будут иметь доступа к информации, которая обычно устанавливается в этих фазах.
Список задач
- cosocket: реализовать API неопределённого UDP LuaSocket.
- переместить этот модуль в подсистему «datagram» NGINX для реализации общих UDP-серверов вместо HTTP-серверов на Lua. Например,
datagram {
server {
listen 1953;
handler_by_lua_block {
-- custom Lua code implementing the special UDP server...
}
}
} - shm: реализовать API «общей очереди» для дополнения существующего API shared dict.
- cosocket: добавить поддержку в контексте init_by_lua*.
- cosocket: реализовать метод
bind()для сокетов типа поток. - cosocket: управление уровнями конкуретности бекенда на основе пулов: реализовать автоматическое
connectочередирование, когда уровень конкуретности бекенда превышает предел пула подключений. - cosocket: пересмотреть и объединить патч aviramc patch для добавления метода
bsdrecv. - добавить новую функцию API
ngx.resp.add_headerдля эмуляции стандартной директивы конфигурацииadd_header. - пересмотреть и применить патч vadim-pavlov для опции
extra_headersметода ngx.location.capture - использовать
ngx_hash_tдля оптимизации встроенного процесса поиска заголовков для ngx.req.set_header, ngx.header.HEADER и т. д. - добавить опции конфигурации для разных стратегий обработки превышения подключений cosocket в пулах.
- добавить директивы для выполнения кода Lua при остановке nginx.
- добавить
ignore_resp_headers,ignore_resp_bodyиignore_respопции к методам ngx.location.capture и ngx.location.capture_multi для настройки микропроизводительности со стороны пользователя. - добавить автоматическую поддержку нарезки кода Lua путем явного передачи и возобновления виртуальной машины Lua через отладочные крючки Lua.
- добавить режим
stat, аналогичный mod_lua. - cosocket: добавить поддержку сертификатов SSL клиента.
Изменения
Изменения, внесённые в каждом релизе этого модуля, перечислены в журналах изменений пакета OpenResty:
Набор тестов
Для выполнения набора тестов необходимы следующие зависимости:
-
Версия Nginx >= 1.4.2
-
Модули Perl:
- Test::Nginx: https://github.com/openresty/test-nginx
-
Модули Nginx:
- ngx_devel_kit
- ngx_set_misc
- ngx_auth_request (не требуется, если используется Nginx 1.5.4+.
- ngx_echo
- ngx_memc
- ngx_srcache
- ngx_lua (то есть, этот модуль)
- ngx_lua_upstream
- ngx_headers_more
- ngx_drizzle
- ngx_rds_json
- ngx_coolkit
- ngx_redis2
Порядок добавления этих модулей во время конфигурации важен, так как позиция любого модуля фильтра в цепочке фильтрации определяет конечный результат, например. Правильный порядок добавления показан выше.
-
Библиотеки Lua сторонних разработчиков:
-
Приложения:
- mysql: создать базу данных 'ngx_test', предоставить все привилегии пользователю 'ngx_test', пароль — 'ngx_test'
- memcached: прослушивает на стандартном порту, 11211.
- redis: прослушивает на стандартном порту, 6379.
См. также скрипт сборки разработчика developer build script для получения более подробной информации о настройке тестовой среды.
Для запуска всего набора тестов в стандартном тестовом режиме:
cd /path/to/lua-nginx-module export PATH=/path/to/your/nginx/sbin:$PATH prove -I/path/to/test-nginx/lib -r t
Для запуска определённых тестовых файлов:
cd /path/to/lua-nginx-module export PATH=/path/to/your/nginx/sbin:$PATH prove -I/path/to/test-nginx/lib t/002-content.t t/003-errors.t
Для запуска определённого тестового блока в конкретном тестовом файле, добавьте строку --- ONLY в нужный тестовый блок, а затем используйте утилиту prove для запуска этого .t файла.
Также существуют различные тестовые режимы, основанные на mockeagain, valgrind и т. д. Для получения дополнительной информации о различных расширенных тестовых режимах обратитесь к документации Test::Nginx. Также см. отчёты о тестах для кластера тестов Nginx, работающего на Amazon EC2: http://qa.openresty.org.
Авторские права и лицензия
Этот модуль лицензирован по лицензии BSD.
Авторские права (C) 2009-2017, Xiaozhe Wang (chaoslawful) chaoslawful@gmail.com.
Авторские права (C) 2009-2018, Yichun "agentzh" Zhang (章亦春) agentzh@gmail.com, OpenResty Inc.
Все права защищены.
Перераспределение и использование в исходной и двоичной формах, с изменениями или без них, разрешены при соблюдении следующих условий:
-
При перераспределении исходного кода необходимо сохранить вышеуказанное уведомление об авторских правах, этот список условий и следующую оговорку об отказе от ответственности.
-
При перераспределении в двоичной форме необходимо воспроизвести вышеуказанное уведомление об авторских правах, этот список условий и следующую оговорку об отказе от ответственности в документации и/или других материалах, поставляемых с распространением.
ЭТА ПРОГРАММА ПРЕДОСТАВЛЯЕТСЯ НАХОДЯЩИМИСЬ В АВТОРСКИХ ПРАВАХ И СОТРУДНИКАМИ «КАК ЕСТЬ», И ЛЮБЫЕ ЯВНЫЕ ИЛИ ПОДРАЗУМЕВАЮЩИЕСЯ ГАРАНТИИ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОДРАЗУМЕВАЕМЫЕ ГАРАНТИИ ТОРГОВОЙ ПРИГОДНОСТИ И ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ, ОТКАЗЫВАЮТСЯ. НИ ПРИ КАКИХ ОБСТОЯТЕЛЬСТВАХ НАХОДЯЩИЕСЯ В АВТОРСКИХ ПРАВАХ ИЛИ СОТРУДНИКИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ЗА ЛЮБЫЕ ПРЯМЫЕ, КОСВЕННЫЕ, СЛУЧАЙНЫЕ, СПЕЦИАЛЬНЫЕ, ШТРАФНЫЕ ИЛИ ПОСЛЕДОВАТЕЛЬНЫЕ УБЫТКИ (ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ, ПОКУПКУ ЗАМЕНЯЮЩИХ ТОВАРОВ ИЛИ УСЛУГ; ПОТЕРЮ ИСПОЛЬЗОВАНИЯ, ДАННЫХ ИЛИ ПРИБЫЛИ; ИЛИ ПЕРЕРЫВ ДЕЯТЕЛЬНОСТИ), ВНЕЗАВИСИМО ОТ ПРИЧИНЫ И НА ЛЮБОЙ ТЕОРИИ ОТВЕТСТВЕННОСТИ, БУДЬ ТО ДОГОВОР, СТРОГАЯ ОТВЕТСТВЕННОСТЬ ИЛИ ДЕЛИКТ (ВКЛЮЧАЯ НЕБРЕЖНОСТЬ ИЛИ ДРУГОЕ), ВОЗНИКШИЕ ЛЮБЫМ ОБРАЗОМ ИЗ ИСПОЛЬЗОВАНИЯ ЭТОЙ ПРОГРАММЫ, ДАЖЕ ЕСЛИ БЫЛО ИЗВЕСТНО О ВОЗМОЖНОСТИ ТАКИХ УБЫТКОВ.
См. также
- ngx_stream_lua_module для официального порта этого модуля для подсистемы NGINX «stream» (выполняющей общие коммуникации по TCP спускаемым вниз).
- lua-resty-memcached библиотека на основе ngx_lua cosocket.
- lua-resty-redis библиотека на основе ngx_lua cosocket.
- lua-resty-mysql библиотека на основе ngx_lua cosocket.
- lua-resty-upload библиотека на основе ngx_lua cosocket.
- lua-resty-dns библиотека на основе ngx_lua cosocket.
- lua-resty-websocket библиотека для WebSocket-сервера и клиента, основанная на ngx_lua cosocket.
- lua-resty-string библиотека на основе LuaJIT FFI.
- lua-resty-lock библиотека для простого API блокировки без ожидания.
- lua-resty-cookie библиотека для управления HTTP-cookies.
- Маршрутизация запросов к различным запросам MySQL на основе аргументов URI
- Динамическая маршрутизация на основе Redis и Lua
- Использование LuaRocks с ngx_lua
- Введение в ngx_lua
- ngx_devel_kit
- echo-nginx-module
- drizzle-nginx-module
- postgres-nginx-module
- memc-nginx-module
- Пакет OpenResty
- Инструменты Nginx Systemtap
Директивы
- lua_capture_error_log
- lua_use_default_type
- lua_malloc_trim
- lua_code_cache
- lua_regex_cache_max_entries
- lua_regex_match_limit
- lua_package_path
- lua_package_cpath
- init_by_lua
- init_by_lua_block
- init_by_lua_file
- init_worker_by_lua
- init_worker_by_lua_block
- init_worker_by_lua_file
- set_by_lua
- set_by_lua_block
- set_by_lua_file
- content_by_lua
- content_by_lua_block
- content_by_lua_file
- rewrite_by_lua
- rewrite_by_lua_block
- rewrite_by_lua_file
- access_by_lua
- access_by_lua_block
- access_by_lua_file
- header_filter_by_lua
- header_filter_by_lua_block
- header_filter_by_lua_file
- body_filter_by_lua
- body_filter_by_lua_block
- body_filter_by_lua_file
- log_by_lua
- log_by_lua_block
- log_by_lua_file
- balancer_by_lua_block
- balancer_by_lua_file
- lua_need_request_body
- ssl_certificate_by_lua_block
- ssl_certificate_by_lua_file
- ssl_session_fetch_by_lua_block
- ssl_session_fetch_by_lua_file
- ssl_session_store_by_lua_block
- ssl_session_store_by_lua_file
- lua_shared_dict
- lua_socket_connect_timeout
- lua_socket_send_timeout
- lua_socket_send_lowat
- lua_socket_read_timeout
- lua_socket_buffer_size
- lua_socket_pool_size
- lua_socket_keepalive_timeout
- lua_socket_log_errors
- lua_ssl_ciphers
- lua_ssl_crl
- lua_ssl_protocols
- lua_ssl_trusted_certificate
- lua_ssl_verify_depth
- lua_http10_buffering
- rewrite_by_lua_no_postpone
- access_by_lua_no_postpone
- lua_transform_underscores_in_response_headers
- lua_check_client_abort
- lua_max_pending_timers
- lua_max_running_timers
Основные строительные блоки для написания скриптов на Lua в Nginx — это директивы. Директивы используются для указания времени выполнения пользовательского кода Lua и того, как будет использоваться результат. Ниже приведена диаграмма, показывающая порядок выполнения директив.
lua_capture_error_log
синтаксис: lua_capture_error_log размер
по умолчанию: нет
контекст: http
Включает буфер заданного size для захвата всех сообщений журнала ошибок Nginx (не только тех, которые генерирует этот модуль или подсистема nginx http, но и всех остальных) без записи в файлы или на диск.
Вы можете использовать единицы измерения, такие как k и m, в значении size, как в
lua_capture_error_log 100k;
Как правило, буфер размером 4 КБ обычно может содержать около 20 типичных сообщений журнала ошибок. Так что посчитайте!
Этот буфер никогда не увеличивается. Если он заполнен, новые сообщения журнала ошибок будут заменять самые старые в буфере.
Размер буфера должен быть больше максимальной длины одного сообщения журнала ошибок (которое составляет 4 КБ в OpenResty и 2 КБ в стандартном Nginx).
Вы можете читать сообщения в буфере в Lua с помощью функции get_logs() модуля ngx.errlog библиотеки lua-resty-core. Эта функция API Lua вернёт захваченные сообщения журнала ошибок, а также удалит уже прочитанные из глобального буфера захвата, освобождая место для новых данных журнала ошибок. Поэтому пользователю не следует настраивать этот буфер слишком большим, если данные из буфера журнала ошибок считываются достаточно быстро.
Обратите внимание, что уровень журнала, указанный в стандартной директиве error_log, действует и на эту функцию захвата. Она захватывает только сообщения журнала уровня не ниже, чем указанный уровень журнала в директиве error_log. Пользователь всё ещё может на лету установить более высокий уровень фильтрации журнала через функцию API Lua errlog.set_filter_level. Поэтому она более гибкая, чем статическая директива error_log.
Стоит отметить, что нет способа захватить сообщения отладки без компиляции OpenResty или Nginx с опцией ./configure --with-debug. В производственных сборках включение журналов отладки настоятельно не рекомендуется из-за высокой нагрузки.
Эта директива была впервые введена в версии v0.10.9.
lua_use_default_type
синтаксис: lua_use_default_type включено | выключено
по умолчанию: lua_use_default_type включено
контекст: http, сервер, расположение, расположение если
Определяет, следует ли использовать тип MIME, указанный директивой default_type, для значения по умолчанию заголовка ответа Content-Type. Отключите эту директиву, если заголовок ответа Content-Type по умолчанию для обработчиков запросов Lua не требуется.
Эта директива включена по умолчанию.
Эта директива была впервые введена в версии v0.9.1.
lua_malloc_trim
синтаксис: lua_malloc_trim <количество запросов>
по умолчанию: lua_malloc_trim 1000
контекст: http
Запрашивает у среды выполнения libc освободить кешированные свободные данные памяти обратно в операционную систему каждые N запросов, обрабатываемых ядром Nginx. По умолчанию, N равно 1000. Вы можете настроить количество запросов, используя свои собственные значения. Меньшие значения означают более частые освобождения, что может привести к большей загрузке процессора и меньшему объёму используемой памяти, а большие значения обычно приводят к меньшему влиянию на время работы процессора и относительно большему объёму используемой памяти. Просто настройте это значение для своих потребностей.
Настройка аргумента 0 фактически отключает периодическую очистку памяти.
lua_malloc_trim 0; # turn off trimming completely
Текущая реализация использует обработчик фазы журнала Nginx для подсчёта запросов. Поэтому появление директив log_subrequest on в nginx.conf может ускорить подсчёт, когда задействованы подзапросы. По умолчанию подсчитываются только «основные запросы».
Обратите внимание, что эта директива не влияет на память, выделенную собственным выделенным по памяти LuaJIT с помощью системного вызова mmap.
Эта директива была впервые введена в версии v0.10.7.
lua_code_cache
синтаксис: lua_code_cache включено | выключено
по умолчанию: lua_code_cache включено
контекст: http, сервер, расположение, расположение если
Включает или отключает кеширование кода Lua для кода Lua в директивах *_by_lua_file (например, set_by_lua_file и content_by_lua_file) и модулях Lua.
При отключении каждый запрос, обрабатываемый ngx_lua, будет выполняться в отдельной виртуальной машине Lua, начиная с версии 0.9.3. Таким образом, файлы Lua, на которые ссылаются директивы set_by_lua_file, content_by_lua_file, access_by_lua_file и т. д., не будут кэшироваться, и все используемые модули Lua будут загружаться с нуля. Это позволяет разработчикам использовать подход редактирования и обновления.
Однако обратите внимание, что код Lua, написанный непосредственно в nginx.conf, например, указанный в set_by_lua, content_by_lua, access_by_lua и rewrite_by_lua, не будет обновляться при редактировании встраиваемого кода Lua в вашем файле nginx.conf, так как только анализатор файла конфигурации Nginx может правильно обработать файл nginx.conf, и единственный способ — перезагрузить файл конфигурации, отправив сигнал HUP или перезапустить Nginx.
Даже при включенном кешировании кода, файлы Lua, загруженные с помощью dofile или loadfile в *_by_lua_file, не могут быть кэшированы (если вы не кэшируете результаты самостоятельно). Обычно вы можете использовать директивы init_by_lua или init_by_lua_file для загрузки всех таких файлов или просто сделать эти файлы Lua настоящими модулями Lua и загрузить их с помощью require.
Модуль ngx_lua не поддерживает режим stat, доступный с модулем Apache mod_lua (ещё нет).
Отключение кэша Lua-кода крайне нежелательно для использования в рабочей среде и должно применяться только во время разработки, так как это существенно негативно сказывается на общей производительности. Например, производительность примера Lua «hello world» может упасть на порядок величины после отключения кэша Lua-кода.
lua_regex_cache_max_entries
синтаксис: lua_regex_cache_max_entries <число>
по умолчанию: lua_regex_cache_max_entries 1024
контекст: http
Устанавливает максимальное количество записей, разрешенных в кэше скомпилированных регулярных выражений на уровне процесса-обработчика.
Регулярные выражения, используемые в ngx.re.match, ngx.re.gmatch, ngx.re.sub и ngx.re.gsub, будут кэшироваться в этом кэше, если указан параметр o (т. е., флаг компиляции один раз).
По умолчанию разрешается 1024 записи, и когда этот предел достигнут, новые регулярные выражения не будут кэшироваться (как если бы параметр o не был указан), и будет выведено одно и только одно предупреждение в файле error.log:
2011/08/27 23:18:26 [warn] 31997#0: *1 lua exceeding regex cache max entries (1024), ...
Если используется реализация ngx.re.* модуля lua-resty-core за счёт загрузки модуля resty.core.regex (или просто модуля resty.core), то используется кэш LRU для кэша регулярных выражений.
Не активируйте параметр o для регулярных выражений (и/или параметр replace для строковых аргументов ngx.re.sub и ngx.re.gsub), которые генерируются на лету и приводят к бесконечным вариациям, чтобы избежать достижения указанного предела.
lua_regex_match_limit
синтаксис: lua_regex_match_limit <число>
по умолчанию: lua_regex_match_limit 0
контекст: http
Устанавливает «предел совпадений», используемый библиотекой PCRE при выполнении API ngx.re. Цитируя справку PCRE, «предел... ограничивает количество обратных проверок, которые могут выполняться».
Когда предел достигнут, функция API ngx.re вернёт строку ошибки «pcre_exec() failed: -8» на уровне Lua.
При установке предела в 0 используется значение «предела совпадений» по умолчанию при компиляции библиотеки PCRE. Это и есть значение по умолчанию для этой директивы.
Эта директива была впервые представлена в релизе v0.8.5.
lua_package_path
синтаксис: lua_package_path <путь-в-стиле-lua>
по умолчанию: Содержимое переменной среды LUA_PATH или значения по умолчанию, скомпилированные в Lua.
контекст: http
Устанавливает путь поиска модулей Lua, используемый скриптами, указанными в set_by_lua, content_by_lua и других. Строка пути имеет стандартный формат Lua, и ;; может быть использована для обозначения исходных путей поиска.
Начиная с релиза v0.5.0rc29, в строке пути поиска можно использовать специальный символ $prefix или ${prefix} для обозначения пути к server prefix, обычно определяемого параметром командной строки -p PATH при запуске сервера Nginx.
lua_package_cpath
синтаксис: lua_package_cpath <путь-в-стиле-lua-cpath>
по умолчанию: Содержимое переменной среды LUA_CPATH или значения по умолчанию, скомпилированные в Lua.
контекст: http
Устанавливает путь поиска Lua C-модулей, используемый скриптами, указанными в set_by_lua, content_by_lua и других. Строка cpath имеет стандартный формат Lua cpath, и ;; может быть использована для обозначения исходного cpath.
Начиная с релиза v0.5.0rc29, в строке пути поиска можно использовать специальный символ $prefix или ${prefix} для обозначения пути к server prefix, обычно определяемого параметром командной строки -p PATH при запуске сервера Nginx.
init_by_lua
синтаксис: init_by_lua <lua-скрипт>
контекст: http
фаза: загрузка-конфигурации
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после релиза v0.9.17. Используйте директиву init_by_lua_block вместо неё.
Выполняет указанный Lua-код в аргументе <lua-script-str> на глобальном уровне виртуальной машины Lua, когда процесс-мастер Nginx (если есть) загружает файл конфигурации Nginx.
Когда Nginx получает сигнал HUP и начинает перезагрузку файла конфигурации, виртуальная машина Lua также будет пересоздана, и init_by_lua будет выполнена снова на новой виртуальной машине Lua. В случае отключения директивы lua_code_cache (по умолчанию включена), обработчик init_by_lua будет выполняться при каждом запросе, поскольку в этом особом режиме для каждого запроса всегда создаётся автономная виртуальная машина Lua.
Обычно с помощью этого хука вы можете предварительно загрузить Lua-модули во время запуска сервера и воспользоваться оптимизацией «копировать при записи» (COW) современных операционных систем. Вот пример предварительной загрузки Lua-модулей:
# this runs before forking out nginx worker processes:
init_by_lua_block { require "cjson" }
server {
location = /api {
content_by_lua_block {
-- the following require() will just return
-- the alrady loaded module from package.loaded:
ngx.say(require "cjson".encode{dog = 5, cat = 6})
}
}
} Вы также можете инициализировать хранилище lua_shared_dict shm на этой фазе. Вот пример для этого:
lua_shared_dict dogs 1m;
init_by_lua_block {
local dogs = ngx.shared.dogs;
dogs:set("Tom", 56)
}
server {
location = /api {
content_by_lua_block {
local dogs = ngx.shared.dogs;
ngx.say(dogs:get("Tom"))
}
}
} Однако обратите внимание, что хранилище shm lua_shared_dict не будет очищено при перезагрузке конфигурации (например, с помощью сигнала HUP). Поэтому, если вы не хотите повторно инициализировать хранилище shm в своём коде init_by_lua в этом случае, вам нужно просто установить пользовательский флаг в хранилище shm и всегда проверять этот флаг в своём коде init_by_lua.
Поскольку код Lua в этом контексте выполняется до того, как Nginx разделит свои рабочие процессы (если таковые имеются), данные или код, загруженные здесь, будут пользоваться возможностью «копировать при записи» (COW), предоставляемой многими операционными системами, во всех рабочих процессах, тем самым экономя значительное количество памяти.
Не инициализируйте свои собственные глобальные переменные Lua в этом контексте, так как это может привести к штрафам производительности и загрязнению глобального пространства имён (см. раздел Область видимости переменных Lua для получения более подробной информации). Рекомендуемый подход — использовать надлежащие файлы Lua-модулей (но не используйте стандартную Lua-функцию module() для определения Lua-модулей, поскольку она также загрязняет глобальное пространство имён) и вызывайте require() для загрузки собственных файлов модулей в init_by_lua или других контекстах (require() кэширует загруженные Lua-модули в глобальной таблице package.loaded в Lua-регистре, поэтому ваши модули будут загружаться только один раз для всего экземпляра виртуальной машины Lua).
В этом контексте поддерживается только небольшой набор API Nginx для Lua:
- API для ведения журнала: ngx.log и print,
- API для общих словарей: ngx.shared.DICT.
В будущем, по запросам пользователей, могут быть добавлены другие API Nginx для Lua.
В принципе, вы можете безопасно использовать Lua-библиотеки, которые выполняют блокирующие операции ввода-вывода в этом контексте, так как блокировка процесса-мастера во время запуска сервера вполне допустима. Даже ядро Nginx выполняет блокирующие операции ввода-вывода (по крайней мере, при разрешении имён хостов upstream) на стадии загрузки конфигурации.
Вы должны проявлять особую осторожность в отношении потенциальных уязвимостей в своём Lua-коде, зарегистрированном в этом контексте, поскольку процесс-мастер Nginx часто запускается от имени пользователя root.
Эта директива была впервые представлена в релизе v0.5.5.
init_by_lua_block
синтаксис: init_by_lua_block { lua-скрипт }
контекст: http
фаза: загрузка-конфигурации
Аналогично директиве init_by_lua, за исключением того, что эта директива вставляет Lua-код непосредственно в фигурных скобках ({}) вместо использования строки NGINX (что требует специальной эскейп-обработки символов).
Например,
init_by_lua_block {
print("I need no extra escaping here, for example: \r\nblah")
} Эта директива была впервые представлена в релизе v0.9.17.
init_by_lua_file
синтаксис: init_by_lua_file <путь-к-файлу-lua-скрипта>
контекст: http
фаза: загрузка-конфигурации
Эквивалентно init_by_lua, за исключением того, что указанный файл <path-to-lua-script-file> содержит Lua-код или байткод Lua/LuaJIT, который необходимо выполнить.
Когда задан относительный путь, как foo/bar.lua, они преобразуются в абсолютный путь относительно пути server prefix, определяемого параметром командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в релизе v0.5.5.
init_worker_by_lua
синтаксис: init_worker_by_lua <lua-скрипт>
контекст: http
фаза: запуск-рабочего-процесса
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после релиза v0.9.17. Используйте директиву init_worker_by_lua_block вместо неё.
Выполняет указанный Lua-код при запуске каждого рабочего процесса Nginx, когда включён процесс-мастер. Когда процесс-мастер отключён, этот хук выполняется после init_by_lua*.
Этот хук часто используется для создания периодических таймеров на рабочем процессе (через ngx.timer.at API Lua), например, для проверки состояния бэкенда или выполнения других задач по расписанию. Ниже приведён пример,
init_worker_by_lua '
local delay = 3 -- in seconds
local new_timer = ngx.timer.at
local log = ngx.log
local ERR = ngx.ERR
local check
check = function(premature)
if not premature then
-- do the health check or other routine work
local ok, err = new_timer(delay, check)
if not ok then
log(ERR, "failed to create timer: ", err)
return
end
end
end
local hdl, err = new_timer(delay, check)
if not hdl then
log(ERR, "failed to create timer: ", err)
return
end
'; Эта директива была впервые представлена в релизе v0.9.5.
Этот хук больше не выполняется в процессах кэширования и загрузки кэша с релиза v0.10.12.
init_worker_by_lua_block
синтаксис: init_worker_by_lua_block { lua-скрипт }
контекст: http
фаза: запуск-рабочего-процесса
Аналогично директиве init_worker_by_lua, за исключением того, что эта директива вставляет Lua-код непосредственно в фигурных скобках ({}) вместо использования строки NGINX (что требует специальной эскейп-обработки символов).
Например,
init_worker_by_lua_block {
print("I need no extra escaping here, for example: \r\nblah")
} Данная директива была впервые представлена в релизе v0.9.17.
Данный обработчик больше не выполняется в процессах менеджера кэша и загрузчика кэша с релиза v0.10.12.
init_worker_by_lua_file
синтаксис: init_worker_by_lua_file <путь-к-файлу-lua>
контекст: http
фаза: starting-worker
Аналогично init_worker_by_lua, но принимает путь к файлу исходного кода Lua или файлу Lua байткода.
Данная директива была впервые представлена в релизе v0.9.5.
Данный обработчик больше не выполняется в процессах менеджера кэша и загрузчика кэша с релиза v0.10.12.
set_by_lua
синтаксис: set_by_lua $res <строка-скрипта-lua> [$arg1 $arg2 ...]
контекст: сервер, сервер если, местоположение, местоположение если
фаза: перезапись
ПРИМЕЧАНИЕ Использование данной директивы не рекомендуется после релиза v0.9.17. Используйте вместо неё директиву set_by_lua_block.
Выполняет код, указанный в <lua-script-str> с необязательными входными аргументами $arg1 $arg2 ..., и возвращает строковый вывод в $res. Код в <lua-script-str> может выполнять вызовы API и может извлекать входные аргументы из таблицы ngx.arg (индекс начинается с 1 и увеличивается последовательно).
Данная директива предназначена для выполнения коротких, быстро выполняемых блоков кода, так как цикл обработки событий Nginx блокируется во время выполнения кода. Следовательно, следует избегать длительных последовательностей кода.
Данная директива реализуется путём вставки пользовательских команд в стандартный список команд ngx_http_rewrite_module. Поскольку ngx_http_rewrite_module не поддерживает асинхронное ввод-вывод в своих командах, функции Lua API, требующие приостановки текущей "лёгкой нити" Lua, не могут работать в данной директиве.
По меньшей мере, следующие функции API в настоящее время отключены в контексте set_by_lua:
- Функции API вывода (например, ngx.say и ngx.send_headers)
- Функции API управления (например, ngx.exit)
- Функции API подзапросов (например, ngx.location.capture и ngx.location.capture_multi)
- Функции API сокетов (например, ngx.socket.tcp и ngx.req.socket).
- Функция сна ngx.sleep.
Кроме того, обратите внимание, что данная директива может записывать значение только в одну переменную Nginx за раз. Однако возможен обходной путь, используя интерфейс ngx.var.VARIABLE.
location /foo {
set $diff ''; # we have to predefine the $diff variable here
set_by_lua $sum '
local a = 32
local b = 56
ngx.var.diff = a - b; -- write to $diff directly
return a + b; -- return the $sum value normally
';
echo "sum = $sum, diff = $diff";
} Данная директива может быть свободно смешана со всеми директивами модулей ngx_http_rewrite_module, set-misc-nginx-module и array-var-nginx-module. Все эти директивы будут выполняться в том же порядке, что и в файле конфигурации.
set $foo 32; set_by_lua $bar 'return tonumber(ngx.var.foo) + 1'; set $baz "bar: $bar"; # $baz == "bar: 33"
Начиная с релиза v0.5.0rc29, интерполяция переменных Nginx отключена в аргументе <lua-script-str> данной директивы, и поэтому знак доллара ($) может использоваться непосредственно.
Для данной директивы требуется модуль ngx_devel_kit.
set_by_lua_block
синтаксис: set_by_lua_block $res { код-скрипта-lua }
контекст: сервер, сервер если, местоположение, местоположение если
фаза: перезапись
Аналогично директиве set_by_lua за исключением
- данная директива встраивает исходный код Lua непосредственно внутри пары фигурных скобок (
{}) вместо строки NGINX (что требует специального экранирования символов), и - данная директива не поддерживает дополнительные аргументы после скрипта Lua, как в set_by_lua.
Например,
set_by_lua_block $res { return 32 + math.cos(32) }
# $res now has the value "32.834223360507" or alike. В блоке кода Lua не требуется специальное экранирование.
Данная директива была впервые представлена в релизе v0.9.17.
set_by_lua_file
синтаксис: set_by_lua_file $res <путь-к-файлу-скрипта-lua> [$arg1 $arg2 ...]
контекст: сервер, сервер если, местоположение, местоположение если
фаза: перезапись
Эквивалентно set_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит код Lua или, начиная с релиза v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Интерполяция переменных Nginx поддерживается в строке аргумента <path-to-lua-script-file> данной директивы. Однако необходимо проявлять особую осторожность при атаках с внедрением кода.
Когда задан относительный путь, как foo/bar.lua, он будет преобразован в абсолютный путь относительно пути server prefix, определённого параметром командной строки -p PATH при запуске сервера Nginx.
Если кеширование кода Lua включено (по умолчанию), пользовательский код загружается один раз при первом запросе и кэшируется, а конфигурация Nginx должна перезагружаться каждый раз, когда изменяется исходный файл Lua. Кэширование кода Lua можно временно отключить во время разработки, переключив lua_code_cache off в nginx.conf, чтобы избежать перезагрузки Nginx.
Для данной директивы требуется модуль ngx_devel_kit.
content_by_lua
синтаксис: content_by_lua <строка-скрипта-lua>
контекст: местоположение, местоположение если
фаза: содержимое
ПРИМЕЧАНИЕ Использование данной директивы не рекомендуется после релиза v0.9.17. Используйте вместо неё директиву content_by_lua_block.
Выступает в роли "обработчика содержимого" и выполняет строку кода Lua, указанную в <lua-script-str> для каждого запроса. Код Lua может выполнять вызовы API и выполняется как новая порождённая корутина в независимой глобальной среде (т. е. в песочнице).
Не используйте эту директиву и другие директивы обработчиков содержимого в одном местеположения. Например, данную директиву и директиву proxy_pass не следует использовать в одном местеположения.
content_by_lua_block
синтаксис: content_by_lua_block { код-скрипта-lua }
контекст: местоположение, местоположение если
фаза: содержимое
Аналогично директиве content_by_lua, за исключением того, что данная директива встраивает исходный код Lua непосредственно внутри пары фигурных скобок ({}) вместо строки NGINX (что требует специального экранирования символов).
Например,
content_by_lua_block {
ngx.say("I need no extra escaping here, for example: \r\nblah")
} Данная директива была впервые представлена в релизе v0.9.17.
content_by_lua_file
синтаксис: content_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: местоположение, местоположение если
фаза: содержимое
Эквивалентно content_by_lua, за исключением того, что в файле, указанном в <path-to-lua-script-file>, содержится код Lua или, начиная с релиза v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Переменные Nginx могут использоваться в строке <path-to-lua-script-file> для обеспечения гибкости. Однако это несёт некоторые риски и не рекомендуется в обычных ситуациях.
Если задан относительный путь, как foo/bar.lua, он будет преобразован в абсолютный путь относительно пути server prefix, определённого параметром командной строки -p PATH при запуске сервера Nginx.
При включённом кешировании кода Lua (по умолчанию) пользовательский код загружается один раз при первом запросе и кэшируется. Конфигурацию Nginx необходимо перезагружать каждый раз, когда изменяется исходный файл Lua. Кэширование кода Lua можно временно отключить во время разработки, переключив lua_code_cache off в nginx.conf, чтобы избежать перезагрузки Nginx.
Переменные Nginx поддерживаются в пути к файлу для динамической маршрутизации, например:
# 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;
} Но будьте очень внимательны к вредоносным пользовательским входам и всегда тщательно проверяйте или фильтруйте пользовательские компоненты пути.
rewrite_by_lua
синтаксис: rewrite_by_lua <строка-скрипта-lua>
контекст: http, сервер, местоположение, местоположение если
фаза: перезапись хвост
ПРИМЕЧАНИЕ Использование данной директивы не рекомендуется после релиза v0.9.17. Используйте вместо неё директиву rewrite_by_lua_block.
Выступает в роли обработчика фазы перезаписи и выполняет строку кода Lua, указанную в <lua-script-str> для каждого запроса. Код Lua может выполнять вызовы API и выполняется как новая порождённая корутина в независимой глобальной среде (т. е. в песочнице).
Обратите внимание, что данный обработчик всегда выполняется после стандартного ngx_http_rewrite_module. Поэтому следующее будет работать как ожидается:
location /foo {
set $a 12; # create and initialize $a
set $b ""; # create and initialize $b
rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1';
echo "res = $b";
} потому что set $a 12 и set $b "" выполняются до rewrite_by_lua.
С другой стороны, следующее не будет работать как ожидается:
? location /foo {
? set $a 12; # create and initialize $a
? set $b ''; # create and initialize $b
? rewrite_by_lua 'ngx.var.b = tonumber(ngx.var.a) + 1';
? if ($b = '13') {
? rewrite ^ /bar redirect;
? break;
? }
?
? echo "res = $b";
? } потому что if выполняется до rewrite_by_lua, даже если оно размещено после rewrite_by_lua в конфигурации.
Правильный способ сделать это:
location /foo {
set $a 12; # create and initialize $a
set $b ''; # create and initialize $b
rewrite_by_lua '
ngx.var.b = tonumber(ngx.var.a) + 1
if tonumber(ngx.var.b) == 13 then
return ngx.redirect("/bar");
end
';
echo "res = $b";
} Обратите внимание, что модуль ngx_eval можно приблизительно заменить с помощью rewrite_by_lua. Например,
location / {
eval $res {
proxy_pass http://foo.com/check-spam;
}
if ($res = 'spam') {
rewrite ^ /terms-of-use.html redirect;
}
fastcgi_pass ...;
} можно реализовать в ngx_lua как:
location = /check-spam {
internal;
proxy_pass http://foo.com/check-spam;
}
location / {
rewrite_by_lua '
local res = ngx.location.capture("/check-spam")
if res.body == "spam" then
return ngx.redirect("/terms-of-use.html")
end
';
fastcgi_pass ...;
} Как и любой другой обработчик фазы перезаписи, rewrite_by_lua также выполняется в подзапросах.
Обратите внимание, что при вызове ngx.exit(ngx.OK) внутри обработчика rewrite_by_lua, поток обработки запроса nginx всё равно будет продолжен в обработчик контента. Чтобы завершить текущий запрос внутри обработчика rewrite_by_lua, нужно вызвать ngx.exit со статусом >= 200 (ngx.HTTP_OK) и статусом < 300 (ngx.HTTP_SPECIAL_RESPONSE) для успешного выхода и ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (или его аналоги) для ошибок.
Если используется директива ngx_http_rewrite_module's rewrite для изменения URI и запуска пересчёта местоположения (внутренние перенаправления), то любые последовательности кода rewrite_by_lua или rewrite_by_lua_file внутри текущего местоположения не будут выполнены. Например,
location /foo {
rewrite ^ /bar;
rewrite_by_lua 'ngx.exit(503)';
}
location /bar {
...
} Здесь Lua код ngx.exit(503) никогда не будет выполнен. Это произойдёт, если rewrite ^ /bar last используется, так как это аналогично инициирует внутреннее перенаправление. Если используется модификатор break, то внутреннего перенаправления не будет и код rewrite_by_lua будет выполнен.
Код rewrite_by_lua всегда будет выполнен в конце фазы обработки запроса rewrite, если не включён rewrite_by_lua_no_postpone.
rewrite_by_lua_block
синтаксис: rewrite_by_lua_block { lua-скрипт }
контекст: http, server, location, location if
фаза: rewrite tail
Аналогично директиве rewrite_by_lua, за исключением того, что эта директива встраивает исходный код Lua непосредственно внутри пар фигурных скобок ({}) вместо строковой константы NGINX (которая требует экранирования специальных символов).
Например,
rewrite_by_lua_block {
do_something("hello, world!\nhiya\n")
} Эта директива была впервые представлена в релизе v0.9.17.
rewrite_by_lua_file
синтаксис: rewrite_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: http, server, location, location if
фаза: rewrite tail
Эквивалентно rewrite_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит Lua код, или, начиная с релиза v0.5.0rc32, Lua/LuaJIT байткод для выполнения.
Переменные Nginx могут использоваться в строке <path-to-lua-script-file> для большей гибкости. Однако это несёт определённые риски и не рекомендуется в обычных случаях.
Когда задан относительный путь, например, foo/bar.lua, он будет преобразован в абсолютный путь, относительно пути server prefix, определённого параметром командной строки -p PATH при запуске сервера Nginx.
Когда кеширование Lua кода включено (по умолчанию), пользовательский код загружается один раз при первом запросе и кэшируется, а конфигурация Nginx должна быть перезагружена каждый раз, когда исходный файл Lua изменяется. Кэширование Lua кода можно временно отключить во время разработки, переключив lua_code_cache off в nginx.conf, чтобы избежать повторной загрузки Nginx.
Код rewrite_by_lua_file всегда будет выполняться в конце фазы обработки запроса rewrite, если не включён rewrite_by_lua_no_postpone.
Переменные Nginx поддерживаются в пути к файлу для динамической диспетчеризации так же, как и в content_by_lua_file.
access_by_lua
синтаксис: access_by_lua <lua-скрипт-строка>
контекст: http, server, location, location if
фаза: access tail
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после релиза v0.9.17. Используйте директиву access_by_lua_block вместо неё.
Выступает как обработчик фазы доступа и выполняет строку Lua-кода, указанную в <lua-script-str> для каждого запроса. Lua код может выполнять API-вызовы и выполняется как новый запущенный сопроцесс в независимой глобальной среде (т.е. в песочнице).
Обратите внимание, что этот обработчик всегда выполняется после стандартного ngx_http_access_module. Поэтому следующее будет работать как ожидается:
location / {
deny 192.168.1.1;
allow 192.168.1.0/24;
allow 10.1.1.0/16;
deny all;
access_by_lua '
local res = ngx.location.capture("/mysql", { ... })
...
';
# proxy_pass/fastcgi_pass/...
} То есть, если адрес IP клиента находится в чёрном списке, он будет отклонен до выполнения MySQL запроса для более сложной аутентификации, выполняемого access_by_lua.
Обратите внимание, что модуль ngx_auth_request можно приблизительно реализовать с помощью access_by_lua:
location / {
auth_request /auth;
# proxy_pass/fastcgi_pass/postgres_pass/...
} может быть реализовано в ngx_lua как:
location / {
access_by_lua '
local res = ngx.location.capture("/auth")
if res.status == ngx.HTTP_OK then
return
end
if res.status == ngx.HTTP_FORBIDDEN then
ngx.exit(res.status)
end
ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
';
# proxy_pass/fastcgi_pass/postgres_pass/...
} Как и другие обработчики фазы доступа, access_by_lua не будет выполняться в подзапросах.
Обратите внимание, что при вызове ngx.exit(ngx.OK) внутри обработчика access_by_lua, поток обработки запроса nginx всё равно будет продолжен в обработчик контента. Чтобы завершить текущий запрос внутри обработчика access_by_lua, нужно вызвать ngx.exit со статусом >= 200 (ngx.HTTP_OK) и статусом < 300 (ngx.HTTP_SPECIAL_RESPONSE) для успешного выхода и ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR) (или его аналоги) для ошибок.
Начиная с релиза v0.9.20, вы можете использовать директиву access_by_lua_no_postpone для управления временем выполнения этого обработчика внутри фазы обработки запроса "access" NGINX.
access_by_lua_block
синтаксис: access_by_lua_block { lua-скрипт }
контекст: http, server, location, location if
фаза: access tail
Аналогично директиве access_by_lua, за исключением того, что эта директива встраивает исходный код Lua непосредственно внутри пар фигурных скобок ({}) вместо строковой константы NGINX (которая требует экранирования специальных символов).
Например,
access_by_lua_block {
do_something("hello, world!\nhiya\n")
} Эта директива была впервые представлена в релизе v0.9.17.
access_by_lua_file
синтаксис: access_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: http, server, location, location if
фаза: access tail
Эквивалентно access_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит Lua код, или, начиная с релиза v0.5.0rc32, Lua/LuaJIT байткод для выполнения.
Переменные Nginx могут использоваться в строке <path-to-lua-script-file> для большей гибкости. Однако это несёт определённые риски и не рекомендуется в обычных случаях.
Когда задан относительный путь, например, foo/bar.lua, он будет преобразован в абсолютный путь, относительно пути server prefix, определённого параметром командной строки -p PATH при запуске сервера Nginx.
Когда кеширование Lua кода включено (по умолчанию), пользовательский код загружается один раз при первом запросе и кэшируется, а конфигурация Nginx должна быть перезагружена каждый раз, когда исходный файл Lua изменяется. Кэширование Lua кода можно временно отключить во время разработки, переключив lua_code_cache off в nginx.conf, чтобы избежать повторной загрузки Nginx.
Переменные Nginx поддерживаются в пути к файлу для динамической диспетчеризации так же, как и в content_by_lua_file.
header_filter_by_lua
синтаксис: header_filter_by_lua <lua-скрипт-строка>
контекст: http, server, location, location if
фаза: output-header-filter
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после релиза v0.9.17. Используйте директиву header_filter_by_lua_block вместо неё.
Использует Lua код, указанный в <lua-script-str>, для определения фильтра выходных заголовков.
Обратите внимание, что следующие функции API в настоящее время отключены в этом контексте:
- Функции API вывода (например, ngx.say и ngx.send_headers)
- Функции API управления (например, ngx.redirect и ngx.exec)
- Функции API подзапросов (например, ngx.location.capture и ngx.location.capture_multi)
- Функции API сокетов (например, ngx.socket.tcp и ngx.req.socket).
Вот пример переопределения заголовка ответа (или добавления его, если он отсутствует) в нашем Lua фильтре заголовков:
location / {
proxy_pass http://mybackend;
header_filter_by_lua 'ngx.header.Foo = "blah"';
} Эта директива была впервые представлена в релизе v0.2.1rc20.
header_filter_by_lua_block
синтаксис: header_filter_by_lua_block { lua-скрипт }
контекст: http, server, location, location if
фаза: output-header-filter
Аналогично директиве header_filter_by_lua, за исключением того, что эта директива встраивает исходный код Lua непосредственно внутри пар фигурных скобок ({}) вместо строковой константы NGINX (которая требует экранирования специальных символов).
Например,
header_filter_by_lua_block {
ngx.header["content-length"] = nil
} Эта директива была впервые представлена в релизе v0.9.17.
header_filter_by_lua_file
синтаксис: header_filter_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: http, server, location, location if
фаза: output-header-filter
Эквивалентно header_filter_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит Lua код, или, начиная с релиза v0.5.0rc32, Lua/LuaJIT байткод для выполнения.
Когда задан относительный путь, например, foo/bar.lua, он будет преобразован в абсолютный путь, относительно пути server prefix, определённого параметром командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в релизе v0.2.1rc20.
body_filter_by_lua
синтаксис: body_filter_by_lua <lua-скрипт-строка>
контекст: http, server, location, location if
фаза: output-body-filter
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после выпуска v0.9.17. Используйте директиву body_filter_by_lua_block вместо неё.
Использует код Lua, указанный в <lua-script-str>, для определения фильтра тела ответа.
Входные данные передаются через ngx.arg[1] (как строковое значение Lua) и флаг "eof", указывающий конец потока данных тела ответа, передаётся через ngx.arg[2] (как булево значение Lua).
На самом деле, флаг "eof" просто last_buf (для основных запросов) или last_in_chain (для дочерних запросов) флаг буферов цепочки Nginx. (До релиза v0.7.14, флаг "eof" вообще не работал в дочерних запросах.)
Поток выходных данных может быть прерван немедленно, выполнив следующую инструкцию Lua:
return ngx.ERROR
Это обрезает тело ответа и обычно приводит к неполным и недействительным ответам.
Код Lua может передать собственную изменённую версию фрагмента входных данных в последующие фильтры тела Nginx, переопределяя ngx.arg[1] строкой Lua или таблицей строк Lua. Например, чтобы преобразовать все строчные буквы в теле ответа, можно написать:
location / {
proxy_pass http://mybackend;
body_filter_by_lua 'ngx.arg[1] = string.upper(ngx.arg[1])';
} При установке nil или пустого значения строки Lua в ngx.arg[1], фрагмент данных вообще не будет передан последующим фильтрам Nginx.
Аналогично, новый флаг "eof" также может быть задан, установив булевое значение в ngx.arg[2]. Например,
location /t {
echo hello world;
echo hiya globe;
body_filter_by_lua '
local chunk = ngx.arg[1]
if string.match(chunk, "hello") then
ngx.arg[2] = true -- new eof
return
end
-- just throw away any remaining chunk data
ngx.arg[1] = nil
';
} Тогда GET /t вернёт результат
hello world
То есть, когда фильтр тела видит фрагмент, содержащий слово "hello", он сразу устанавливает флаг "eof" в значение true, что приводит к обрезке, но всё же корректным ответам.
Когда код Lua может изменить длину тела ответа, необходимо всегда очищать заголовок ответа Content-Length (если таковой имеется) в фильтре заголовков, чтобы обеспечить потоковую передачу вывода, как в
location /foo {
# fastcgi_pass/proxy_pass/...
header_filter_by_lua_block { ngx.header.content_length = nil }
body_filter_by_lua 'ngx.arg[1] = string.len(ngx.arg[1]) .. "\\n"';
} Обратите внимание, что следующие функции API в настоящее время отключены в этом контексте из-за ограничений текущей реализации фильтра вывода NGINX:
- Функции API вывода (например, ngx.say и ngx.send_headers)
- Функции API управления (например, ngx.exit и ngx.exec)
- Функции API дочерних запросов (например, ngx.location.capture и ngx.location.capture_multi)
- Функции API сокетов (например, ngx.socket.tcp и ngx.req.socket).
Фильтры вывода Nginx могут вызываться несколько раз для одного запроса, потому что тело ответа может передаваться частями. Таким образом, код Lua, указанный в этой директиве, также может выполняться несколько раз в течение жизненного цикла одного HTTP-запроса.
Эта директива была впервые представлена в выпуске v0.5.0rc32.
body_filter_by_lua_block
синтаксис: body_filter_by_lua_block { lua-script-str }
контекст: http, server, location, location if
фаза: output-body-filter
Аналогично директиве body_filter_by_lua, за исключением того, что эта директива вставляет исходный код Lua непосредственно в пару фигурных скобок ({}) вместо строки NGINX (которая требует экранирования специальных символов).
Например,
body_filter_by_lua_block {
local data, eof = ngx.arg[1], ngx.arg[2]
} Эта директива была впервые представлена в выпуске v0.9.17.
body_filter_by_lua_file
синтаксис: body_filter_by_lua_file <path-to-lua-script-file>
контекст: http, server, location, location if
фаза: output-body-filter
Эквивалентно body_filter_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит код Lua или, начиная с выпуска v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Если задан относительный путь, например, foo/bar.lua, они будут преобразуются в абсолютный путь относительно пути server prefix, определенного опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в выпуске v0.5.0rc32.
log_by_lua
синтаксис: log_by_lua <lua-script-str>
контекст: http, server, location, location if
фаза: log
ПРИМЕЧАНИЕ Использование этой директивы не рекомендуется после выпуска v0.9.17. Используйте директиву log_by_lua_block вместо неё.
Выполняет код Lua, указанный как <lua-script-str>, на фазе обработки запросов log. Это не заменяет текущие логи доступа, но выполняется до них.
Обратите внимание, что следующие функции API в настоящее время отключены в этом контексте:
- Функции API вывода (например, ngx.say и ngx.send_headers)
- Функции API управления (например, ngx.exit)
- Функции API дочерних запросов (например, ngx.location.capture и ngx.location.capture_multi)
- Функции API сокетов (например, ngx.socket.tcp и ngx.req.socket).
Вот пример сбора средних данных для $upstream_response_time:
lua_shared_dict log_dict 5M;
server {
location / {
proxy_pass http://mybackend;
log_by_lua '
local log_dict = ngx.shared.log_dict
local upstream_time = tonumber(ngx.var.upstream_response_time)
local sum = log_dict:get("upstream_time-sum") or 0
sum = sum + upstream_time
log_dict:set("upstream_time-sum", sum)
local newval, err = log_dict:incr("upstream_time-nb", 1)
if not newval and err == "not found" then
log_dict:add("upstream_time-nb", 0)
log_dict:incr("upstream_time-nb", 1)
end
';
}
location = /status {
content_by_lua_block {
local log_dict = ngx.shared.log_dict
local sum = log_dict:get("upstream_time-sum")
local nb = log_dict:get("upstream_time-nb")
if nb and sum then
ngx.say("average upstream response time: ", sum / nb,
" (", nb, " reqs)")
else
ngx.say("no data yet")
end
}
}
} Эта директива была впервые представлена в выпуске v0.5.0rc31.
log_by_lua_block
синтаксис: log_by_lua_block { lua-script }
контекст: http, server, location, location if
фаза: log
Аналогично директиве log_by_lua, за исключением того, что эта директива вставляет исходный код Lua непосредственно в пару фигурных скобок ({}) вместо строки NGINX (которая требует экранирования специальных символов).
Например,
log_by_lua_block {
print("I need no extra escaping here, for example: \r\nblah")
} Эта директива была впервые представлена в выпуске v0.9.17.
log_by_lua_file
синтаксис: log_by_lua_file <path-to-lua-script-file>
контекст: http, server, location, location if
фаза: log
Эквивалентно log_by_lua, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит код Lua или, начиная с выпуска v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Если задан относительный путь, например, foo/bar.lua, они будут преобразуются в абсолютный путь относительно пути server prefix, определенного опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в выпуске v0.5.0rc31.
balancer_by_lua_block
синтаксис: balancer_by_lua_block { lua-script }
контекст: upstream
фаза: content
Эта директива выполняет код Lua в качестве балансировщика обращений для любых сущностей upstream, определённых в блоке конфигурации upstream {}.
Например,
upstream foo {
server 127.0.0.1;
balancer_by_lua_block {
-- use Lua to do something interesting here
-- as a dynamic balancer
}
}
server {
location / {
proxy_pass http://foo;
}
} Получившийся балансировщик на Lua может работать с любыми существующими модулями nginx upstream, такими как ngx_proxy и ngx_fastcgi.
Кроме того, балансировщик на Lua может работать со стандартным механизмом пула подключений upstream, т. е. со стандартной директивой keepalive. Просто убедитесь, что директива keepalive используется после этой balancer_by_lua_block директивы в одном блоке конфигурации upstream {}.
Балансировщик на Lua может полностью игнорировать список серверов, определённый в блоке upstream {}, и выбирать peer из полностью динамического списка серверов (даже меняющегося по запросу) через модуль ngx.balancer из библиотеки lua-resty-core.
Обработчик кода Lua, зарегистрированный этой директивой, может вызываться более одного раза в одном запросе от downstream, когда механизм nginx upstream повторно пытается обработать запрос по условиям, указанным в таких директивах, как proxy_next_upstream.
В этом контексте выполнения Lua не поддерживается приостановление, поэтому API Lua, которые могут приостанавливаться (например, сокеты и «лёгкие потоки»), отключены в этом контексте. Обычно можно обойти это ограничение, выполняя такие операции в обработчике ранней фазы (например, access_by_lua*) и передавая результат в этот контекст через таблицу ngx.ctx.
Эта директива была впервые представлена в выпуске v0.10.0.
balancer_by_lua_file
синтаксис: balancer_by_lua_file <path-to-lua-script-file>
контекст: upstream
фаза: content
Эквивалентно balancer_by_lua_block, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит код Lua или, начиная с выпуска v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Если задан относительный путь, например, foo/bar.lua, они будут преобразуются в абсолютный путь относительно пути server prefix, определенного опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в выпуске v0.10.0.
lua_need_request_body
синтаксис: lua_need_request_body <on|off>
по умолчанию: off
контекст: http, server, location, location if
фаза: зависит от использования
Определяет, нужно ли принудительно считывать данные тела запроса перед выполнением переписывания/доступа/access_by_lua* или нет. По умолчанию ядро Nginx не считывает тело запроса клиента, и если данные тела запроса необходимы, то этот директиву нужно включить on или вызвать функцию ngx.req.read_body в Lua-коде.
Для чтения данных тела запроса в переменной $request_body значение client_body_buffer_size должно быть таким же, как и значение client_max_body_size. Это потому, что когда длина содержимого превышает client_body_buffer_size, но меньше client_max_body_size, Nginx буферизует данные в временный файл на диске, что приведёт к пустому значению в переменной $request_body.
Если текущий URI содержит директивы rewrite_by_lua*, то тело запроса будет считано непосредственно перед выполнением кода rewrite_by_lua* (и также на фазе rewrite). Аналогично, если указан только content_by_lua, тело запроса не будет считано до тех пор, пока не будет выполнено Lua-код обработчика содержимого (т.е., тело запроса будет считано на фазе обработки содержимого).
Тем не менее, рекомендуется использовать функции ngx.req.read_body и ngx.req.discard_body для более точного управления процессом чтения тела запроса.
Это также относится к access_by_lua*.
ssl_certificate_by_lua_block
синтаксис: ssl_certificate_by_lua_block { lua-script }
контекст: server
фаза: right-before-SSL-handshake
Эта директива выполняет пользовательский Lua-код, когда NGINX собирается начать SSL-рукопожатие для последующих SSL (https) соединений.
Это особенно полезно для установки цепочки SSL-сертификатов и соответствующего закрытого ключа на основе каждого запроса. Это также полезно для неблокирующей загрузки таких конфигураций рукопожатия из удалённого источника (например, с помощью API cosocket). И здесь же можно выполнить обработку OCSP-подтверждения на основе каждого запроса в чистом Lua.
Другой типичный случай использования — неблокирующий контроль трафика SSL-рукопожатия в этом контексте, например, с помощью библиотеки lua-resty-limit-traffic#readme.
Можно также выполнить интересные действия с запросами SSL-рукопожатия со стороны клиента, например, выборочно отклонять старые SSL-клиенты, использующие протокол SSLv3 или даже ниже.
Модули Lua ngx.ssl и ngx.ocsp, предоставляемые библиотекой lua-resty-core, особенно полезны в этом контексте. Вы можете использовать Lua-API, предлагаемые этими двумя Lua-модулями, для управления цепочкой SSL-сертификатов и закрытым ключом для текущего инициируемого SSL-соединения.
Однако, этот Lua-обработчик вообще не выполняется, когда NGINX/OpenSSL успешно возобновляет SSL-сессию через идентификаторы SSL-сессий или билеты TLS-сессий для текущего SSL-соединения. Другими словами, этот Lua-обработчик выполняется только тогда, когда NGINX должен инициировать полное SSL-рукопожатие.
Ниже приведён тривиальный пример с использованием модуля ngx.ssl:
server {
listen 443 ssl;
server_name test.com;
ssl_certificate_by_lua_block {
print("About to initiate a new SSL handshake!")
}
location / {
root html;
}
} Более сложные примеры можно найти в официальной документации Lua-модулей ngx.ssl и ngx.ocsp.
Необработанные Lua-исключения в пользовательском Lua-коде немедленно прерывают текущую SSL-сессию, как и вызов ngx.exit с кодом ошибки, например, ngx.ERROR.
Этот контекст выполнения Lua-кода поддерживает приостановку, поэтому Lua-API, которые могут приостанавливаться (например, сокеты, засыпание и "лёгкие потоки"), разрешены в этом контексте.
Однако, вам всё ещё необходимо настроить директивы ssl_certificate и ssl_certificate_key, даже если вы вообще не будете использовать этот статический сертификат и закрытый ключ. Это связано с тем, что ядру NGINX необходим их вид, иначе при запуске NGINX будет показана следующая ошибка:
nginx: [emerg] no ssl configured for the server
Для корректной работы этой директивы в настоящее время требуется следующая настройка ядра NGINX:
http://mailman.nginx.org/pipermail/nginx-devel/2016-January/007748.html
В собранной версии ядра NGINX в OpenResty 1.9.7.2 (или выше) эта настройка уже применена.
Кроме того, для работы этой директивы требуется как минимум OpenSSL 1.0.2e.
Эта директива была впервые представлена в версии v0.10.0.
ssl_certificate_by_lua_file
синтаксис: ssl_certificate_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: server
фаза: right-before-SSL-handshake
Аналогично ssl_certificate_by_lua_block, за исключением того, что файл, указанный по адресу <path-to-lua-script-file>, содержит Lua-код, или, начиная с версии v0.5.0rc32, байткод Lua/LuaJIT для выполнения.
Когда задаётся относительный путь, например, foo/bar.lua, он преобразуется в абсолютный путь, относительный к пути server prefix, определённому опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в версии v0.10.0.
ssl_session_fetch_by_lua_block
синтаксис: ssl_session_fetch_by_lua_block { lua-script }
контекст: http
фаза: right-before-SSL-handshake
Эта директива выполняет Lua-код для поиска и загрузки SSL-сессии (если таковая имеется) в соответствии с идентификатором сессии, предоставленным текущим запросом SSL-рукопожатия для последующего соединения.
Lua-API для получения текущего идентификатора сессии и загрузки данных кэшированной SSL-сессии предоставляется в Lua-модуле ngx.ssl.session, поставляемом с библиотекой lua-resty-core.
Lua-API, которые могут приостанавливаться, например, ngx.sleep и cosockets, разрешены в этом контексте.
Этот обработчик, вместе с обработчиком ssl_session_store_by_lua*, может использоваться для реализации механизмов распределённого кэширования в чистом Lua (например, на основе API cosocket). Если кэшированная SSL-сессия найдена и загружена в контекст текущего SSL-соединения, возобновление SSL-сессии может быть немедленно инициировано, минуя процесс полного SSL-рукопожатия, который является очень затратным с точки зрения времени ЦП.
Обратите внимание, что билеты TLS-сессий сильно отличаются, и ответственность за кэширование состояния SSL-сессии лежит на клиентах, когда используются билеты TLS-сессий. Возобновление SSL-сессий на основе билетов TLS-сессий происходит автоматически, без прохождения через этот обработчик (ни через обработчик ssl_session_store_by_lua_block). Этот обработчик в основном предназначен для более старых или менее мощных SSL-клиентов, которые могут выполнять SSL-сессии только по идентификаторам сессий.
Когда ssl_certificate_by_lua* указан одновременно, этот обработчик обычно выполняется до ssl_certificate_by_lua*. Если SSL-сессия найдена и успешно загружена для текущего SSL-соединения, возобновление SSL-сессии произойдёт, и, таким образом, обработчик ssl_certificate_by_lua* будет пропущен полностью. В этом случае NGINX также пропускает обработчик ssl_session_store_by_lua_block по понятным причинам.
Для лёгкого тестирования этого обработчика локально с современным веб-браузером, можно временно добавить следующую строку в блок конфигурации сервера https, чтобы отключить поддержку билетов TLS-сессий:
ssl_session_tickets off;
Но не забудьте закомментировать эту строку перед публикацией вашего сайта в глобальную сеть.
Если вы используете официальные предварительно скомпилированные пакеты для OpenResty 1.11.2.1 или более поздних версий, всё должно работать из коробки.
Если вы используете библиотеки OpenSSL, не предоставленные OpenResty, вам необходимо применить следующую настройку для OpenSSL 1.0.2h или более поздних версий:
Если вы не используете ядро NGINX, поставляемое с OpenResty 1.11.2.1 или более поздними версиями, вам необходимо применить следующую настройку к стандартному ядру NGINX 1.11.2 или более поздним версиям:
http://openresty.org/download/nginx-1.11.2-nonblocking_ssl_handshake_hooks.patch
Эта директива была впервые представлена в версии v0.10.6.
Обратите внимание: эта директива разрешена только в контексте http с версии v0.10.7 (потому что возобновление SSL-сессии происходит до обработки имени сервера).
ssl_session_fetch_by_lua_file
синтаксис: ssl_session_fetch_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: http
фаза: right-before-SSL-handshake
Аналогично ssl_session_fetch_by_lua_block, за исключением того, что файл, указанный по адресу <path-to-lua-script-file>, содержит Lua-код, а точнее, байткод Lua/LuaJIT для выполнения.
Когда задаётся относительный путь, например, foo/bar.lua, он преобразуется в абсолютный путь, относительный к пути server prefix, определённому опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в релизе v0.10.6.
Обратите внимание: эта директива разрешена только для использования в контексте http с релиза v0.10.7 (поскольку возобновление сеанса SSL происходит до распределения имени сервера).
ssl_session_store_by_lua_block
синтаксис: ssl_session_store_by_lua_block { lua-скрипт }
контекст: http
фаза: сразу после рукопожатия SSL
Эта директива выполняет код Lua для извлечения и сохранения сеанса SSL (если таковой имеется) в соответствии с идентификатором сеанса, предоставленным текущим запросом рукопожатия SSL для последующего соединения. Сохранённые или кэшированные данные сеанса SSL могут использоваться для возобновления сеансов SSL в будущих подключениях без прохождения полного процесса рукопожатия SSL (что очень затратно с точки зрения времени ЦП).
API Lua, которые могут приостанавливать выполнение, такие как ngx.sleep и cosockets, отключены в этом контексте. Однако вы по-прежнему можете использовать API ngx.timer.at для создания таймеров с задержкой 0 для асинхронного сохранения данных сеанса SSL во внешние службы (например, redis или memcached).
API Lua для получения текущего идентификатора сеанса и связанных данных состояния сеанса предоставляется в модуле Lua ngx.ssl.session, поставляемом с библиотекой lua-resty-core.
Чтобы легко протестировать этот обработчик локально с современным веб-браузером, вы можете временно добавить следующую строку в свой блок сервера https для отключения поддержки билетов сеанса TLS:
ssl_session_tickets off;
Но не забудьте закомментировать эту строку перед публикацией вашего сайта в глобальную сеть.
Эта директива была впервые представлена в релизе v0.10.6.
Обратите внимание: эта директива разрешена только для использования в контексте http с релиза v0.10.7 (поскольку возобновление сеанса SSL происходит до распределения имени сервера).
ssl_session_store_by_lua_file
синтаксис: ssl_session_store_by_lua_file <путь-к-файлу-скрипта-lua>
контекст: http
фаза: сразу после рукопожатия SSL
Эквивалентно ssl_session_store_by_lua_block, за исключением того, что файл, указанный в <path-to-lua-script-file>, содержит код Lua, или, точнее, байткод Lua/LuaJIT для выполнения.
Когда указывается относительный путь, например foo/bar.lua, они будут преобразованы в абсолютный путь, относительный к пути server prefix, определяемому опцией командной строки -p PATH при запуске сервера Nginx.
Эта директива была впервые представлена в релизе v0.10.6.
Обратите внимание: эта директива разрешена только для использования в контексте http с релиза v0.10.7 (поскольку возобновление сеанса SSL происходит до распределения имени сервера).
lua_shared_dict
синтаксис: lua_shared_dict <имя> <размер>
по умолчанию: нет
контекст: http
фаза: зависит от использования
Объявляет зону общей памяти, <name>, которая служит хранилищем для словаря Lua на основе shm ngx.shared.<name>.
Зоны общей памяти всегда используются всеми процессами nginx в текущем экземпляре сервера nginx.
Аргумент <size> принимает единицы измерения размера, такие как k и m:
http {
lua_shared_dict dogs 10m;
...
} Минимальный жёстко заданный размер составляет 8 КБ, а фактический минимальный размер зависит от фактического набора данных пользователя (некоторые начинают с 12 КБ).
См. ngx.shared.DICT для получения подробностей.
Эта директива была впервые представлена в релизе v0.3.1rc22.
lua_socket_connect_timeout
синтаксис: lua_socket_connect_timeout <время>
по умолчанию: lua_socket_connect_timeout 60s
контекст: http, сервер, расположение
Данная директива управляет значением таймаута по умолчанию, используемым в методе connect объекта сокета TCP/unix-домен и может быть переопределена методами settimeout или settimeouts.
Аргумент <time> может быть целым числом с необязательной единицей измерения времени, например, s (секунда), ms (миллисекунда), m (минута). Единицей измерения времени по умолчанию является s, т.е. «секунда». Значение по умолчанию — 60s.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_send_timeout
синтаксис: lua_socket_send_timeout <время>
по умолчанию: lua_socket_send_timeout 60s
контекст: http, сервер, расположение
Управляет значением таймаута по умолчанию, используемым в методе send объекта сокета TCP/unix-домен, и может быть переопределено методами settimeout или settimeouts.
Аргумент <time> может быть целым числом с необязательной единицей измерения времени, например, s (секунда), ms (миллисекунда), m (минута). Единицей измерения времени по умолчанию является s, т.е. «секунда». Значение по умолчанию — 60s.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_send_lowat
синтаксис: lua_socket_send_lowat <размер>
по умолчанию: lua_socket_send_lowat 0
контекст: http, сервер, расположение
Управляет значением lowat (нижний порог) для буфера отправки cosocket.
lua_socket_read_timeout
синтаксис: lua_socket_read_timeout <время>
по умолчанию: lua_socket_read_timeout 60s
контекст: http, сервер, расположение
фаза: зависит от использования
Эта директива управляет значением таймаута по умолчанию, используемым в методе receive объекта сокета TCP/unix-домен и функциях-итераторах, возвращаемых методом receiveuntil. Это значение может быть переопределено методами settimeout или settimeouts.
Аргумент <time> может быть целым числом с необязательной единицей измерения времени, например, s (секунда), ms (миллисекунда), m (минута). Единицей измерения времени по умолчанию является s, т.е. «секунда». Значение по умолчанию — 60s.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_buffer_size
синтаксис: lua_socket_buffer_size <размер>
по умолчанию: lua_socket_buffer_size 4k/8k
контекст: http, сервер, расположение
Устанавливает размер буфера, используемого операциями чтения cosocket.
Этот буфер не обязательно должен быть таким большим, чтобы содержать всё одновременно, потому что cosocket поддерживает чтение и обработку без буферизации на 100%. Таким образом, даже буфер размером 1 байт должен работать везде, но производительность может быть ужасной.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_pool_size
синтаксис: lua_socket_pool_size <размер>
по умолчанию: lua_socket_pool_size 30
контекст: http, сервер, расположение
Устанавливает лимит размера (в количестве подключений) для каждого пула подключений cosocket, связанного с каждым удалённым сервером (то есть, идентифицированного либо парой хост-порт, либо путём файла сокета unix-домена).
По умолчанию — 30 подключений для каждого пула.
Когда пул подключений превышает установленный лимит размера, самое малое используемое (бездействующее) подключение, уже присутствующее в пуле, будет закрыто, чтобы освободить место для текущего подключения.
Обратите внимание, что пул подключений cosocket относится к каждому процессу nginx, а не к каждому экземпляру сервера nginx, поэтому установленный здесь лимит размера также относится к каждому процессу nginx.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_keepalive_timeout
синтаксис: lua_socket_keepalive_timeout <время>
по умолчанию: lua_socket_keepalive_timeout 60s
контекст: http, сервер, расположение
Данная директива управляет максимальным временем бездействия подключений в встроенном пуле подключений cosocket. При достижении этого таймаута бездействующие подключения будут закрыты и удалены из пула. Это значение может быть переопределено методом setkeepalive объектов cosocket.
Аргумент <time> может быть целым числом с необязательной единицей измерения времени, например, s (секунда), ms (миллисекунда), m (минута). Единицей измерения времени по умолчанию является s, т.е. «секунда». Значение по умолчанию — 60s.
Эта директива была впервые представлена в релизе v0.5.0rc1.
lua_socket_log_errors
синтаксис: lua_socket_log_errors on|off
по умолчанию: lua_socket_log_errors on
контекст: http, сервер, расположение
Эта директива может быть использована для включения или выключения ведения журнала ошибок, когда возникают ошибки для TCP или UDP cosockets. Если вы уже выполняете надлежащую обработку и ведение журнала ошибок в коде Lua, рекомендуется выключить эту директиву, чтобы предотвратить сброс данных в логах ошибок nginx (что обычно довольно дорогостоящее).
Эта директива была впервые представлена в релизе v0.5.13.
lua_ssl_ciphers
синтаксис: lua_ssl_ciphers <шифры>
по умолчанию: lua_ssl_ciphers DEFAULT
контекст: http, сервер, расположение
Устанавливает включенные шифры для запросов к серверу SSL/TLS в методе tcpsock:sslhandshake. Шифры указываются в формате, понятном библиотеке OpenSSL.
Полный список можно просмотреть, используя команду «openssl ciphers».
Эта директива была впервые представлена в релизе v0.9.11.
lua_ssl_crl
синтаксис: lua_ssl_crl <файл>
по умолчанию: нет
контекст: http, сервер, расположение
Указывает файл с отозванными сертификатами (CRL) в формате PEM, используемый для проверки сертификата сервера SSL/TLS в методе tcpsock:sslhandshake.
Эта директива была впервые представлена в релизе v0.9.11.
lua_ssl_protocols
синтаксис: lua_ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2] [TLSv1.3]
по умолчанию: lua_ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2
контекст: http, server, location
Включает указанные протоколы для запросов к серверу SSL/TLS в методе tcpsock:sslhandshake.
Поддержка параметра TLSv1.3 требует версии v0.10.12 и OpenSSL 1.1.1.
Эта директива была впервые представлена в релизе v0.9.11.
lua_ssl_trusted_certificate
синтаксис: lua_ssl_trusted_certificate <file>
по умолчанию: нет
контекст: http, server, location
Указывает путь к файлу с доверенными сертификатами CA в формате PEM, используемыми для проверки сертификата сервера SSL/TLS в методе tcpsock:sslhandshake.
Эта директива была впервые представлена в релизе v0.9.11.
См. также lua_ssl_verify_depth.
lua_ssl_verify_depth
синтаксис: lua_ssl_verify_depth <число>
по умолчанию: lua_ssl_verify_depth 1
контекст: http, server, location
Устанавливает глубину проверки в цепочке сертификатов сервера.
Эта директива была впервые представлена в релизе v0.9.11.
См. также lua_ssl_trusted_certificate.
lua_http10_buffering
синтаксис: lua_http10_buffering on|off
по умолчанию: lua_http10_buffering on
контекст: http, server, location, location-if
Включает или отключает автоматическое буферирование ответов для запросов HTTP 1.0 (или более ранних). Этот механизм буферизации в основном используется для keep-alive HTTP 1.0, который полагается на правильный заголовок ответа Content-Length.
Если Lua-код явно устанавливает заголовок ответа Content-Length перед отправкой заголовков (явно через ngx.send_headers или неявно через первый вызов ngx.say или ngx.print), то буферизация ответов HTTP 1.0 будет отключена, даже если эта директива включена.
Для вывода очень больших данных ответа в потоковом режиме (например, с помощью вызова ngx.flush), эта директива ДОЛЖНА быть выключена, чтобы минимизировать использование памяти.
Эта директива включена on по умолчанию.
Эта директива была впервые представлена в релизе v0.5.0rc19.
rewrite_by_lua_no_postpone
синтаксис: rewrite_by_lua_no_postpone on|off
по умолчанию: rewrite_by_lua_no_postpone off
контекст: http
Управляет отключением отложенного выполнения директив rewrite_by_lua* до конца фазы обработки запроса rewrite. По умолчанию эта директива выключена, и Lua-код откладывается до конца фазы rewrite.
Эта директива была впервые представлена в релизе v0.5.0rc29.
access_by_lua_no_postpone
синтаксис: access_by_lua_no_postpone on|off
по умолчанию: access_by_lua_no_postpone off
контекст: http
Управляет отключением отложенного выполнения директив access_by_lua* до конца фазы обработки запроса access. По умолчанию эта директива выключена, и Lua-код откладывается до конца фазы access.
Эта директива была впервые представлена в релизе v0.9.20.
lua_transform_underscores_in_response_headers
синтаксис: lua_transform_underscores_in_response_headers on|off
по умолчанию: lua_transform_underscores_in_response_headers on
контекст: http, server, location, location-if
Управляет преобразованием подчеркиваний (_) в названиях заголовков ответа, указанных в API ngx.header.HEADER, в тире (-).
Эта директива была впервые представлена в релизе v0.5.0rc32.
lua_check_client_abort
синтаксис: lua_check_client_abort on|off
по умолчанию: lua_check_client_abort off
контекст: http, server, location, location-if
Управляет проверкой преждевременного прерывания соединения клиентом.
Когда эта директива включена, модуль ngx_lua отслеживает событие преждевременного закрытия соединения на подключении downstream и при таком событии вызывает пользовательскую Lua функцию обратного вызова (зарегистрированную с помощью ngx.on_abort) или просто останавливается и очищает все Lua "лёгкие потоки", работающие в обработчике запроса текущего запроса, когда нет зарегистрированной пользовательской функции обратного вызова.
Однако, согласно текущей реализации, если клиент закрывает соединение до завершения чтения Lua данных тела запроса через ngx.req.socket, то ngx_lua не остановит все работающие "лёгкие потоки" и не вызовет пользовательский обратный вызов (если ngx.on_abort был вызван). Вместо этого, операция чтения из ngx.req.socket просто вернет сообщение об ошибке "клиент прервал" как второе возвращаемое значение (первое возвращаемое значение, безусловно, nil).
Когда TCP keepalive отключен, он полагается на клиент для закрытия сокета корректно (отправив пакет FIN или что-то подобное). Для веб-приложений (мягкого) реального времени настоятельно рекомендуется настроить поддержку TCP keepalive в реализации стека TCP вашей системы, чтобы вовремя обнаруживать "полуоткрытые" TCP-соединения.
Например, на Linux, вы можете настроить стандартную директиву listen в вашем файле nginx.conf следующим образом:
listen 80 so_keepalive=2s:2s:8;
На FreeBSD вы можете настроить только системную конфигурацию для TCP keepalive, например:
# sysctl net.inet.tcp.keepintvl=2000 # sysctl net.inet.tcp.keepidle=2000
Эта директива была впервые представлена в релизе v0.7.4.
См. также ngx.on_abort.
lua_max_pending_timers
синтаксис: lua_max_pending_timers <количество>
по умолчанию: lua_max_pending_timers 1024
контекст: http
Управляет максимальным количеством ожидающих таймеров.
Ожидающие таймеры — это таймеры, которые еще не истекли.
При превышении этого предела вызов ngx.timer.at немедленно вернёт nil и строку ошибки "слишком много ожидающих таймеров".
Эта директива была впервые представлена в релизе v0.8.0.
lua_max_running_timers
синтаксис: lua_max_running_timers <count>
по умолчанию: lua_max_running_timers 256
контекст: http
Управляет максимальным количеством "работающих таймеров".
Работающие таймеры — это таймеры, чьи пользовательские функции обратного вызова все еще выполняются.
При превышении этого предела Nginx прекратит выполнение обратных вызовов вновь истекших таймеров и выведет сообщение об ошибке "N lua_max_running_timers недостаточно", где "N" — текущее значение этой директивы.
Эта директива была впервые представлена в релизе v0.8.0.
Nginx API для Lua
- Введение
- ngx.arg
- ngx.var.ПЕРЕМЕННАЯ
- Основные константы
- Константы методов HTTP
- Константы кодов состояния HTTP
- Константы уровней логов Nginx
- ngx.ctx
- ngx.location.capture
- ngx.location.capture_multi
- ngx.status
- ngx.header.ЗАГОЛОВОК
- ngx.resp.get_headers
- ngx.req.is_internal
- ngx.req.start_time
- ngx.req.http_version
- ngx.req.raw_header
- ngx.req.get_method
- ngx.req.set_method
- ngx.req.set_uri
- ngx.req.set_uri_args
- ngx.req.get_uri_args
- ngx.req.get_post_args
- ngx.req.get_headers
- ngx.req.set_header
- ngx.req.clear_header
- ngx.req.read_body
- ngx.req.discard_body
- ngx.req.get_body_data
- ngx.req.get_body_file
- ngx.req.set_body_data
- ngx.req.set_body_file
- ngx.req.init_body
- ngx.req.append_body
- ngx.req.finish_body
- ngx.req.socket
- ngx.exec
- ngx.redirect
- ngx.send_headers
- ngx.headers_sent
- ngx.print
- ngx.say
- ngx.log
- ngx.flush
- ngx.exit
- ngx.eof
- ngx.sleep
- ngx.escape_uri
- ngx.unescape_uri
- ngx.encode_args
- ngx.decode_args
- ngx.encode_base64
- ngx.decode_base64
- ngx.crc32_short
- ngx.crc32_long
- ngx.hmac_sha1
- ngx.md5
- ngx.md5_bin
- ngx.sha1_bin
- ngx.quote_sql_str
- ngx.today
- ngx.time
- ngx.now
- ngx.update_time
- ngx.localtime
- ngx.utctime
- ngx.cookie_time
- ngx.http_time
- ngx.parse_http_time
- ngx.is_subrequest
- ngx.re.match
- ngx.re.find
- ngx.re.gmatch
- ngx.re.sub
- ngx.re.gsub
- ngx.shared.DICT
- ngx.shared.DICT.get
- ngx.shared.DICT.get_stale
- ngx.shared.DICT.set
- ngx.shared.DICT.safe_set
- ngx.shared.DICT.add
- ngx.shared.DICT.safe_add
- ngx.shared.DICT.replace
- ngx.shared.DICT.delete
- ngx.shared.DICT.incr
- ngx.shared.DICT.lpush
- ngx.shared.DICT.rpush
- ngx.shared.DICT.lpop
- ngx.shared.DICT.rpop
- ngx.shared.DICT.llen
- ngx.shared.DICT.ttl
- ngx.shared.DICT.expire
- ngx.shared.DICT.flush_all
- ngx.shared.DICT.flush_expired
- ngx.shared.DICT.get_keys
- ngx.shared.DICT.capacity
- ngx.shared.DICT.free_space
- ngx.socket.udp
- udpsock:setpeername
- udpsock:send
- udpsock:receive
- udpsock:close
- udpsock:settimeout
- ngx.socket.stream
- ngx.socket.tcp
- tcpsock:connect
- tcpsock:sslhandshake
- tcpsock:send
- tcpsock:receive
- tcpsock:receiveuntil
- tcpsock:close
- tcpsock:settimeout
- tcpsock:settimeouts
- tcpsock:setoption
- tcpsock:setkeepalive
- tcpsock:getreusedtimes
- ngx.socket.connect
- ngx.get_phase
- ngx.thread.spawn
- ngx.thread.wait
- ngx.thread.kill
- ngx.on_abort
- ngx.timer.at
- ngx.timer.every
- ngx.timer.running_count
- ngx.timer.pending_count
- ngx.config.subsystem
- ngx.config.debug
- ngx.config.prefix
- ngx.config.nginx_version
- ngx.config.nginx_configure
- ngx.config.ngx_lua_version
- ngx.worker.exiting
- ngx.worker.pid
- ngx.worker.count
- ngx.worker.id
- ngx.semaphore
- ngx.balancer
- ngx.ssl
- ngx.ocsp
- ndk.set_var.ДИРЕКТИВА
- coroutine.create
- coroutine.resume
- coroutine.yield
- coroutine.wrap
- coroutine.running
- coroutine.status
Введение
Различные *_by_lua, *_by_lua_block и *_by_lua_file директивы конфигурации служат шлюзами к API Lua в файле nginx.conf. Описанный ниже API Nginx Lua может быть вызван только внутри пользовательского кода Lua, выполняемого в контексте этих директив конфигурации.
API предоставляется Lua в виде двух стандартных пакетов ngx и ndk. Эти пакеты находятся в глобальной области видимости по умолчанию в ngx_lua и всегда доступны в директивах ngx_lua.
Пакеты можно ввести в внешние модули Lua так:
local say = ngx.say
local _M = {}
function _M.foo(a)
say(a)
end
return _M Использование флага package.seeall категорически не рекомендуется из-за его различных негативных последствий.
Также возможно прямо потребовать пакеты во внешних модулях Lua:
local ngx = require "ngx" local ndk = require "ndk"
Возможность потребовать эти пакеты была введена в релизе v0.2.1rc19.
Операции ввода-вывода сети в пользовательском коде должны выполняться только через вызовы Nginx Lua API, так как цикл обработки событий Nginx может быть заблокирован, и производительность значительно пострадает в противном случае. Операции с диском с относительно небольшим объёмом данных могут выполняться с помощью стандартной Lua io библиотеки, но следует избегать больших операций чтения и записи файлов, так как они могут значительно заблокировать процесс Nginx. Рекомендуется делегировать все операции ввода-вывода сети и диска подзапросам Nginx (через метод ngx.location.capture и аналогичные) для максимальной производительности.
ngx.arg
синтаксис: val = ngx.arg[индекс]
контекст: set_by_lua*, body_filter_by_lua*
Когда это используется в контексте директив set_by_lua*, эта таблица является только для чтения и содержит входные аргументы для директив конфигурации:
value = ngx.arg[n]
Вот пример
location /foo {
set $a 32;
set $b 56;
set_by_lua $sum
'return tonumber(ngx.arg[1]) + tonumber(ngx.arg[2])'
$a $b;
echo $sum;
} который выводит 88, сумму 32 и 56.
Когда эта таблица используется в контексте body_filter_by_lua*, первый элемент содержит фрагмент входных данных для кода фильтра вывода, а второй элемент содержит булеву метку "eof", указывающую конец всего потока данных вывода.
Фрагмент данных и флаг "eof", передаваемые в последующие фильтры вывода Nginx, также могут быть переопределены путём прямого присваивания значений соответствующим элементам таблицы. При установке nil или пустой строки Lua в ngx.arg[1], фрагмент данных не будет передан в последующие фильтры вывода Nginx.
ngx.var.ПЕРЕМЕННАЯ
синтаксис: ngx.var.ИМЯ_ПЕРЕМЕННОЙ
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Чтение и запись значений переменных Nginx.
value = ngx.var.some_nginx_variable_name ngx.var.some_nginx_variable_name = value
Обратите внимание, что можно записывать только уже определенные переменные nginx. Например:
location /foo {
set $my_var ''; # this line is required to create $my_var at config time
content_by_lua_block {
ngx.var.my_var = 123;
...
}
} То есть, переменные nginx не могут быть созданы на лету.
Некоторые специальные переменные nginx, такие как $args и $limit_rate, могут быть присвоены значение, многие другие нет, например, $query_string, $arg_PARAMETER и $http_NAME.
Переменные nginx для захвата групп в регулярных выражениях $1, $2, $3 и т. д. также могут быть прочитаны через этот интерфейс, записав ngx.var[1], ngx.var[2], ngx.var[3] и т. д.
Установление ngx.var.Foo в значение nil приведет к удалению переменной Nginx $Foo.
ngx.var.args = nil
ВНИМАНИЕ При чтении из переменной Nginx, Nginx выделяет память в пуле памяти на запрос, которая освобождается только при завершении запроса. Поэтому, когда вам нужно многократно читать переменную Nginx в вашем Lua-коде, кэшируйте значение переменной Nginx в вашей собственной Lua-переменной, например,
local val = ngx.var.some_var --- use the val repeatedly later
чтобы предотвратить (временную) утечку памяти в течение текущего запроса. Другой способ кэширования результата — использование таблицы ngx.ctx.
Неопределенные переменные NGINX оцениваются как nil, в то время как неинициализированные (но определенные) переменные NGINX оцениваются как пустая Lua-строка.
Этот API требует относительно дорогостоящего вызова метаметода, и рекомендуется избегать его использования в горячих точках кода.
Основные константы
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, *log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
ngx.OK (0) ngx.ERROR (-1) ngx.AGAIN (-2) ngx.DONE (-4) ngx.DECLINED (-5)
Обратите внимание, что только три из этих констант используются API Nginx для Lua (Nginx API для Lua) (т. е. ngx.exit принимает ngx.OK, ngx.ERROR и ngx.DECLINED в качестве входных данных).
ngx.null
Константа ngx.null — это NULL пользовательский данные, обычно используемый для представления значений nil в таблицах Lua и т. д., и аналогичен константе cjson.null библиотеки lua-cjson. Эта константа была впервые представлена в релизе v0.5.0rc5.
Константа ngx.DECLINED была впервые представлена в релизе v0.5.0rc19.
Константы методов HTTP
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
ngx.HTTP_GET ngx.HTTP_HEAD ngx.HTTP_PUT ngx.HTTP_POST ngx.HTTP_DELETE ngx.HTTP_OPTIONS (added in the v0.5.0rc24 release) ngx.HTTP_MKCOL (added in the v0.8.2 release) ngx.HTTP_COPY (added in the v0.8.2 release) ngx.HTTP_MOVE (added in the v0.8.2 release) ngx.HTTP_PROPFIND (added in the v0.8.2 release) ngx.HTTP_PROPPATCH (added in the v0.8.2 release) ngx.HTTP_LOCK (added in the v0.8.2 release) ngx.HTTP_UNLOCK (added in the v0.8.2 release) ngx.HTTP_PATCH (added in the v0.8.2 release) ngx.HTTP_TRACE (added in the v0.8.2 release)
Эти константы обычно используются в вызовах метода ngx.location.capture и ngx.location.capture_multi.
Константы кодов состояния HTTP
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
value = ngx.HTTP_CONTINUE (100) (first added in the v0.9.20 release) value = ngx.HTTP_SWITCHING_PROTOCOLS (101) (first added in the v0.9.20 release) value = ngx.HTTP_OK (200) value = ngx.HTTP_CREATED (201) value = ngx.HTTP_ACCEPTED (202) (first added in the v0.9.20 release) value = ngx.HTTP_NO_CONTENT (204) (first added in the v0.9.20 release) value = ngx.HTTP_PARTIAL_CONTENT (206) (first added in the v0.9.20 release) value = ngx.HTTP_SPECIAL_RESPONSE (300) value = ngx.HTTP_MOVED_PERMANENTLY (301) value = ngx.HTTP_MOVED_TEMPORARILY (302) value = ngx.HTTP_SEE_OTHER (303) value = ngx.HTTP_NOT_MODIFIED (304) value = ngx.HTTP_TEMPORARY_REDIRECT (307) (first added in the v0.9.20 release) value = ngx.HTTP_PERMANENT_REDIRECT (308) value = ngx.HTTP_BAD_REQUEST (400) value = ngx.HTTP_UNAUTHORIZED (401) value = ngx.HTTP_PAYMENT_REQUIRED (402) (first added in the v0.9.20 release) value = ngx.HTTP_FORBIDDEN (403) value = ngx.HTTP_NOT_FOUND (404) value = ngx.HTTP_NOT_ALLOWED (405) value = ngx.HTTP_NOT_ACCEPTABLE (406) (first added in the v0.9.20 release) value = ngx.HTTP_REQUEST_TIMEOUT (408) (first added in the v0.9.20 release) value = ngx.HTTP_CONFLICT (409) (first added in the v0.9.20 release) value = ngx.HTTP_GONE (410) value = ngx.HTTP_UPGRADE_REQUIRED (426) (first added in the v0.9.20 release) value = ngx.HTTP_TOO_MANY_REQUESTS (429) (first added in the v0.9.20 release) value = ngx.HTTP_CLOSE (444) (first added in the v0.9.20 release) value = ngx.HTTP_ILLEGAL (451) (first added in the v0.9.20 release) value = ngx.HTTP_INTERNAL_SERVER_ERROR (500) value = ngx.HTTP_METHOD_NOT_IMPLEMENTED (501) value = ngx.HTTP_BAD_GATEWAY (502) (first added in the v0.9.20 release) value = ngx.HTTP_SERVICE_UNAVAILABLE (503) value = ngx.HTTP_GATEWAY_TIMEOUT (504) (first added in the v0.3.1rc38 release) value = ngx.HTTP_VERSION_NOT_SUPPORTED (505) (first added in the v0.9.20 release) value = ngx.HTTP_INSUFFICIENT_STORAGE (507) (first added in the v0.9.20 release)
Константы уровней ведения журнала Nginx
контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
ngx.STDERR ngx.EMERG ngx.ALERT ngx.CRIT ngx.ERR ngx.WARN ngx.NOTICE ngx.INFO ngx.DEBUG
Эти константы обычно используются методом ngx.log.
синтаксис: print(...)
контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Записывает значения аргументов в файл nginx error.log с уровнем ведения журнала ngx.NOTICE.
Это эквивалентно
ngx.log(ngx.NOTICE, ...)
Принимаются аргументы Lua nil, которые приводят к буквальным "nil" строкам, а Lua-булевы значения — к буквальным "true" или "false" строкам. И константа ngx.null даст строку вывода "null".
В ядре Nginx есть жёсткое ограничение в 2048 байтах на длину сообщений об ошибках. Это ограничение включает завершающие символы новой строки и ведущие временные метки. Если размер сообщения превышает это ограничение, Nginx обрезает текст сообщения соответствующим образом. Это ограничение можно изменить вручную, отредактировав определение макроса NGX_MAX_ERROR_STR в файле src/core/ngx_log.h в дереве исходного кода Nginx.
ngx.ctx
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*
Эта таблица может использоваться для хранения данных контекста Lua на запрос, и имеет срок жизни, идентичный текущему запросу (как и переменные Nginx).
Рассмотрим следующий пример,
location /test {
rewrite_by_lua_block {
ngx.ctx.foo = 76
}
access_by_lua_block {
ngx.ctx.foo = ngx.ctx.foo + 3
}
content_by_lua_block {
ngx.say(ngx.ctx.foo)
}
} Тогда GET /test даст вывод
79
То есть, запись ngx.ctx.foo сохраняется на этапах переработки, доступа и содержимого запроса.
Каждый запрос, включая подзапросы, имеет свою копию таблицы. Например:
location /sub {
content_by_lua_block {
ngx.say("sub pre: ", ngx.ctx.blah)
ngx.ctx.blah = 32
ngx.say("sub post: ", ngx.ctx.blah)
}
}
location /main {
content_by_lua_block {
ngx.ctx.blah = 73
ngx.say("main pre: ", ngx.ctx.blah)
local res = ngx.location.capture("/sub")
ngx.print(res.body)
ngx.say("main post: ", ngx.ctx.blah)
}
} Тогда GET /main даст вывод
main pre: 73 sub pre: nil sub post: 32 main post: 73
Здесь изменение записи ngx.ctx.blah в подзапросе не влияет на неё в родительском запросе. Это потому, что у них есть две отдельные версии ngx.ctx.blah.
Внутреннее перенаправление уничтожит исходные данные запроса ngx.ctx (если таковые имеются), а у нового запроса будет пустая таблица ngx.ctx. Например,
location /new {
content_by_lua_block {
ngx.say(ngx.ctx.foo)
}
}
location /orig {
content_by_lua_block {
ngx.ctx.foo = "hello"
ngx.exec("/new")
}
} Тогда GET /orig даст
nil
а не исходное значение "hello".
В эту "волшебную" таблицу можно вставить произвольные данные, включая Lua-замыкания и вложенные таблицы. Она также позволяет регистрировать пользовательские метаметоды.
Поддержка перезаписи ngx.ctx новой таблицей Lua, например,
ngx.ctx = { foo = 32, bar = 54 } При использовании в контексте init_worker_by_lua* эта таблица имеет тот же срок жизни, что и текущий обработчик Lua.
Поиск ngx.ctx требует относительно дорогостоящих вызовов метаметодов и значительно медленнее, чем явное передача данных на запрос через аргументы вашей функции. Поэтому не злоупотребляйте этим API для сохранения аргументов своих функций, так как это обычно оказывает значительное влияние на производительность.
Из-за волшебства метаметодов никогда не делайте "local" таблицу ngx.ctx вне области видимости вашей Lua-функции на уровне Lua-модуля из-за обмена данными на уровне рабочего процесса Nginx. Например, следующее нежелательно:
-- mymodule.lua
local _M = {}
-- the following line is bad since ngx.ctx is a per-request
-- data while this <code>ctx</code> variable is on the Lua module level
-- and thus is per-nginx-worker.
local ctx = ngx.ctx
function _M.main()
ctx.foo = "bar"
end
return _M Вместо этого используйте следующее:
-- mymodule.lua
local _M = {}
function _M.main(ctx)
ctx.foo = "bar"
end
return _M То есть, пусть вызывающая сторона передаёт таблицу ctx явно в качестве аргумента функции.
ngx.location.capture
синтаксис: res = ngx.location.capture(uri, options?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Выполняет синхронный, но всё ещё асинхронный подзапрос Nginx с использованием uri.
Подзапросы Nginx предоставляют мощный способ выполнения асинхронных внутренних запросов к другим расположениям, настроенным с помощью каталогов файлов или любых других C-модулей nginx, например, ngx_proxy, ngx_fastcgi, ngx_memc, ngx_postgres, ngx_drizzle и даже ngx_lua, и т. д.
Обратите также внимание, что подзапросы просто имитируют интерфейс HTTP, но никакого дополнительного трафика HTTP/TCP и никакой IPC не задействовано. Всё работает внутренне, эффективно, на уровне C.
Подзапросы существенно отличаются от перенаправлений HTTP 301/302 (через ngx.redirect) и внутренних перенаправлений (через ngx.exec).
Перед запуском подзапроса всегда необходимо прочитать тело запроса (вызвав ngx.req.read_body или настроив lua_need_request_body).
Эта функция API (а также ngx.location.capture_multi) всегда буферизует всё тело ответа подзапроса в памяти. Поэтому в случае обработки больших ответов подзапросов рекомендуется использовать cosockets и потоковую обработку.
Вот базовый пример:
res = ngx.location.capture(uri)
Возвращает Lua-таблицу с 4 слотами: res.status, res.header, res.body и res.truncated.
res.status содержит код состояния ответа подзапроса.
res.header содержит все заголовки ответа подзапроса, и это обычная Lua-таблица. Для заголовков ответа с несколькими значениями значение является Lua-таблицей (массивом), содержащей все значения в порядке их появления. Например, если заголовки ответа подзапроса содержат следующие строки:
Set-Cookie: a=3 Set-Cookie: foo=bar Set-Cookie: baz=blah
Тогда res.header["Set-Cookie"] будет вычислено как значение таблицы {"a=3", "foo=bar", "baz=blah"}.
res.body содержит данные тела ответа подзапроса, которые могут быть усечёнными. Вам всегда нужно проверять флаг res.truncated, чтобы убедиться, что res.body содержит усечённые данные. Усечение данных здесь может быть вызвано только теми необратимыми ошибками в ваших подзапросах, такими как случаи, когда удалённый конец преждевременно прерывает соединение посреди потока данных тела ответа, или происходит таймаут чтения при получении данных тела ответа подзапроса от удалённого.
Строки запроса URI могут быть конкатенированы с самим URI, например,
res = ngx.location.capture('/foo/bar?a=3&b=4') Имена расположений, такие как @foo, запрещены из-за ограничений ядра nginx. Используйте обычные расположения в сочетании с директивой internal для подготовки только внутренних расположений.
В качестве второго аргумента можно передать необязательную таблицу опций, которая поддерживает опции:
-
methodукажите метод запроса подзапроса, который принимает только константы, такие какngx.HTTP_POST. -
bodyукажите тело запроса подзапроса (только строковое значение). -
argsукажите аргументы URI подзапроса (приняты как строковые значения, так и Lua-таблицы). -
ctxукажите Lua-таблицу, которая будет таблицей ngx.ctx для подзапроса. Это может быть таблица ngx.ctx текущего запроса, что эффективно заставляет родительский запрос и подзапрос использовать точно одну и ту же таблицу контекста. Этот параметр был впервые представлен вv0.3.1rc25релизе. -
varsпримите Lua-таблицу, содержащую значения для установки указанных переменных Nginx в подзапросе в качестве значения этого параметра. Этот параметр был впервые представлен вv0.3.1rc31релизе. -
copy_all_varsукажите, нужно ли копировать все значения переменных Nginx текущего запроса в подзапрос. Изменения переменных nginx в подзапросе не повлияют на текущий (родительский) запрос. Этот параметр был впервые представлен вv0.3.1rc31релизе. -
share_all_varsукажите, нужно ли совместно использовать все переменные Nginx подзапроса с текущим (родительским) запросом. Изменения переменных Nginx в подзапросе повлияют на текущий (родительский) запрос. Включение этого параметра может привести к трудноотлаживаемым проблемам из-за побочных эффектов и считается нежелательным и вредным. Включайте этот параметр только в том случае, если вы полностью понимаете, что делаете. -
always_forward_bodyесли значение равно true, тело запроса текущего (родительского) запроса всегда будет пересылаться подзапросу, который создается, если параметрbodyне указан. Тело запроса, прочитанное с помощью ngx.req.read_body() или lua_need_request_body on, будет напрямую пересылаться подзапросу без копирования всего тела запроса при создании подзапроса (независимо от того, буферизуется ли тело запроса в буферах памяти или временных файлах). По умолчанию этот параметр равенfalse, и когда параметрbodyне указан, тело запроса текущего (родительского) запроса пересылается только в том случае, когда подзапрос использует метод запросаPUTилиPOST.
Например, для выдачи POST-подзапроса можно сделать следующее
res = ngx.location.capture(
'/foo/bar',
{ method = ngx.HTTP_POST, body = 'hello, world' }
) См. константы методов HTTP, отличные от POST. Параметр method по умолчанию равен ngx.HTTP_GET.
Параметр args может указать дополнительные аргументы URI, например,
ngx.location.capture('/foo?a=1',
{ args = { b = 3, c = ':' } }
) эквивалентно
ngx.location.capture('/foo?a=1&b=3&c=%3a') то есть этот метод будет экранировать ключи и значения аргументов в соответствии с правилами URI и объединять их в полную строку запроса. Формат Lua-таблицы, переданной в качестве аргумента args, идентичен формату, используемому в методе ngx.encode_args.
Параметр args также может принимать простые строки запроса:
ngx.location.capture('/foo?a=1',
{ args = 'b=3&c=%3a' } }
) Это функционально идентично предыдущим примерам.
Параметр share_all_vars управляет совместным использованием переменных nginx между текущим запросом и его подзапросами. Если этот параметр равен true, то текущий запрос и связанные подзапросы будут использовать один и тот же объем переменных Nginx. Следовательно, изменения переменных Nginx, внесенные подзапросом, повлияют на текущий запрос.
Следует проявлять осторожность при использовании этого параметра, поскольку совместное использование области переменных может иметь непредвиденные последствия. Вместо этого обычно предпочтительны параметры args, vars или copy_all_vars.
По умолчанию этот параметр равен false
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ share_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
} Доступ к расположению /lua дает
/other dog: hello world /lua: hello world
Параметр copy_all_vars предоставляет копию переменных Nginx родительского запроса подзапросам при их вызове. Изменения, внесенные в эти переменные такими подзапросами, не повлияют на родительский запрос или любые другие подзапросы, использующие переменные родительского запроса.
location /other {
set $dog "$dog world";
echo "$uri dog: $dog";
}
location /lua {
set $dog 'hello';
content_by_lua_block {
res = ngx.location.capture("/other",
{ copy_all_vars = true });
ngx.print(res.body)
ngx.say(ngx.var.uri, ": ", ngx.var.dog)
}
} Запрос GET /lua даст вывод
/other dog: hello world /lua: hello
Обратите внимание, что если оба share_all_vars и copy_all_vars установлены в true, то share_all_vars имеет приоритет.
Помимо двух вышеуказанных параметров, можно указать значения для переменных в подзапросе с помощью параметра vars. Эти переменные устанавливаются после оценки совместного использования или копирования переменных и обеспечивают более эффективный метод передачи определенных значений подзапросу по сравнению с кодированием их как аргументов URL и их разэкранированием в файле конфигурации Nginx.
location /other {
content_by_lua_block {
ngx.say("dog = ", ngx.var.dog)
ngx.say("cat = ", ngx.var.cat)
}
}
location /lua {
set $dog '';
set $cat '';
content_by_lua_block {
res = ngx.location.capture("/other",
{ vars = { dog = "hello", cat = 32 }});
ngx.print(res.body)
}
} Доступ к /lua приведет к выводу
dog = hello cat = 32
Параметр ctx может быть использован для указания пользовательской Lua-таблицы в качестве таблицы ngx.ctx для подзапроса.
location /sub {
content_by_lua_block {
ngx.ctx.foo = "bar";
}
}
location /lua {
content_by_lua_block {
local ctx = {}
res = ngx.location.capture("/sub", { ctx = ctx })
ngx.say(ctx.foo);
ngx.say(ngx.ctx.foo);
}
} Затем запрос GET /lua дает
bar nil
Также можно использовать этот параметр ctx для совместного использования одной и той же таблицы ngx.ctx между текущим (родительским) запросом и подзапросом:
location /sub {
content_by_lua_block {
ngx.ctx.foo = "bar";
}
}
location /lua {
content_by_lua_block {
res = ngx.location.capture("/sub", { ctx = ngx.ctx })
ngx.say(ngx.ctx.foo);
}
} Запрос GET /lua выводит
bar
Обратите внимание, что подзапросы, вызываемые с помощью ngx.location.capture, по умолчанию наследуют все заголовки запроса текущего запроса, что может иметь непредвиденные последствия для ответов подзапроса. Например, при использовании стандартного модуля ngx_proxy для обслуживания подзапросов заголовок "Accept-Encoding: gzip" в основном запросе может привести к сжатым ответам, которые не могут быть правильно обработаны в Lua-коде. Заголовки исходного запроса следует игнорировать, установив proxy_pass_request_headers в значение off в расположениях подзапроса.
Если параметр body не указан, а параметр always_forward_body имеет значение false (значение по умолчанию), подзапросы POST и PUT унаследуют тела запроса родительского запроса (если таковые имеются).
Существует жестко заданный верхний предел числа возможных одновременных подзапросов для каждого основного запроса. В более старых версиях Nginx предел составлял 50 одновременных подзапросов, а в более новых версиях Nginx, начиная с 1.1.x, он был увеличен до 200 одновременных подзапросов. При превышении этого предела в файл error.log добавляется следующее сообщение об ошибке:
[error] 13983#0: *1 subrequests cycle while processing "/uri"
Предел можно вручную изменить, если нужно, отредактировав определение макроса NGX_HTTP_MAX_SUBREQUESTS в файле nginx/src/http/ngx_http_request.h в дереве исходного кода Nginx.
Также обратитесь к ограничениям по расположениям захвата, сконфигурированным директивами подзапроса других модулей.
ngx.location.capture_multi
синтаксис: res1, res2, ... = ngx.location.capture_multi({ {uri, options?}, {uri, options?}, ... })
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Точно так же, как ngx.location.capture, но поддерживает несколько подзапросов, выполняемых параллельно.
Эта функция отправляет несколько параллельных подзапросов, указанных в таблице ввода, и возвращает их результаты в том же порядке. Например,
res1, res2, res3 = ngx.location.capture_multi{
{ "/foo", { args = "a=3&b=4" } },
{ "/bar" },
{ "/baz", { method = ngx.HTTP_POST, body = "hello" } },
}
if res1.status == ngx.HTTP_OK then
...
end
if res2.body == "BLAH" then
...
end Эта функция не вернется, пока все подзапросы не завершатся. Общее время ожидания — это самое большое время ожидания отдельных подзапросов, а не сумма.
Lua-таблицы могут использоваться для запросов и ответов, когда количество подзапросов, которые нужно отправить, заранее неизвестно:
-- construct the requests table
local reqs = {}
table.insert(reqs, { "/mysql" })
table.insert(reqs, { "/postgres" })
table.insert(reqs, { "/redis" })
table.insert(reqs, { "/memcached" })
-- issue all the requests at once and wait until they all return
local resps = { ngx.location.capture_multi(reqs) }
-- loop over the responses table
for i, resp in ipairs(resps) do
-- process the response table "resp"
end Функция ngx.location.capture — это всего лишь специальный вид этой функции. Логически ngx.location.capture можно реализовать так
ngx.location.capture =
function (uri, args)
return ngx.location.capture_multi({ {uri, args} })
end Также обратитесь к ограничениям по расположениям захвата, сконфигурированным директивами подзапроса других модулей.
ngx.status
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Считывает и записывает статус ответа текущего запроса. Это следует вызвать до отправки заголовков ответа.
ngx.status = ngx.HTTP_CREATED status = ngx.status
Установка ngx.status после отправки заголовка ответа не имеет эффекта, но в журнале ошибок nginx появляется сообщение об ошибке:
attempt to set ngx.status after sending out response headers
ngx.header.HEADER
синтаксис: ngx.header.HEADER = VALUE
синтаксис: value = ngx.header.HEADER
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Устанавливает, добавляет или очищает заголовок ответа текущего запроса, который должен быть отправлен.
Подчеркивания (_) в именах заголовков по умолчанию заменяются дефисами (-). Это преобразование можно отключить с помощью директивы lua_transform_underscores_in_response_headers.
Имена заголовков сопоставляются без учета регистра.
-- equivalent to ngx.header["Content-Type"] = 'text/plain' ngx.header.content_type = 'text/plain'; ngx.header["X-My-Header"] = 'blah blah';
Многозначные заголовки можно установить так:
ngx.header['Set-Cookie'] = {'a=32; path=/', 'b=4; path=/'} что приведет к
Set-Cookie: a=32; path=/ Set-Cookie: b=4; path=/
в заголовках ответа.
Принимаются только Lua-таблицы (только последний элемент таблицы будет действовать для стандартных заголовков, таких как Content-Type, которые принимают только одно значение).
ngx.header.content_type = {'a', 'b'} эквивалентно
ngx.header.content_type = 'b'
Установка значения в nil эффективно удаляет его из заголовков ответа:
ngx.header["X-My-Header"] = nil;
То же самое относится к присвоению пустой таблицы:
ngx.header["X-My-Header"] = {}; Установка ngx.header.HEADER после отправки заголовков ответа (явно с помощью ngx.send_headers или неявно с помощью ngx.print и аналогичных функций) приведет к записи сообщения об ошибке.
Чтение ngx.header.HEADER вернет значение заголовка ответа с именем HEADER.
Подчеркивания (_) в именах заголовков также заменяются дефисами (-), и имена заголовков сопоставляются без учета регистра. Если заголовок ответа вообще отсутствует, возвращается nil.
Это особенно полезно в контексте header_filter_by_lua*, например,
location /test {
set $footer '';
proxy_pass http://some-backend;
header_filter_by_lua_block {
if ngx.header["X-My-Header"] == "blah" then
ngx.var.footer = "some value"
end
}
echo_after_body $footer;
} Для заголовков с несколькими значениями все значения заголовка будут собраны в порядке следования и возвращены в виде таблицы Lua. Например, заголовки ответа
Foo: bar Foo: baz
приведут к
{"bar", "baz"} будут возвращены при чтении ngx.header.Foo.
Обратите внимание, что ngx.header не является обычной таблицей Lua, и поэтому нельзя перебирать ее с помощью функции Lua ipairs.
Для чтения заголовков запроса используйте функцию ngx.req.get_headers вместо этого.
ngx.resp.get_headers
синтаксис: headers, err = ngx.resp.get_headers(max_headers?, raw?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, balancer_by_lua*
Возвращает таблицу Lua, содержащую все текущие заголовки ответа для текущего запроса.
local h, err = ngx.resp.get_headers() if err == "truncated" then -- one can choose to ignore or reject the current response here end for k, v in pairs(h) do ... end
Эта функция имеет тот же синтаксис, что и ngx.req.get_headers, за исключением того, что она получает заголовки ответа вместо заголовков запроса.
Обратите внимание, что по умолчанию анализируется максимум 100 заголовков ответа (включая те с одинаковым именем), а дополнительные заголовки ответа игнорируются для защиты от потенциальных атак типа отказа в обслуживании. С момента v0.10.13, при превышении лимита, возвращается второе значение, которое является строкой "truncated".
Этот API был впервые представлен в версии v0.9.5.
ngx.req.is_internal
синтаксис: is_internal = ngx.req.is_internal()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Возвращает логическое значение, указывающее, является ли текущий запрос "внутренним запросом", т.е. запросом, инициированным внутри текущего сервера nginx, а не со стороны клиента.
Подзапросы — это всегда внутренние запросы, как и запросы после внутренних редиректов.
Этот API был впервые представлен в версии v0.9.20.
ngx.req.start_time
синтаксис: secs = ngx.req.start_time()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Возвращает число с плавающей точкой, представляющее отметку времени (включая миллисекунды в качестве дробной части) создания текущего запроса.
Следующий пример эмулирует значение переменной $request_time (предоставленное модулем ngx_http_log_module) в чистом Lua:
local request_time = ngx.now() - ngx.req.start_time()
Эта функция была впервые представлена в версии v0.7.7.
См. также ngx.now и ngx.update_time.
ngx.req.http_version
синтаксис: num = ngx.req.http_version()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
Возвращает номер версии HTTP для текущего запроса как числовое значение Lua.
Возможные значения: 2.0, 1.0, 1.1 и 0.9. Возвращает nil для неизвестных значений.
Этот метод был впервые представлен в версии v0.7.17.
ngx.req.raw_header
синтаксис: str = ngx.req.raw_header(no_request_line?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
Возвращает исходный необработанный заголовок HTTP-протокола, полученный сервером Nginx.
По умолчанию в результат также включена строка запроса и заключительный CR LF терминатор. Например,
ngx.print(ngx.req.raw_header())
даёт что-то вроде этого:
GET /t HTTP/1.1 Host: localhost Connection: close Foo: bar
Можно указать необязательный параметр no_request_line со значением true, чтобы исключить строку запроса из результата. Например,
ngx.print(ngx.req.raw_header(true))
выведет что-то вроде этого:
Host: localhost Connection: close Foo: bar
Этот метод был впервые представлен в версии v0.7.17.
Этот метод пока не работает с запросами HTTP/2.
ngx.req.get_method
синтаксис: method_name = ngx.req.get_method()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, balancer_by_lua*
Возвращает имя метода запроса текущего запроса. Вместо числовых постоянных методов возвращаются строки, такие как "GET" и "POST".
Если текущий запрос является подзапросом Nginx, возвращается имя метода подзапроса.
Этот метод был впервые представлен в версии v0.5.6.
См. также ngx.req.set_method.
ngx.req.set_method
синтаксис: ngx.req.set_method(method_id)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*
Заменяет текущий метод запроса текущего запроса аргументом method_id. В настоящее время поддерживаются только числовые постоянные методы, такие как ngx.HTTP_POST и ngx.HTTP_GET.
Если текущий запрос является подзапросом Nginx, то метод подзапроса будет изменён.
Этот метод был впервые представлен в версии v0.5.6.
См. также ngx.req.get_method.
ngx.req.set_uri
синтаксис: ngx.req.set_uri(uri, jump?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
Изменяет текущий (разрешённый) URI запроса с помощью аргумента uri. Аргумент uri должен быть строкой Lua и не может быть пустой, иначе будет выброшено исключение Lua.
Необязательный булевый аргумент jump может инициировать повторный поиск расположения (или переход к расположению), как и директива rewrite модуля ngx_http_rewrite_module. То есть, когда jump имеет значение true (по умолчанию false), эта функция никогда не вернётся и сообщит Nginx о необходимости повторного поиска расположений с новым значением URI на последующей post-rewrite фазе и переходе к новому расположению.
В противном случае переход к расположению не произойдёт, а будет изменён только текущий URI запроса, что также является стандартным поведением. Функция вернётся без возвращаемых значений, если аргумент jump имеет значение false или отсутствует.
Например, следующий фрагмент конфигурации nginx
rewrite ^ /foo last;
может быть закодирован на Lua следующим образом:
ngx.req.set_uri("/foo", true) Аналогично, конфигурация Nginx
rewrite ^ /foo break;
может быть закодирована на Lua как
ngx.req.set_uri("/foo", false) или эквивалентно
ngx.req.set_uri("/foo") Аргумент jump может быть установлен только в true в rewrite_by_lua*. Использование перехода в других контекстах запрещено и приведёт к выбросу исключения Lua.
Более сложный пример, включающий подстановку по регулярному выражению:
location /test {
rewrite_by_lua_block {
local uri = ngx.re.sub(ngx.var.uri, "^/test/(.*)", "/$1", "o")
ngx.req.set_uri(uri)
}
proxy_pass http://my_backend;
} что функционально эквивалентно
location /test {
rewrite ^/test/(.*) /$1 break;
proxy_pass http://my_backend;
} Обратите внимание, что нельзя использовать этот интерфейс для изменения аргументов URI, и для этого следует использовать ngx.req.set_uri_args. Например, конфигурация Nginx
rewrite ^ /foo?a=3? last;
может быть закодирована как
ngx.req.set_uri_args("a=3")
ngx.req.set_uri("/foo", true) или
ngx.req.set_uri_args({a = 3})
ngx.req.set_uri("/foo", true) Этот интерфейс был впервые представлен в версии v0.3.1rc14.
ngx.req.set_uri_args
синтаксис: ngx.req.set_uri_args(args)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
Изменяет аргументы запроса URI текущего запроса с помощью аргумента args. Аргумент args может быть строкой Lua, как в
ngx.req.set_uri_args("a=3&b=hello%20world") или таблицей Lua, содержащей пары ключ-значение аргументов запроса, как в
ngx.req.set_uri_args({ a = 3, b = "hello world" }) в этом случае метод будет экранировать ключи и значения аргументов в соответствии с правилом экранирования URI.
Поддержка многозначных аргументов:
ngx.req.set_uri_args({ a = 3, b = {5, 6} }) что приведёт к строке запроса вида a=3&b=5&b=6.
Этот интерфейс был впервые представлен в версии v0.3.1rc13.
См. также ngx.req.set_uri.
ngx.req.get_uri_args
синтаксис: args, err = ngx.req.get_uri_args(max_args?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, balancer_by_lua*
Возвращает таблицу Lua, содержащую все текущие аргументы запроса URL.
location = /test {
content_by_lua_block {
local args, err = ngx.req.get_uri_args()
if err == "truncated" then
-- one can choose to ignore or reject the current request here
end
for key, val in pairs(args) do
if type(val) == "table" then
ngx.say(key, ": ", table.concat(val, ", "))
else
ngx.say(key, ": ", val)
end
end
}
} Затем GET /test?foo=bar&bar=baz&bar=blah вернёт тело ответа
foo: bar bar: baz, blah
Несколько вхождений ключа аргумента приведут к табличному значению, содержащему все значения этого ключа в порядке следования.
Ключи и значения деэкранированы в соответствии с правилами экранирования URI. В приведенных выше настройках GET /test?a%20b=1%61+2 вернёт:
a b: 1a 2
Аргументы без =<value> частей обрабатываются как булевые аргументы. GET /test?foo&bar вернёт:
foo: true bar: true
То есть, они будут принимать булевые значения Lua true. Однако они отличаются от аргументов, принимающих пустые строковые значения. GET /test?foo=&bar= даст что-то вроде
foo: bar:
Пустые ключевые аргументы отбрасываются. GET /test?=hello&=world вернёт пустой результат, например.
Обновление аргументов запроса с помощью переменной nginx $args (или ngx.var.args в Lua) во время выполнения также поддерживается:
ngx.var.args = "a=3&b=42" local args, err = ngx.req.get_uri_args()
Здесь таблица args всегда будет выглядеть как
{a = 3, b = 42} независимо от фактической строки запроса.
Обратите внимание, что по умолчанию анализируется максимум 100 аргументов запроса (включая те с одинаковыми именами), а дополнительные аргументы запроса игнорируются для защиты от потенциальных атак типа отказа в обслуживании. С момента v0.10.13, при превышении лимита, возвращается второе значение, которое является строкой "truncated".
Однако необязательный аргумент функции max_args может быть использован для переопределения этого лимита:
local args, err = ngx.req.get_uri_args(10) if err == "truncated" then -- one can choose to ignore or reject the current request here end
Этот аргумент может быть установлен в ноль, чтобы удалить лимит и обработать все полученные аргументы запроса:
local args, err = ngx.req.get_uri_args(0)
Удаление ограничения max_args категорически не рекомендуется.
ngx.req.get_post_args
синтаксис: args, err = ngx.req.get_post_args(max_args?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Возвращает Lua таблицу, содержащую все текущие аргументы запроса POST (типа MIME application/x-www-form-urlencoded). Вызовите ngx.req.read_body, чтобы сначала прочитать тело запроса, или включите директиву lua_need_request_body, чтобы избежать ошибок.
location = /test {
content_by_lua_block {
ngx.req.read_body()
local args, err = ngx.req.get_post_args()
if err == "truncated" then
-- one can choose to ignore or reject the current request here
end
if not args then
ngx.say("failed to get post args: ", err)
return
end
for key, val in pairs(args) do
if type(val) == "table" then
ngx.say(key, ": ", table.concat(val, ", "))
else
ngx.say(key, ": ", val)
end
end
}
} Затем
# Post request with the body 'foo=bar&bar=baz&bar=blah' $ curl --data 'foo=bar&bar=baz&bar=blah' localhost/test
будет выводить тело ответа, как
foo: bar bar: baz, blah
Несколько вхождений ключа аргумента приведут к табличному значению, содержащему все значения для этого ключа в порядке.
Ключи и значения будут декодированы в соответствии с правилами URI-кодирования.
При указанных выше настройках
# POST request with body 'a%20b=1%61+2' $ curl -d 'a%20b=1%61+2' localhost/test
будет выводить:
a b: 1a 2
Аргументы без =<value> частей рассматриваются как логические аргументы. POST /test с телом запроса foo&bar будет выводить:
foo: true bar: true
То есть они будут принимать логические значения Lua true. Однако они отличаются от аргументов, принимающих пустые строковые значения. POST /test с телом запроса foo=&bar= вернёт что-то вроде
foo: bar:
Пустые аргументы ключей отбрасываются. POST /test с телом =hello&=world, например, будут возвращать пустые результаты.
Обратите внимание, что по умолчанию анализируется максимум 100 аргументов запроса (включая аргументы с одинаковым именем), а дополнительные аргументы запроса отбрасываются для предотвращения потенциальных атак типа "отказ в обслуживании". С версии v0.10.13, при превышении лимита, возвращается второе значение, которое является строкой "truncated".
Однако, необязательный аргумент функции max_args может использоваться для переопределения этого ограничения:
local args, err = ngx.req.get_post_args(10) if err == "truncated" then -- one can choose to ignore or reject the current request here end
Этот аргумент можно установить в ноль, чтобы снять ограничение и обработать все полученные аргументы запроса:
local args, err = ngx.req.get_post_args(0)
Убирание ограничения max_args настоятельно не рекомендуется.
ngx.req.get_headers
синтаксис: headers, err = ngx.req.get_headers(max_headers?, raw?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Возвращает Lua таблицу, содержащую все текущие заголовки запроса.
local h, err = ngx.req.get_headers() if err == "truncated" then -- one can choose to ignore or reject the current request here end for k, v in pairs(h) do ... end
Чтобы прочитать отдельный заголовок:
ngx.say("Host: ", ngx.req.get_headers()["Host"]) Обратите внимание, что вызов API ngx.var.HEADER, использующий основные переменные $http_HEADER, может быть предпочтительнее для чтения отдельных заголовков запроса.
Для нескольких вхождений заголовков запроса, таких как:
Foo: foo Foo: bar Foo: baz
значение ngx.req.get_headers()["Foo"] будет Lua-таблицей (массивом), такой как:
{"foo", "bar", "baz"} Обратите внимание, что по умолчанию анализируется максимум 100 заголовков запроса (включая заголовки с одинаковым именем), а дополнительные заголовки запроса отбрасываются для предотвращения потенциальных атак типа "отказ в обслуживании". С версии v0.10.13, при превышении лимита, возвращается второе значение, которое является строкой "truncated".
Однако, необязательный аргумент функции max_headers может использоваться для переопределения этого ограничения:
local headers, err = ngx.req.get_headers(10) if err == "truncated" then -- one can choose to ignore or reject the current request here end
Этот аргумент можно установить в ноль, чтобы снять ограничение и обработать все полученные заголовки запроса:
local headers, err = ngx.req.get_headers(0)
Убирание ограничения max_headers настоятельно не рекомендуется.
С версии 0.6.9, все имена заголовков в возвращаемой Lua таблице по умолчанию преобразуются в чистый нижний регистр, если не указано иное, с помощью аргумента raw, который установлен в true (по умолчанию false).
Также по умолчанию к полученной Lua таблице добавляется метаметод __index, который нормализует ключи к чистому нижнему регистру, заменяя все символы подчеркивания на дефисы в случае промаха при поиске. Например, если заголовок запроса My-Foo-Header присутствует, следующие вызовы правильно получат значение этого заголовка:
ngx.say(headers.my_foo_header) ngx.say(headers["My-Foo-Header"]) ngx.say(headers["my-foo-header"])
Метаметод __index не будет добавлен, если аргумент raw установлен в true.
ngx.req.set_header
синтаксис: ngx.req.set_header(header_name, header_value)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
Устанавливает заголовок запроса текущего запроса с именем header_name на значение header_value, перезаписывая любые существующие.
По умолчанию все последующие подзапросы, инициированные с помощью ngx.location.capture и ngx.location.capture_multi, унаследуют новый заголовок.
Вот пример установки заголовка Content-Type:
ngx.req.set_header("Content-Type", "text/css") Аргумент header_value может принимать список значений, например
ngx.req.set_header("Foo", {"a", "abc"}) сгенерирует два новых заголовка запроса:
Foo: a Foo: abc
и старые заголовки Foo будут перезаписаны, если таковые есть.
Когда аргумент header_value равен nil, заголовок запроса будет удалён. Таким образом
ngx.req.set_header("X-Foo", nil) эквивалентно
ngx.req.clear_header("X-Foo") ngx.req.clear_header
синтаксис: ngx.req.clear_header(header_name)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*
Очищает заголовок запроса текущего запроса с именем header_name. Ни один из текущих подзапросов запроса не будет затронут, но последующие подзапросы по умолчанию унаследуют изменения.
ngx.req.read_body
синтаксис: ngx.req.read_body()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Асинхронно считывает тело запроса клиента без блокировки цикла событий Nginx.
ngx.req.read_body() local args = ngx.req.get_post_args()
Если тело запроса уже было прочитано ранее, включением lua_need_request_body или с помощью других модулей, эта функция не выполняется и возвращает результат немедленно.
Если тело запроса уже было явно отброшено функцией ngx.req.discard_body или другими модулями, эта функция не выполняется и возвращает результат немедленно.
В случае ошибок, таких как ошибки соединения при чтении данных, этот метод генерирует Lua исключение или немедленно завершает текущий запрос со статусом 500.
Данные тела запроса, прочитанные с помощью этой функции, могут быть получены позже через ngx.req.get_body_data или, как альтернатива, имя временного файла для данных тела, кэшированных на диске, с помощью ngx.req.get_body_file. Это зависит от
- является ли текущее тело запроса больше, чем client_body_buffer_size,
- и включён ли client_body_in_file_only.
В случаях, когда текущий запрос может иметь тело запроса, а данные тела запроса не требуются, функция ngx.req.discard_body должна использоваться для явного отбрасывания тела запроса, чтобы избежать проблем при HTTP 1.1 keepalive или HTTP 1.1 pipelining.
Функция была впервые представлена в версии v0.3.1rc17.
ngx.req.discard_body
синтаксис: ngx.req.discard_body()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Явно отбрасывает тело запроса, т.е. считывает данные по соединению и сразу их удаляет (без использования тела запроса никоим образом).
Эта функция является асинхронным вызовом и возвращает результат немедленно.
Если тело запроса уже прочитано, эта функция ничего не делает и возвращает результат немедленно.
Функция была впервые представлена в версии v0.3.1rc17.
См. также ngx.req.read_body.
ngx.req.get_body_data
синтаксис: data = ngx.req.get_body_data()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, log_by_lua*
Получает данные тела запроса в памяти. Возвращает Lua строку, а не Lua таблицу, содержащую все обработанные аргументы запроса. Используйте функцию ngx.req.get_post_args вместо этого, если требуется Lua таблица.
Функция возвращает nil если
- тело запроса не было прочитано,
- тело запроса было записано во временные файлы на диске,
- или размер тела запроса равен нулю.
Если тело запроса ещё не прочитано, сначала вызовите ngx.req.read_body (или включите lua_need_request_body, чтобы заставить этот модуль прочитать тело запроса. Это не рекомендуется).
Если тело запроса было записано в файлы на диске, попробуйте вызвать функцию ngx.req.get_body_file вместо этого.
Чтобы форсировать использование тела запроса в памяти, установите client_body_buffer_size на то же значение, что и в client_max_body_size.
Обратите внимание, что вызов этой функции вместо использования ngx.var.request_body или ngx.var.echo_request_body более эффективен, так как это может сэкономить одну динамическую выделение памяти и одну копирование данных.
Функция была впервые представлена в версии v0.3.1rc17.
См. также ngx.req.get_body_file.
ngx.req.get_body_file
синтаксис: file_name = ngx.req.get_body_file()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Возвращает имя файла для данных тела запроса в файле. Возвращает nil, если тело запроса не было прочитано или было прочитано в память.
Возвращаемый файл предназначен только для чтения и обычно очищается пулом памяти Nginx. Его не следует изменять, переименовывать или удалять в коде Lua.
Если тело запроса ещё не прочитано, сначала вызовите ngx.req.read_body (или включите lua_need_request_body, чтобы заставить этот модуль прочитать тело запроса. Это не рекомендуется).
Если тело запроса было прочитано в память, попробуйте вызвать функцию ngx.req.get_body_data вместо этого.
Чтобы принудительно использовать тела запросов из файла, попробуйте включить client_body_in_file_only.
Эта функция была впервые представлена в v0.3.1rc17 версии.
См. также ngx.req.get_body_data.
ngx.req.set_body_data
синтаксис: ngx.req.set_body_data(данные)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Установите тело текущего запроса, используя данные в памяти, указанные аргументом data.
Если тело текущего запроса ещё не было прочитано, оно будет корректно удалено. Если тело текущего запроса уже загружено в память или буферизовано в файл на диске, то память старого тела запроса будет освобождена или файл на диске будет очищен соответственно.
Эта функция была впервые представлена в v0.3.1rc18 версии.
См. также ngx.req.set_body_file.
ngx.req.set_body_file
синтаксис: ngx.req.set_body_file(имя_файла, авто_очистка?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Установите тело текущего запроса, используя данные из файла, указанные аргументом file_name.
Если необязательный аргумент auto_clean задан со значением true, то этот файл будет удалён по завершении запроса или в следующий раз, когда эта функция или ngx.req.set_body_data будут вызваны в рамках этого запроса. Значение auto_clean по умолчанию равно false.
Убедитесь, что файл, указанный аргументом file_name, существует и доступен для чтения процессом Nginx, правильно установив его права доступа, чтобы избежать ошибок Lua.
Если тело текущего запроса ещё не было прочитано, оно будет корректно удалено. Если тело текущего запроса уже загружено в память или буферизовано в файл на диске, то память старого тела запроса будет освобождена или файл на диске будет очищен соответственно.
Эта функция была впервые представлена в v0.3.1rc18 версии.
См. также ngx.req.set_body_data.
ngx.req.init_body
синтаксис: ngx.req.init_body(размер_буфера?)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
Создаёт новое пустое тело запроса для текущего запроса и инициализирует буфер для последующей записи данных тела запроса с помощью API ngx.req.append_body и ngx.req.finish_body.
Если аргумент buffer_size задан, его значение будет использоваться для размера буфера памяти для записи тела запроса с помощью ngx.req.append_body. Если аргумент опущен, будет использоваться значение, заданное директивой client_body_buffer_size.
Когда данные больше не могут поместиться в буфер памяти тела запроса, они будут выгружены во временный файл, как и в стандартном обработчике тела запроса в ядре Nginx.
Важно всегда вызывать ngx.req.finish_body после добавления всех данных в тело текущего запроса. Также, при использовании этой функции вместе с ngx.req.socket, необходимо вызвать ngx.req.socket перед этой функцией, иначе вы получите сообщение об ошибке "тело запроса уже существует".
Пример использования:
ngx.req.init_body(128 * 1024) -- buffer is 128KB for chunk in next_data_chunk() do ngx.req.append_body(chunk) -- each chunk can be 4KB end ngx.req.finish_body()
Эта функция может использоваться с ngx.req.append_body, ngx.req.finish_body и ngx.req.socket для реализации эффективных фильтров ввода в чистом Lua (в контексте rewrite_by_lua* или access_by_lua*), которые могут использоваться с другими обработчиками контента Nginx или модулями upstream, такими как ngx_http_proxy_module и ngx_http_fastcgi_module.
Эта функция была впервые представлена в v0.5.11 версии.
ngx.req.append_body
синтаксис: ngx.req.append_body(кусок_данных)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
Добавляет новый кусок данных, указанный аргументом data_chunk, к существующему телу запроса, созданному вызовом ngx.req.init_body.
Когда данные больше не могут поместиться в буфер памяти тела запроса, они будут выгружены во временный файл, как и в стандартном обработчике тела запроса в ядре Nginx.
Важно всегда вызывать ngx.req.finish_body после добавления всех данных в тело текущего запроса.
Эта функция может использоваться с ngx.req.init_body, ngx.req.finish_body и ngx.req.socket для реализации эффективных фильтров ввода в чистом Lua (в контексте rewrite_by_lua* или access_by_lua*), которые могут использоваться с другими обработчиками контента Nginx или модулями upstream, такими как ngx_http_proxy_module и ngx_http_fastcgi_module.
Эта функция была впервые представлена в v0.5.11 версии.
См. также ngx.req.init_body.
ngx.req.finish_body
синтаксис: ngx.req.finish_body()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
Завершает процесс построения нового тела запроса, созданного вызовами ngx.req.init_body и ngx.req.append_body.
Эта функция может использоваться с ngx.req.init_body, ngx.req.append_body и ngx.req.socket для реализации эффективных фильтров ввода в чистом Lua (в контексте rewrite_by_lua* или access_by_lua*), которые могут использоваться с другими обработчиками контента Nginx или модулями upstream, такими как ngx_http_proxy_module и ngx_http_fastcgi_module.
Эта функция была впервые представлена в v0.5.11 версии.
См. также ngx.req.init_body.
ngx.req.socket
синтаксис: tcpsock, err = ngx.req.socket()
синтаксис: tcpsock, err = ngx.req.socket(raw)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Возвращает объект cosocket для чтения, который оборачивает подключение вниз по потоку. Поддерживаются только методы receive и receiveuntil для этого объекта.
В случае ошибки, возвращается nil вместе со строкой, описывающей ошибку.
Объект сокета, возвращаемый этим методом, обычно используется для чтения тела текущего запроса в потоковом режиме. Не включайте директиву lua_need_request_body и не смешивайте этот вызов с ngx.req.read_body и ngx.req.discard_body.
Если данные тела запроса были предварительно прочитаны в буфер заголовков запроса ядра Nginx, возвращаемый объект cosocket позаботится об этом, чтобы избежать потенциальной потери данных из-за такого предварительного чтения. Чанкированные тела запросов пока не поддерживаются в этом API.
Начиная с версии v0.9.0, эта функция принимает необязательный булевый аргумент raw. Когда этот аргумент имеет значение true, эта функция возвращает объект full-duplex cosocket, оборачивающий первичный сокет подключения вниз по потоку, для которого вы можете вызвать методы receive, receiveuntil и send.
Когда аргумент raw имеет значение true, требуется, чтобы не было ожидающих данных от предыдущих вызовов ngx.say, ngx.print или ngx.send_headers. Поэтому, если у вас были эти вызовы вывода вниз по потоку, вы должны вызвать ngx.flush(true) перед вызовом ngx.req.socket(true), чтобы убедиться, что нет ожидающих данных вывода. Если тело запроса ещё не было прочитано, этот «сырой сокет» также может быть использован для чтения тела запроса.
Вы можете использовать «сырой сокет запроса», возвращаемый ngx.req.socket(true), для реализации сложных протоколов, таких как WebSocket, или просто для отправки собственных заголовков или данных тела HTTP-ответа. Для реального примера обратитесь к библиотеке lua-resty-websocket.
Эта функция была впервые представлена в v0.5.0rc1 версии.
ngx.exec
синтаксис: ngx.exec(uri, args?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Выполняет внутренний переадресации на uri с args и аналогичен директиве echo_exec модуля echo-nginx-module.
ngx.exec('/some-location');
ngx.exec('/some-location', 'a=3&b=5&c=6');
ngx.exec('/some-location?a=3&b=5', 'c=6'); Необязательный второй аргумент args может использоваться для указания дополнительных аргументов запроса URI, например:
ngx.exec("/foo", "a=3&b=hello%20world") В качестве альтернативы, для аргумента args можно передать таблицу Lua, чтобы ngx_lua выполнил экранирование URI и конкатенацию строк.
ngx.exec("/foo", { a = 3, b = "hello world" }) Результат будет точно таким же, как в предыдущем примере.
Формат таблицы Lua, передаваемой в качестве аргумента args, идентичен формату, используемому в методе ngx.encode_args.
Поддерживаются и именованные места, но второй аргумент args будет проигнорирован, если он присутствует, и строка запроса для новой цели будет унаследована от места ссылки (если таковое есть).
GET /foo/file.php?a=hello вернёт "hello", а не "goodbye" в приведённом ниже примере
location /foo {
content_by_lua_block {
ngx.exec("@bar", "a=goodbye");
}
}
location @bar {
content_by_lua_block {
local args = ngx.req.get_uri_args()
for key, val in pairs(args) do
if key == "a" then
ngx.say(val)
end
end
}
} Обратите внимание, что метод ngx.exec отличается от ngx.redirect тем, что он представляет собой чисто внутренний переадресацию и не вовлекает нового внешнего HTTP-трафика.
Также обратите внимание, что этот метод вызывает завершение обработки текущего запроса и что он обязательно должен быть вызван перед ngx.send_headers или явным выводом тела ответа с помощью ngx.print или ngx.say.
Рекомендуется использовать стиль кодирования, который сочетает этот метод вызова с оператором return, то есть return ngx.exec(...), когда этот метод вызывается в контекстах, отличных от header_filter_by_lua*, чтобы подчеркнуть тот факт, что обработка запроса завершается.
ngx.redirect
синтаксис: ngx.redirect(uri, status?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Выполните HTTP 301 или 302 перенаправление на uri.
Необязательный параметр status указывает код HTTP-статуса, который будет использоваться. В настоящее время поддерживаются следующие коды статуса:
301-
302(по умолчанию) 303307308
По умолчанию это 302 (ngx.HTTP_MOVED_TEMPORARILY).
Вот пример, предполагая, что текущее имя сервера — localhost, и что он прослушивает порт 1984:
return ngx.redirect("/foo") что эквивалентно
return ngx.redirect("/foo", ngx.HTTP_MOVED_TEMPORARILY) Также поддерживается перенаправление произвольных внешних URL-адресов, например:
return ngx.redirect("http://www.google.com") Мы также можем использовать числовой код непосредственно в качестве второго status аргумента:
return ngx.redirect("/foo", 301) Этот метод аналогичен директиве rewrite с модификатором redirect в стандартном модуле ngx_http_rewrite_module, например, этот nginx.conf фрагмент
rewrite ^ /foo? redirect; # nginx config
эквивалентен следующему коду Lua
return ngx.redirect('/foo'); -- Lua code в то время как
rewrite ^ /foo? permanent; # nginx config
эквивалентно
return ngx.redirect('/foo', ngx.HTTP_MOVED_PERMANENTLY) -- Lua code Также можно указать аргументы URI, например:
return ngx.redirect('/foo?a=3&b=4') Обратите внимание, что этот метод вызова завершает обработку текущего запроса и что его обязательно следует вызывать до ngx.send_headers или явного вывода тела ответа с помощью ngx.print или ngx.say.
Рекомендуется использовать стиль кодирования, сочетающий этот вызов метода с оператором return, то есть return ngx.redirect(...), при использовании этого вызова метода в контекстах, отличных от header_filter_by_lua*, чтобы подчеркнуть тот факт, что обработка запроса завершается.
ngx.send_headers
синтаксис: ok, err = ngx.send_headers()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Явно отправляет заголовки ответа.
Поскольку v0.8.3 эта функция возвращает 1 при успехе или возвращает nil и строку, описывающую ошибку в противном случае.
Обратите внимание, что обычно нет необходимости вручную отправлять заголовки ответа, так как ngx_lua автоматически отправляет заголовки перед выводом содержимого с помощью ngx.say или ngx.print или когда content_by_lua* завершается нормально.
ngx.headers_sent
синтаксис: value = ngx.headers_sent
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*
Возвращает true, если заголовки ответа были отправлены (ngx_lua), и false в противном случае.
Этот API был впервые представлен в ngx_lua v0.3.1rc6.
ngx.print
синтаксис: ok, err = ngx.print(...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Выводит аргументы, объединенные в HTTP-клиент (как тело ответа). Если заголовки ответа не были отправлены, эта функция отправит заголовки сначала, а затем выведет данные тела.
Поскольку v0.8.3 эта функция возвращает 1 при успехе или возвращает nil и строку, описывающую ошибку в противном случае.
Значения Lua nil будут выводить строки "nil", а значения Lua boolean будут выводить строки "true" и "false" соответственно.
Разрешены вложенные массивы строк, и элементы массивов будут отправляться по одному:
local table = {
"hello, ",
{"world: ", true, " or ", false,
{": ", nil}}
}
ngx.print(table) приведет к выводу
hello, world: true or false: nil
Аргументы таблиц, не являющихся массивами, приведут к выбрасыванию исключения Lua.
Константа ngx.null даст в результате вывод строки "null".
Это асинхронный вызов, и он возвращается немедленно, не ожидая, пока все данные будут записаны в буфер отправки системы. Чтобы запустить в синхронном режиме, вызовите ngx.flush(true) после вызова ngx.print. Это особенно полезно для потокового вывода. См. ngx.flush для получения дополнительной информации.
Обратите внимание, что как ngx.print, так и ngx.say всегда вызывают всю цепочку фильтров тела вывода Nginx, что является дорогостоящей операцией. Будьте осторожны при вызове их в цикле; буферизуйте данные самостоятельно в Lua и сохраняйте вызовы.
ngx.say
синтаксис: ok, err = ngx.say(...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
То же, что и ngx.print, но также выводит заключительную новую строку.
ngx.log
синтаксис: ngx.log(log_level, ...)
контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Логирует аргументы, объединенные в error.log с заданным уровнем ведения журнала.
Принимаются аргументы Lua nil, что приводит к выводу строковой литералы "nil", а булевы значения Lua — к строковым литералам "true" или "false" соответственно. А константа ngx.null выведет строку "null".
Аргумент log_level может принимать константы, такие как ngx.ERR и ngx.WARN. Подробности см. в разделе Nginx log level constants.
В ядре Nginx существует жестко заданное ограничение на длину сообщений об ошибках в 2048 байт. Это ограничение включает завершающие новые строки и предваряющие временные метки. Если размер сообщения превышает это ограничение, Nginx усекает текст сообщения соответственно. Это ограничение можно изменить вручную, отредактировав определение макроса NGX_MAX_ERROR_STR в файле src/core/ngx_log.h в дереве исходных кодов Nginx.
ngx.flush
синтаксис: ok, err = ngx.flush(wait?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Очищает вывод ответа для клиента.
ngx.flush принимает необязательный булев аргумент wait (По умолчанию: false), впервые представленный в выпуске v0.3.1rc34. При вызове с аргументом по умолчанию он выполняет асинхронный вызов (Возвращается немедленно, не ожидая, пока данные вывода будут записаны в буфер отправки системы). Вызов функции с аргументом wait, установленным в true, переключает режим на синхронный.
В синхронном режиме функция не возвращается, пока все данные вывода не будут записаны в буфер отправки системы или пока не истечет время ожидания send_timeout. Обратите внимание, что использование механизма корутин Lua означает, что эта функция не блокирует цикл событий Nginx даже в синхронном режиме.
Вызов ngx.flush(true) сразу после ngx.print или ngx.say приводит к тому, что последние функции работают в синхронном режиме. Это особенно полезно для потокового вывода.
Обратите внимание, что ngx.flush не работает в режиме буферизации вывода HTTP 1.0. См. HTTP 1.0 support.
Поскольку v0.8.3 эта функция возвращает 1 при успехе или возвращает nil и строку, описывающую ошибку в противном случае.
ngx.exit
синтаксис: ngx.exit(status)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Если status >= 200 (то есть ngx.HTTP_OK и выше), он прервет выполнение текущего запроса и вернёт код состояния Nginx.
Если status == 0 (то есть ngx.OK), он выйдет только из текущего обработчика фазы (или обработчика содержимого, если используется директива content_by_lua*) и продолжит выполнение последующих фаз (если таковые имеются) для текущего запроса.
Аргумент status может быть ngx.OK, ngx.ERROR, ngx.HTTP_NOT_FOUND, ngx.HTTP_MOVED_TEMPORARILY или другими константами HTTP-состояний HTTP status constants.
Чтобы вернуть страницу ошибки с пользовательским содержимым, используйте фрагменты кода, подобные этому:
ngx.status = ngx.HTTP_GONE
ngx.say("This is our own content")
-- to cause quit the whole request rather than the current phase handler
ngx.exit(ngx.HTTP_OK) Эффект в действии:
$ curl -i http://localhost/test HTTP/1.1 410 Gone Server: nginx/1.0.6 Date: Thu, 15 Sep 2011 00:51:48 GMT Content-Type: text/plain Transfer-Encoding: chunked Connection: keep-alive This is our own content
Числовые литералы могут быть использованы непосредственно в качестве аргумента, например,
ngx.exit(501)
Обратите внимание, что, хотя этот метод принимает все константы HTTP-состояний HTTP status constants в качестве входных данных, он принимает только ngx.OK и ngx.ERROR из констант ядра core constants.
Также обратите внимание, что этот вызов метода завершает обработку текущего запроса, и рекомендуется использовать стиль кодирования, сочетающий этот вызов метода с оператором return, то есть return ngx.exit(...), для подтверждения того, что обработка запроса завершена.
При использовании в контекстах header_filter_by_lua*, balancer_by_lua* и ssl_session_store_by_lua*, ngx.exit() является асинхронной операцией и возвращается немедленно. Это поведение может измениться в будущем, и рекомендуется всегда использовать return в сочетании, как предложено выше.
ngx.eof
синтаксис: ok, err = ngx.eof()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Явно укажите конец потока вывода ответа. В случае вывода с фрагментацией HTTP 1.1 он просто запустит ядро Nginx для отправки «последнего фрагмента».
Когда вы отключаете функцию HTTP 1.1 keep-alive для своих подключений вниз по потоку, вы можете полагаться на правильно написанные HTTP-клиенты, которые будут активно закрывать соединение за вас при вызове этого метода. Этот трюк можно использовать для выполнения фоновых задач, не заставляя HTTP-клиенты ожидать соединения, как показано в следующем примере:
location = /async {
keepalive_timeout 0;
content_by_lua_block {
ngx.say("got the task!")
ngx.eof() -- well written HTTP clients will close the connection at this point
-- access MySQL, PostgreSQL, Redis, Memcached, and etc here...
}
} Но если вы создаете подзапросы для доступа к другим местам, настроенным модулями Nginx upstream, то вы должны настроить эти модули upstream на игнорирование прерываний клиентского соединения, если они по умолчанию не игнорируются. Например, по умолчанию стандартный модуль ngx_http_proxy_module завершит как подзапрос, так и основной запрос, как только клиент закроет соединение, поэтому важно включить директиву proxy_ignore_client_abort в вашем блоке location, настроенном модулем ngx_http_proxy_module:
proxy_ignore_client_abort on;
Лучший способ выполнения фоновых задач — использовать API ngx.timer.at.
Поскольку v0.8.3 эта функция возвращает 1 при успехе или возвращает nil и строку, описывающую ошибку в противном случае.
ngx.sleep
Синтаксис: ngx.sleep(секунды)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Засыпает на указанное количество секунд без блокировки. Можно указать разрешение времени до 0,001 секунды (т. е. одной миллисекунды).
За кулисами этот метод использует таймеры Nginx.
С момента 0.7.20 выпуска, аргумент времени 0 также может быть указан.
Этот метод был представлен в выпуске 0.5.0rc30.
ngx.escape_uri
Синтаксис: newstr = ngx.escape_uri(str)
Контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Экранирование str как компонента URI.
ngx.unescape_uri
Синтаксис: newstr = ngx.unescape_uri(str)
Контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*
Декодирование str как закодированного компонента URI.
Например,
ngx.say(ngx.unescape_uri("b%20r56+7")) дает вывод
b r56 7
ngx.encode_args
Синтаксис: str = ngx.encode_args(таблица)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*
Кодирует Lua-таблицу в строку аргументов запроса в соответствии с правилами кодирования URI.
Например,
ngx.encode_args({foo = 3, ["b r"] = "hello world"}) дает
foo=3&b%20r=hello%20world
Ключи таблицы должны быть Lua-строками.
Поддерживаются также многозначные аргументы запроса. Просто используйте Lua-таблицу для значения аргумента, например:
ngx.encode_args({baz = {32, "hello"}}) дает
baz=32&baz=hello
Если таблица значений пуста, эффект эквивалентен значению nil.
Поддерживаются также булевы значения аргументов, например,
ngx.encode_args({a = true, b = 1}) дает
a&b=1
Если значение аргумента равно false, то эффект эквивалентен значению nil.
Этот метод был впервые представлен в выпуске v0.3.1rc27.
ngx.decode_args
Синтаксис: таблица, ошибка = ngx.decode_args(строка, max_args?)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Декодирует закодированную по URI строку запроса в Lua-таблицу. Это обратная функция ngx.encode_args.
Необязательный аргумент max_args можно использовать для указания максимального количества аргументов, проанализированных из аргумента str. По умолчанию анализируется максимум 100 аргументов запроса (включая аргументы с одинаковым именем), и дополнительные аргументы URI молча отбрасываются для защиты от потенциальных атак типа «отказ в обслуживании». С момента v0.10.13 выпуска, при превышении лимита, возвращается второе значение, которое является строкой "truncated".
Этот аргумент можно установить в ноль, чтобы удалить ограничение и обработать все полученные аргументы запроса:
local args = ngx.decode_args(str, 0)
Удаление ограничения max_args категорически не рекомендуется.
Этот метод был представлен в выпуске v0.5.0rc29.
ngx.encode_base64
Синтаксис: newstr = ngx.encode_base64(str, no_padding?)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Кодирует str в базу 64.
С момента 0.9.16 выпуска, необязательный аргумент типа boolean no_padding можно указать для управления тем, следует ли добавлять базу 64 заполнение к полученному результату (по умолчанию false, то есть с включенным заполнением).
ngx.decode_base64
Синтаксис: newstr = ngx.decode_base64(str)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Декодирует аргумент str как базу 64 в исходную форму. Возвращает nil, если str не имеет правильного формата.
ngx.crc32_short
Синтаксис: intval = ngx.crc32_short(str)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Вычисляет контрольную сумму CRC-32 (циклический избыточный код) для аргумента str.
Этот метод работает лучше на относительно коротких входных данных str (т. е. менее 30 ~ 60 байт) по сравнению с ngx.crc32_long. Результат точно такой же, как у ngx.crc32_long.
За кулисами это просто тонкий оболочку вокруг функции ngx_crc32_short, определенной в ядре Nginx.
Этот API был впервые представлен в выпуске v0.3.1rc8.
ngx.crc32_long
Синтаксис: intval = ngx.crc32_long(str)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Вычисляет контрольную сумму CRC-32 (циклический избыточный код) для аргумента str.
Этот метод работает лучше на относительно длинных входных данных str (т. е. длиннее 30 ~ 60 байт) по сравнению с ngx.crc32_short. Результат точно такой же, как у ngx.crc32_short.
За кулисами это просто тонкий оболочку вокруг функции ngx_crc32_long, определенной в ядре Nginx.
Этот API был впервые представлен в выпуске v0.3.1rc8.
ngx.hmac_sha1
Синтаксис: digest = ngx.hmac_sha1(секретный_ключ, str)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Вычисляет дайджест HMAC-SHA1 аргумента str и преобразует результат с использованием секретного ключа <secret_key>.
Будет сгенерирован исходный двоичный дайджест HMAC-SHA1. Для кодирования результата в текстовое представление используйте, например, ngx.encode_base64.
Например,
local key = "thisisverysecretstuff" local src = "some string we want to sign" local digest = ngx.hmac_sha1(key, src) ngx.say(ngx.encode_base64(digest))
дает вывод
R/pvxzHC4NLtj7S+kXFg/NePTmk=
Этот API требует поддержки библиотеки OpenSSL в сборке Nginx (обычно путем передачи опции --with-http_ssl_module в скрипт ./configure).
Эта функция была впервые представлена в выпуске v0.3.1rc29.
ngx.md5
Синтаксис: digest = ngx.md5(строка)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает шестнадцатеричное представление дайджеста MD5 аргумента str.
Например,
location = /md5 {
content_by_lua_block { ngx.say(ngx.md5("hello")) }
} дает вывод
5d41402abc4b2a76b9719d911017c592
См. ngx.md5_bin, если требуется исходный двоичный дайджест MD5.
ngx.md5_bin
Синтаксис: digest = ngx.md5_bin(строка)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает двоичную форму дайджеста MD5 аргумента str.
См. ngx.md5, если требуется шестнадцатеричная форма дайджеста MD5.
ngx.sha1_bin
Синтаксис: digest = ngx.sha1_bin(строка)
Контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает двоичную форму дайджеста SHA-1 аргумента str.
Для работы этой функции требуется поддержка SHA-1 в сборке Nginx. (Обычно это означает, что необходимо установить OpenSSL при сборке Nginx).
Эта функция была впервые представлена в v0.5.0rc6.
ngx.quote_sql_str
синтаксис: quoted_value = ngx.quote_sql_str(raw_value)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает строку SQL, заключённую в кавычки, в соответствии с правилами цитирования MySQL.
ngx.today
синтаксис: str = ngx.today()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает текущую дату (в формате yyyy-mm-dd) из кэшированного времени Nginx (без системных вызовов в отличие от библиотеки даты Lua).
Это локальное время.
ngx.time
синтаксис: secs = ngx.time()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает количество прошедших секунд с эпохи для текущего временного отметки из кэшированного времени Nginx (без системных вызовов в отличие от библиотеки даты Lua).
Обновление кэша времени Nginx можно принудительно выполнить, вызвав ngx.update_time сначала.
ngx.now
синтаксис: secs = ngx.now()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает число с плавающей точкой, представляющее количество прошедших секунд (включая миллисекунды в качестве десятичной части) с эпохи для текущей временной отметки из кэшированного времени Nginx (без системных вызовов в отличие от библиотеки даты Lua).
Вы можете принудительно обновить кэш времени Nginx, вызвав ngx.update_time сначала.
Этот API был впервые представлен в v0.3.1rc32.
ngx.update_time
синтаксис: ngx.update_time()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Принудительно обновляет кэш текущего времени Nginx. Этот вызов предполагает системный вызов и, следовательно, имеет некоторую нагрузку, поэтому не злоупотребляйте им.
Этот API был впервые представлен в v0.3.1rc32.
ngx.localtime
синтаксис: str = ngx.localtime()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает текущую временную метку (в формате yyyy-mm-dd hh:mm:ss) из кэшированного времени Nginx (без системных вызовов в отличие от функции Lua os.date).
Это локальное время.
ngx.utctime
синтаксис: str = ngx.utctime()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает текущую временную метку (в формате yyyy-mm-dd hh:mm:ss) из кэшированного времени Nginx (без системных вызовов в отличие от функции Lua os.date).
Это время UTC.
ngx.cookie_time
синтаксис: str = ngx.cookie_time(sec)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает отформатированную строку, которая может быть использована как время истечения срока действия cookie. Параметр sec — временная метка в секундах (такие, как возвращаемые функцией ngx.time).
ngx.say(ngx.cookie_time(1290079655)) -- yields "Thu, 18-Nov-10 11:27:35 GMT"
ngx.http_time
синтаксис: str = ngx.http_time(sec)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает отформатированную строку, которая может быть использована как время http-заголовка (например, используемое в заголовке Last-Modified). Параметр sec — временная метка в секундах (такие, как возвращаемые функцией ngx.time).
ngx.say(ngx.http_time(1290079655)) -- yields "Thu, 18 Nov 2010 11:27:35 GMT"
ngx.parse_http_time
синтаксис: sec = ngx.parse_http_time(str)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Парсит строку времени http (как возвращаемая функцией ngx.http_time) в секунды. Возвращает количество секунд или nil, если входная строка имеет неправильный формат.
local time = ngx.parse_http_time("Thu, 18 Nov 2010 11:27:35 GMT")
if time == nil then
...
end ngx.is_subrequest
синтаксис: value = ngx.is_subrequest
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*
Возвращает true, если текущий запрос является подзапросом Nginx, или false в противном случае.
ngx.re.match
синтаксис: captures, err = ngx.re.match(subject, regex, options?, ctx?, res_table?)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Сопоставляет строку subject с регулярным выражением, совместимым с Perl, regex с необязательными options.
Возвращается только первое совпадение или nil, если совпадение не найдено. В случае ошибок, таких как некорректное регулярное выражение или превышение лимита стека PCRE, возвращается nil и строка, описывающая ошибку.
Если совпадение найдено, возвращается таблица Lua captures, где captures[0] содержит всю подстроку, с которой происходит совпадение, а captures[1] содержит первую подстроку с захваченным подвыражением, captures[2] — вторую и так далее.
local m, err = ngx.re.match("hello, 1234", "[0-9]+")
if m then
-- m[0] == "1234"
else
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end
ngx.say("match not found")
end local m, err = ngx.re.match("hello, 1234", "([0-9])[0-9]+")
-- m[0] == "1234"
-- m[1] == "1" Поддержка именованных захватов также поддерживается с выпуска v0.7.14 и возвращается в той же таблице Lua в виде пар «ключ-значение», что и пронумерованные захваты.
local m, err = ngx.re.match("hello, 1234", "([0-9])(?<remaining>[0-9]+)")
-- m[0] == "1234"
-- m[1] == "1"
-- m[2] == "234"
-- m["remaining"] == "234" Несовпавшие подвыражения будут иметь значения false в полях таблицы captures.
local m, err = ngx.re.match("hello, world", "(world)|(hello)|(?<named>howdy)")
-- m[0] == "hello"
-- m[1] == false
-- m[2] == "hello"
-- m[3] == false
-- m["named"] == false Укажите options, чтобы контролировать, как будет выполняться операция сопоставления. Поддерживаются следующие символы опций:
a anchored mode (only match from the beginning)
d enable the DFA mode (or the longest token match semantics).
this requires PCRE 6.0+ or else a Lua exception will be thrown.
first introduced in ngx_lua v0.3.1rc30.
D enable duplicate named pattern support. This allows named
subpattern names to be repeated, returning the captures in
an array-like Lua table. for example,
local m = ngx.re.match("hello, world",
"(?<named>\w+), (?<named>\w+)",
"D")
-- m["named"] == {"hello", "world"}
this option was first introduced in the v0.7.14 release.
this option requires at least PCRE 8.12.
i case insensitive mode (similar to Perl's /i modifier)
j enable PCRE JIT compilation, this requires PCRE 8.21+ which
must be built with the --enable-jit option. for optimum performance,
this option should always be used together with the 'o' option.
first introduced in ngx_lua v0.3.1rc30.
J enable the PCRE Javascript compatible mode. this option was
first introduced in the v0.7.14 release. this option requires
at least PCRE 8.12.
m multi-line mode (similar to Perl's /m modifier)
o compile-once mode (similar to Perl's /o modifier),
to enable the worker-process-level compiled-regex cache
s single-line mode (similar to Perl's /s modifier)
u UTF-8 mode. this requires PCRE to be built with
the --enable-utf8 option or else a Lua exception will be thrown.
U similar to "u" but disables PCRE's UTF-8 validity check on
the subject string. first introduced in ngx_lua v0.8.1.
x extended mode (similar to Perl's /x modifier)
Эти опции могут быть объединены:
local m, err = ngx.re.match("hello, world", "HEL LO", "ix")
-- m[0] == "hello" local m, err = ngx.re.match("hello, 美好生活", "HELLO, (.{2})", "iu")
-- m[0] == "hello, 美好"
-- m[1] == "美好" Опция o полезна для оптимизации производительности, потому что шаблон регулярного выражения будет скомпилирован только один раз, кэширован на уровне процесса обработки и будет использоваться всеми запросами в текущем процессе обработки Nginx. Верхний предел кэша регулярных выражений можно настроить с помощью директивы lua_regex_cache_max_entries.
Необязательный четвёртый аргумент, ctx, может быть таблицей Lua, содержащей необязательное поле pos. Когда поле pos в таблице ctx указано, ngx.re.match начнёт сопоставление с этого смещения (начиная с 1). Независимо от наличия поля pos в таблице ctx, ngx.re.match всегда установит это поле pos в позицию *после* подстроки, соответствующей всему шаблону, в случае успешного совпадения. Если совпадение не найдено, таблица ctx останется неизменной.
local ctx = {}
local m, err = ngx.re.match("1234, hello", "[0-9]+", "", ctx)
-- m[0] = "1234"
-- ctx.pos == 5 local ctx = { pos = 2 }
local m, err = ngx.re.match("1234, hello", "[0-9]+", "", ctx)
-- m[0] = "234"
-- ctx.pos == 5 Таблица ctx, используемая вместе с модификатором регулярного выражения a, может быть использована для создания лексического анализатора над ngx.re.match.
Обратите внимание, что аргумент options не является необязательным, когда указан аргумент ctx, и что пустая строка Lua ("") должна использоваться в качестве заполнителя для options, если не требуются значимые опции регулярного выражения.
Для этой функции требуется включённая в Nginx библиотека PCRE. (Известная проблема со специальными последовательностями экранирования).
Чтобы подтвердить, что PCRE JIT включен, активируйте журнал отладки Nginx, добавив параметр --with-debug в Nginx или скрипт OpenResty's ./configure. Затем включите уровень ошибок «debug» в директиве error_log. Следующее сообщение будет сгенерировано, если PCRE JIT включён:
pcre JIT compiling result: 1
Начиная с выпуска 0.9.4, эта функция также принимает пятый аргумент, res_table, для того, чтобы позволить вызывающей стороне предоставить таблицу Lua для хранения всех результатов захватов. Начиная с 0.9.6, ответственность за обеспечение пустоты этой таблицы ложится на вызывающую сторону. Это очень полезно для повторного использования таблиц Lua и экономии ресурсов GC и выделения памяти для таблиц.
Эта функция была представлена в выпуске v0.2.1rc11.
ngx.re.find
синтаксис: from, to, err = ngx.re.find(subject, regex, options?, ctx?, nth?)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично ngx.re.match, но возвращает только начальный индекс (from) и конечный индекс (to) совпавшей подстроки. Возвращаемые индексы имеют базу 1 и могут быть напрямую переданы в функцию string.sub для получения совпавшей подстроки.
В случае ошибок (например, неверных регулярных выражений или любых ошибок выполнения PCRE), эта функция API возвращает два nil значения, за которыми следует строка, описывающая ошибку.
Если совпадение не найдено, эта функция просто возвращает nil значение.
Ниже приведен пример:
local s = "hello, 1234"
local from, to, err = ngx.re.find(s, "([0-9]+)", "jo")
if from then
ngx.say("from: ", from)
ngx.say("to: ", to)
ngx.say("matched: ", string.sub(s, from, to))
else
if err then
ngx.say("error: ", err)
return
end
ngx.say("not matched!")
end Этот пример выводит
from: 8 to: 11 matched: 1234
Поскольку эта функция API не создаёт новые строки Lua или новые таблицы Lua, она значительно быстрее, чем ngx.re.match. Её следует использовать всякий раз, когда это возможно.
Начиная с версии 0.9.3, поддерживается необязательный 5-й аргумент, nth, для указания индексов (подпоследовательности) захвата, которые нужно вернуть. Когда nth равно 0 (что является значением по умолчанию), возвращаются индексы всей совпавшей подстроки; когда nth равно 1, возвращаются индексы первого совпадения подпоследовательности; когда nth равно 2, возвращается второе совпадение подпоследовательности и так далее. Если указанное совпадение подпоследовательности не найдено, будут возвращены два nil значения. Ниже приведен пример для этого:
local str = "hello, 1234"
local from, to = ngx.re.find(str, "([0-9])([0-9]+)", "jo", nil, 2)
if from then
ngx.say("matched 2nd submatch: ", string.sub(str, from, to)) -- yields "234"
end Эта функция API была впервые представлена в версии v0.9.2.
ngx.re.gmatch
синтаксис: итератор, ошибка = ngx.re.gmatch(предмет, регулярное_выражение, опции?)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично ngx.re.match, но возвращает итератор Lua, позволяющий пользователю перебирать все совпадения в строке-аргументе <subject> с помощью библиотеки PCRE regex.
В случае ошибок, таких как неправильно сформированное регулярное выражение, nil и строка, описывающая ошибку, будут возвращены.
Вот небольшой пример, демонстрирующий её основное использование:
local iterator, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
if not iterator then
ngx.log(ngx.ERR, "error: ", err)
return
end
local m
m, err = iterator() -- m[0] == m[1] == "hello"
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end
m, err = iterator() -- m[0] == m[1] == "world"
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end
m, err = iterator() -- m == nil
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end Чаще всего мы просто помещаем её в цикл Lua:
local it, err = ngx.re.gmatch("hello, world!", "([a-z]+)", "i")
if not it then
ngx.log(ngx.ERR, "error: ", err)
return
end
while true do
local m, err = it()
if err then
ngx.log(ngx.ERR, "error: ", err)
return
end
if not m then
-- no match found (any more)
break
end
-- found a match
ngx.say(m[0])
ngx.say(m[1])
end Необязательный аргумент options имеет точно такие же семантические значения, как метод ngx.re.match.
Текущая реализация требует, чтобы возвращаемый итератор использовался только в одном запросе. То есть, его не следует присваивать переменной, принадлежащей постоянно действующему пространству имён, например, пакетам Lua.
Для работы этого метода необходима библиотека PCRE, включенная в Nginx. (Известная проблема со специальными последовательностями экранирования).
Эта функция была впервые представлена в версии v0.2.1rc12.
ngx.re.sub
синтаксис: новая_строка, n, ошибка = ngx.re.sub(предмет, регулярное_выражение, замена, опции?)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Заменяет первое совпадение регулярного выражения, совместимого с Perl, regex в строке-аргументе subject, на строку или функцию-аргумент replace. Необязательный аргумент options имеет точно такое же значение, как в методе ngx.re.match.
Этот метод возвращает новую результирующую строку и количество успешных замен. В случае сбоя, например, при синтаксических ошибках в регулярных выражениях или в строке-аргументе <replace>, он вернёт nil и строку, описывающую ошибку.
Если replace — это строка, она обрабатывается как специальная шаблонная строка для замены строк. Например,
local newstr, n, err = ngx.re.sub("hello, 1234", "([0-9])[0-9]", "[$0][$1]")
if newstr then
-- newstr == "hello, [12][1]34"
-- n == 1
else
ngx.log(ngx.ERR, "error: ", err)
return
end где $0 относится к всей подстроке, совпадающей с шаблоном, а $1 относится к первой скобками захваченной подстроке.
Фигурные скобки также могут использоваться для разграничения имён переменных от строковых литералов:
local newstr, n, err = ngx.re.sub("hello, 1234", "[0-9]", "${0}00")
-- newstr == "hello, 100234"
-- n == 1 Литеральные знаки доллара ($) в строке-аргументе replace могут быть экранированы другим знаком доллара, например:
local newstr, n, err = ngx.re.sub("hello, 1234", "[0-9]", "$$")
-- newstr == "hello, $234"
-- n == 1 Не используйте обратные слэши для экранирования знаков доллара; это не сработает должным образом.
Если аргумент replace — это функция, она будет вызвана со "таблицей совпадений" в качестве аргумента для генерации строки замены для подстановки. "Таблица совпадений", переданная в функцию replace, совпадает с возвращаемым значением ngx.re.match. Вот пример:
local func = function (m)
return "[" .. m[0] .. "][" .. m[1] .. "]"
end
local newstr, n, err = ngx.re.sub("hello, 1234", "( [0-9] ) [0-9]", func, "x")
-- newstr == "hello, [12][1]34"
-- n == 1 Символы доллара в возвращаемом значении аргумента-функции replace не являются специальными.
Для работы этого метода необходима библиотека PCRE, включенная в Nginx. (Известная проблема со специальными последовательностями экранирования).
Эта функция была впервые представлена в версии v0.2.1rc13.
ngx.re.gsub
синтаксис: новая_строка, n, ошибка = ngx.re.gsub(предмет, регулярное_выражение, замена, опции?)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
То же, что и ngx.re.sub, но с глобальной заменой.
Вот несколько примеров:
local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", "[$0,$1]", "i")
if newstr then
-- newstr == "[hello,h], [world,w]"
-- n == 2
else
ngx.log(ngx.ERR, "error: ", err)
return
end local func = function (m)
return "[" .. m[0] .. "," .. m[1] .. "]"
end
local newstr, n, err = ngx.re.gsub("hello, world", "([a-z])[a-z]+", func, "i")
-- newstr == "[hello,h], [world,w]"
-- n == 2 Для работы этого метода необходима библиотека PCRE, включенная в Nginx. (Известная проблема со специальными последовательностями экранирования).
Эта функция была впервые представлена в версии v0.2.1rc15.
ngx.shared.DICT
синтаксис: словарь = ngx.shared.DICT
синтаксис: словарь = ngx.shared[имя_переменной]
контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Получение объекта Lua-словаря, основанного на shm, для зоны общей памяти с именем DICT, определённой директивой lua_shared_dict.
Зоны общей памяти всегда разделяются всеми процессами nginx worker в текущей инстанции nginx.
Полученный объект dict имеет следующие методы:
- get
- get_stale
- set
- safe_set
- add
- safe_add
- replace
- delete
- incr
- lpush
- rpush
- lpop
- rpop
- llen
- ttl
- expire
- flush_all
- flush_expired
- get_keys
- capacity
- free_space
Все эти методы являются атомарными операциями, то есть безопасными от одновременного доступа нескольких процессов nginx worker к той же зоне lua_shared_dict.
Вот пример:
http {
lua_shared_dict dogs 10m;
server {
location /set {
content_by_lua_block {
local dogs = ngx.shared.dogs
dogs:set("Jim", 8)
ngx.say("STORED")
}
}
location /get {
content_by_lua_block {
local dogs = ngx.shared.dogs
ngx.say(dogs:get("Jim"))
}
}
}
} Давайте протестируем:
$ curl localhost/set STORED $ curl localhost/get 8 $ curl localhost/get 8
Число 8 будет постоянно выводиться при обращении к /get независимо от того, сколько процессов Nginx worker существует, потому что словарь dogs находится в общей памяти и виден всем процессам worker.
Общий словарь сохранит своё содержимое при перезагрузке конфигурации сервера (либо путём отправки сигнала HUP процессу Nginx, либо с помощью опции командной строки -s reload).
Однако содержимое хранилища словаря будет потеряно, когда сервер Nginx завершит работу.
Эта функция была впервые представлена в версии v0.3.1rc22.
ngx.shared.DICT.get
синтаксис: значение, флаги = ngx.shared.DICT:get(ключ)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Извлечение значения из словаря ngx.shared.DICT для ключа key. Если ключ не существует или истек срок действия, то будет возвращено nil.
В случае ошибок, будут возвращены nil и строка, описывающая ошибку.
Возвращаемое значение будет иметь исходный тип данных, когда они были вставлены в словарь, например, булевы значения Lua, числа или строки.
Первый аргумент этого метода должен быть самим объектом словаря, например,
local cats = ngx.shared.cats local value, flags = cats.get(cats, "Marry")
или использовать синтаксический сахар Lua для вызовов методов:
local cats = ngx.shared.cats
local value, flags = cats:get("Marry") Эти два варианта в основе своей эквивалентны.
Если аргумент флагов пользователя — это 0 (по умолчанию), то значение флагов не будет возвращено.
Эта функция была впервые представлена в версии v0.3.1rc22.
См. также ngx.shared.DICT.
ngx.shared.DICT.get_stale
синтаксис: значение, флаги, просрочено = ngx.shared.DICT:get_stale(ключ)
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично методу get, но возвращает значение, даже если срок действия ключа истек.
Возвращает третье значение, stale, указывающее, истек ли срок действия ключа.
Обратите внимание, что значение просроченного ключа не гарантируется, поэтому не следует полагаться на доступность просроченных элементов.
Этот метод был впервые представлен в версии 0.8.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.set
синтаксис: успех, ошибка, принудительно = ngx.shared.DICT:set(ключ, значение, время_действия?, флаги?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Безусловно устанавливает пару «ключ-значение» в словарь shm-based ngx.shared.DICT. Возвращает три значения:
-
success: логическое значение, указывающее, сохранена ли пара «ключ-значение» или нет. -
err: текстовое сообщение об ошибке, может быть"no memory". -
forcible: логическое значение, указывающее, были ли принудительно удалены другие допустимые элементы, когда в зоне общей памяти закончилось место.
Аргумент value может быть логическими значениями Lua, числами, строками или nil. Тип значения также будет сохранён в словаре, и тот же тип данных можно будет извлечь позже с помощью метода get.
Необязательный аргумент exptime указывает время истечения срока действия (в секундах) для вставленной пары «ключ-значение». Разрешение времени составляет 0.001 секунды. Если аргумент exptime принимает значение 0 (по умолчанию), то элемент никогда не истечёт.
Необязательный аргумент flags указывает значение пользовательских флагов, связанных с записываемым элементом. Его также можно извлечь позже. Пользовательские флаги хранятся в виде целого числа без знака 32 бита. По умолчанию значение 0. Аргумент пользовательских флагов был впервые введён в релизе v0.5.0rc2.
При невозможности выделения памяти для текущего элемента «ключ-значение», set попытается удалить существующие элементы в хранилище в соответствии с алгоритмом наименее часто используемого (LRU). Обратите внимание, что LRU имеет приоритет перед временем истечения срока действия. Если удалено до нескольких десятков существующих элементов, и свободного места в хранилище всё ещё недостаточно (либо из-за ограничения общего объёма, указанного в lua_shared_dict, либо из-за сегментации памяти), то возвращаемое значение err будет no memory, а success будет false.
Если этот метод успешно сохраняет текущий элемент, принудительно удаляя другие ещё не истекшие элементы в словаре с помощью LRU, возвращаемое значение forcible будет true. Если он сохраняет элемент без принудительного удаления других допустимых элементов, то возвращаемое значение forcible будет false.
Первый аргумент этого метода должен быть самим объектом словаря, например,
local cats = ngx.shared.cats local succ, err, forcible = cats.set(cats, "Marry", "it is a nice cat!")
или используйте синтаксический сахар Lua для вызова методов:
local cats = ngx.shared.cats
local succ, err, forcible = cats:set("Marry", "it is a nice cat!") Эти два варианта в сущности эквивалентны.
Эта функция была впервые представлена в релизе v0.3.1rc22.
Обратите внимание, что, хотя внутренне пара «ключ-значение» устанавливается атомарно, атомарность не распространяется на границу вызова метода.
См. также ngx.shared.DICT.
ngx.shared.DICT.safe_set
синтаксис: ok, ошибка = ngx.shared.DICT:safe_set(ключ, значение, время_действия?, флаги?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично методу set, но никогда не перезаписывает (наименее используемые) неистекшие элементы в хранилище при отсутствии памяти в зоне общей памяти. В этом случае он сразу вернёт nil и строку "no memory".
Эта функция была впервые представлена в релизе v0.7.18.
См. также ngx.shared.DICT.
ngx.shared.DICT.add
синтаксис: успех, ошибка, принудительно = ngx.shared.DICT:add(ключ, значение, время_действия?, флаги?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Точно так же, как метод set, но сохраняет пару «ключ-значение» в словарь ngx.shared.DICT только в том случае, если ключ не существует.
Если аргумент key уже существует в словаре (и точно не истек), возвращаемое значение success будет false, а возвращаемое значение err будет "exists".
Эта функция была впервые представлена в релизе v0.3.1rc22.
См. также ngx.shared.DICT.
ngx.shared.DICT.safe_add
синтаксис: ok, ошибка = ngx.shared.DICT:safe_add(ключ, значение, время_действия?, флаги?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично методу add, но никогда не перезаписывает (наименее используемые) неистекшие элементы в хранилище при отсутствии памяти в зоне общей памяти. В этом случае он сразу вернёт nil и строку "no memory".
Эта функция была впервые представлена в релизе v0.7.18.
См. также ngx.shared.DICT.
ngx.shared.DICT.replace
синтаксис: успех, ошибка, принудительно = ngx.shared.DICT:replace(ключ, значение, время_действия?, флаги?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Точно так же, как метод set, но сохраняет пару «ключ-значение» в словарь ngx.shared.DICT только в том случае, если ключ существует.
Если аргумент key не существует в словаре (или уже истек), возвращаемое значение success будет false, а возвращаемое значение err будет "not found".
Эта функция была впервые представлена в релизе v0.3.1rc22.
См. также ngx.shared.DICT.
ngx.shared.DICT.delete
синтаксис: ngx.shared.DICT:delete(ключ)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Безусловно удаляет пару «ключ-значение» из словаря shm-based ngx.shared.DICT.
Эквивалентно ngx.shared.DICT:set(key, nil).
Эта функция была впервые представлена в релизе v0.3.1rc22.
См. также ngx.shared.DICT.
ngx.shared.DICT.incr
синтаксис: новое_значение, ошибка, принудительно? = ngx.shared.DICT:incr(ключ, значение, начальное_значение?, время_действия_начального_значения?)
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
необязательное требование: resty.core.shdict или resty.core
Увеличивает (числовое) значение для key в словаре shm-based ngx.shared.DICT на шаг value. Возвращает новое результирующее число, если операция выполнена успешно, или nil и сообщение об ошибке в противном случае.
Когда ключ не существует или уже истек в общем словаре,
- если аргумент
initне указан или принимает значениеnil, этот метод вернётnilи строку ошибки"not found", или - если аргумент
initпринимает числовое значение, этот метод создаст новыйkeyсо значениемinit + value.
Как и метод add, он также перезаписывает (наименее используемые) неистекшие элементы в хранилище при отсутствии памяти в зоне общей памяти.
Необязательный аргумент init_ttl указывает время истечения срока действия значения при инициализации через аргумент init (в секундах). Разрешение времени составляет 0.001 секунды. Если init_ttl принимает значение 0 (по умолчанию), то элемент никогда не истечёт. Этот аргумент не может быть предоставлен без предоставления аргумента init, и не имеет эффекта, если значение уже существует (например, если оно было ранее вставлено через set или аналогично).
Примечание: Использование аргумента init_ttl требует модулей resty.core.shdict или resty.core из библиотеки lua-resty-core. Пример:
require "resty.core"
local cats = ngx.shared.cats
local newval, err = cats:incr("black_cats", 1, 0, 0.1)
print(newval) -- 1
ngx.sleep(0.2)
local val, err = cats:get("black_cats")
print(val) -- nil Возвращаемое значение forcible всегда будет nil, когда аргумент init не указан.
Если этот метод успешно сохраняет текущий элемент, принудительно удаляя другие ещё не истекшие элементы в словаре с помощью LRU, возвращаемое значение forcible будет true. Если он сохраняет элемент без принудительного удаления других допустимых элементов, то возвращаемое значение forcible будет false.
Если исходное значение в словаре не является корректным числом Lua, возвращается nil и "not a number".
Аргумент value и аргумент init могут быть любыми корректными Lua числами, например, отрицательными числами или числами с плавающей запятой.
Этот метод был впервые представлен в релизе v0.3.1rc22.
Необязательный параметр init был впервые добавлен в релизе v0.10.6.
Необязательный параметр init_ttl был представлен в релизе v0.10.12rc2.
См. также ngx.shared.DICT.
ngx.shared.DICT.lpush
Синтаксис: length, err = ngx.shared.DICT:lpush(key, value)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Вставляет указанное (числовое или строковое) value в начало списка, имеющего имя key, в словаре shm ngx.shared.DICT. Возвращает количество элементов в списке после операции вставки.
Если key не существует, он создаётся как пустой список перед выполнением операции вставки. Если key уже имеет значение, которое не является списком, возвращается nil и "value not a list".
Никогда не перезаписывает (элементы с наименьшим временем последнего использования) непросроченные элементы в хранилище при отсутствии места в зоне общей памяти. В этом случае он немедленно вернёт nil и строку "no memory".
Эта функция была впервые представлена в релизе v0.10.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.rpush
Синтаксис: length, err = ngx.shared.DICT:rpush(key, value)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично методу lpush, но вставляет указанное (числовое или строковое) value в конец списка, имеющего имя key.
Эта функция была впервые представлена в релизе v0.10.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.lpop
Синтаксис: val, err = ngx.shared.DICT:lpop(key)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Удаляет и возвращает первый элемент списка, имеющего имя key, в словаре shm ngx.shared.DICT.
Если key не существует, возвращается nil. Если key уже имеет значение, которое не является списком, возвращается nil и "value not a list".
Эта функция была впервые представлена в релизе v0.10.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.rpop
Синтаксис: val, err = ngx.shared.DICT:rpop(key)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Удаляет и возвращает последний элемент списка, имеющего имя key, в словаре shm ngx.shared.DICT.
Если key не существует, возвращается nil. Если key уже имеет значение, которое не является списком, возвращается nil и "value not a list".
Эта функция была впервые представлена в релизе v0.10.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.llen
Синтаксис: len, err = ngx.shared.DICT:llen(key)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает количество элементов в списке, имеющем имя key, в словаре shm ngx.shared.DICT.
Если ключ не существует, он интерпретируется как пустой список, и возвращается 0. Если key уже имеет значение, которое не является списком, возвращается nil и "value not a list".
Эта функция была впервые представлена в релизе v0.10.6.
См. также ngx.shared.DICT.
ngx.shared.DICT.ttl
Синтаксис: ttl, err = ngx.shared.DICT:ttl(key)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Требуется: resty.core.shdict или resty.core
Получает оставшееся время жизни (TTL в секундах) пары ключ-значение в словаре shm ngx.shared.DICT. Возвращает TTL как число, если операция выполнена успешно, или nil и сообщение об ошибке в противном случае.
Если ключ не существует (или уже истек), этот метод вернёт nil и строку ошибки "not found".
TTL первоначально определяется аргументом exptime методов set, add, replace (и аналогичных). Он имеет временное разрешение в 0.001 секунды. Значение 0 означает, что элемент никогда не истечёт.
Пример:
require "resty.core"
local cats = ngx.shared.cats
local succ, err = cats:set("Marry", "a nice cat", 0.5)
ngx.sleep(0.2)
local ttl, err = cats:ttl("Marry")
ngx.say(ttl) -- 0.3 Эта функция была впервые представлена в релизе v0.10.11.
Примечание: Этот метод требует модулей resty.core.shdict или resty.core из библиотеки lua-resty-core.
См. также ngx.shared.DICT.
ngx.shared.DICT.expire
Синтаксис: success, err = ngx.shared.DICT:expire(key, exptime)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Требуется: resty.core.shdict или resty.core
Обновляет время жизни (в секундах) пары ключ-значение в словаре shm ngx.shared.DICT. Возвращает булево значение, указывающее на успех, если операция выполнена, или nil и сообщение об ошибке в противном случае.
Если ключ не существует, этот метод вернёт nil и строку ошибки "not found".
Аргумент exptime имеет разрешение в 0.001 секунды. Если exptime равно 0, то элемент никогда не истечёт.
Пример:
require "resty.core"
local cats = ngx.shared.cats
local succ, err = cats:set("Marry", "a nice cat", 0.1)
succ, err = cats:expire("Marry", 0.5)
ngx.sleep(0.2)
local val, err = cats:get("Marry")
ngx.say(val) -- "a nice cat" Эта функция была впервые представлена в релизе v0.10.11.
Примечание: Этот метод требует модулей resty.core.shdict или resty.core из библиотеки lua-resty-core.
См. также ngx.shared.DICT.
ngx.shared.DICT.flush_all
Синтаксис: ngx.shared.DICT:flush_all()
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Очищает все элементы в словаре. Этот метод фактически не освобождает все блоки памяти в словаре, а только отмечает все существующие элементы как просроченные.
Эта функция была впервые представлена в релизе v0.5.0rc17.
См. также ngx.shared.DICT.flush_expired и ngx.shared.DICT.
ngx.shared.DICT.flush_expired
Синтаксис: flushed = ngx.shared.DICT:flush_expired(max_count?)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Очищает просроченные элементы в словаре до максимального числа, указанного в необязательном аргументе max_count. Если аргумент max_count задан значением 0 или не задан вообще, это означает неограниченное число. Возвращает количество элементов, которые фактически были очищены.
В отличие от метода flush_all, этот метод действительно освобождает память, используемую просроченными элементами.
Эта функция была впервые представлена в релизе v0.6.3.
См. также ngx.shared.DICT.flush_all и ngx.shared.DICT.
ngx.shared.DICT.get_keys
Синтаксис: keys = ngx.shared.DICT:get_keys(max_count?)
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Извлекает список ключей из словаря до <max_count>.
По умолчанию возвращаются только первые 1024 ключа (если таковые имеются). Если аргумент <max_count> имеет значение 0, то будут возвращены все ключи, даже если их больше 1024.
ВНИМАНИЕ Избегайте вызова этого метода для словарей с очень большим количеством ключей, так как это может заблокировать словарь на значительное время и заблокировать процессы Nginx, пытающиеся получить доступ к словарю.
Эта функция была впервые представлена в релизе v0.7.3.
ngx.shared.DICT.capacity
Синтаксис: capacity_bytes = ngx.shared.DICT:capacity()
Контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Требуется: resty.core.shdict или resty.core
Возвращает ёмкость в байтах для словаря shm ngx.shared.DICT, объявленного с директивой lua_shared_dict.
Пример:
require "resty.core.shdict" local cats = ngx.shared.cats local capacity_bytes = cats:capacity()
Эта функция была впервые представлена в релизе v0.10.11.
Примечание: Для использования этого метода требуются модули resty.core.shdict или resty.core из библиотеки lua-resty-core.
Для работы этой функции требуется версия ядра nginx не ниже 0.7.3.
См. также ngx.shared.DICT.
ngx.shared.DICT.free_space
синтаксис: free_page_bytes = ngx.shared.DICT:free_space()
контекст: init_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
требуется: resty.core.shdict или resty.core
Возвращает размер свободной страницы в байтах для словаря ngx.shared.DICT, основанного на shm.
Примечание: Память для ngx.shared.DICT выделяется через механизм выделения памяти nginx, который имеет каждый слот для диапазонов размеров данных, таких как ~8, 9~16, 17~32, ..., 1025~2048, 2048~ байт. Страницы назначаются слоту, если в уже выделенных страницах нет места для этого слота.
Таким образом, даже если возвращаемое значение метода free_space равно нулю, в уже выделенных страницах может быть место, поэтому вы можете успешно установить новую пару ключ-значение в общий словарь, не получив true для forcible или непустое значение err из метода ngx.shared.DICT.set.
С другой стороны, если уже выделенные страницы для слота полны и к слоту добавлена новая пара ключ-значение, и свободной страницы нет, вы можете получить true для forcible или непустое значение err из метода ngx.shared.DICT.set.
Пример:
require "resty.core.shdict" local cats = ngx.shared.cats local free_page_bytes = cats:free_space()
Эта функция была впервые представлена в релизе v0.10.11.
Примечание: Для использования этого метода требуются модули resty.core.shdict или resty.core из библиотеки lua-resty-core.
Для работы этой функции требуется версия ядра nginx не ниже 1.11.7.
См. также ngx.shared.DICT.
ngx.socket.udp
синтаксис: udpsock = ngx.socket.udp()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Создает и возвращает объект сокета UDP или сокета Unix-домена ориентированного на датаграммы (также известный как один тип объектов "сокета"). Для этого объекта поддерживаются следующие методы:
Он предназначен для совместимости с API UDP библиотеки LuaSocket, но является 100% асинхронным изначально.
Эта функция была впервые представлена в релизе v0.5.7.
См. также ngx.socket.tcp.
udpsock:setpeername
синтаксис: ok, err = udpsock:setpeername(host, port)
синтаксис: ok, err = udpsock:setpeername("unix:/path/to/unix-domain.socket")
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Попытка подключить объект сокета UDP к удаленному серверу или к файлу сокета Unix-домена, ориентированному на датаграммы. Поскольку протокол датаграмм фактически является беспроводным, этот метод не устанавливает фактическое "соединение", а только устанавливает имя удаленного узла для последующих операций чтения/записи.
В качестве аргумента host могут быть указаны IP-адреса и доменные имена. В случае с доменными именами этот метод будет использовать динамический разрешитель ядра Nginx для анализа доменного имени без блокировки, и необходимо настроить директиву resolver в файле nginx.conf следующим образом:
resolver 8.8.8.8; # use Google's public DNS nameserver
Если сервер имен возвращает несколько IP-адресов для имени хоста, этот метод случайным образом выберет один.
В случае ошибки метод возвращает nil, за которым следует строка, описывающая ошибку. В случае успеха метод возвращает 1.
Вот пример подключения к серверу UDP (memcached):
location /test {
resolver 8.8.8.8;
content_by_lua_block {
local sock = ngx.socket.udp()
local ok, err = sock:setpeername("my.memcached.server.domain", 11211)
if not ok then
ngx.say("failed to connect to memcached: ", err)
return
end
ngx.say("successfully connected to memcached!")
sock:close()
}
} С релиза v0.7.18 также стало возможным подключение к файлу сокета Unix-домена, ориентированного на датаграммы, в Linux:
local sock = ngx.socket.udp()
local ok, err = sock:setpeername("unix:/tmp/some-datagram-service.sock")
if not ok then
ngx.say("failed to connect to the datagram unix domain socket: ", err)
return
end предполагая, что служба датаграмм прослушивает файл сокета Unix-домена /tmp/some-datagram-service.sock, а клиентский сокет будет использовать функцию "autobind" в Linux.
Вызов этого метода для уже подключенного объекта сокета приведет к закрытию исходного соединения.
Этот метод был впервые представлен в релизе v0.5.7.
udpsock:send
синтаксис: ok, err = udpsock:send(data)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Отправляет данные на текущий объект сокета UDP или сокета Unix-домена, ориентированного на датаграммы.
В случае успеха возвращает 1. В противном случае возвращает nil и строку, описывающую ошибку.
Входной аргумент data может быть строкой Lua или (вложенным) таблицей Lua, содержащей фрагменты строк. В случае аргументов таблицы этот метод будет копировать все фрагменты строк по частям в буферы отправки сокета Nginx, что обычно оптимальнее, чем выполнять операции конкатенации строк в Lua.
Эта функция была впервые представлена в релизе v0.5.7.
udpsock:receive
синтаксис: data, err = udpsock:receive(size?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Принимает данные из объекта сокета UDP или сокета Unix-домена, ориентированного на датаграммы, с необязательным аргументом размера буфера приема size.
Этот метод является синхронной операцией и полностью асинхронной.
В случае успеха возвращает полученные данные; в случае ошибки возвращает nil со строкой, описывающей ошибку.
Если указан аргумент size, этот метод использует этот размер в качестве размера буфера приема. Но когда этот размер больше 8192, используется значение 8192 вместо этого.
Если аргумент не указан, предполагается максимальный размер буфера 8192.
Таймаут для операции чтения управляется директивой конфигурации lua_socket_read_timeout и методом settimeout. Последний имеет приоритет. Например:
sock:settimeout(1000) -- one second timeout
local data, err = sock:receive()
if not data then
ngx.say("failed to read a packet: ", err)
return
end
ngx.say("successfully read a packet: ", data) Важно вызвать метод settimeout до вызова этого метода.
Эта функция была впервые представлена в релизе v0.5.7.
udpsock:close
синтаксис: ok, err = udpsock:close()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Закрывает текущий сокет UDP или сокета Unix-домена, ориентированного на датаграммы. Возвращает 1 в случае успеха и возвращает nil со строкой, описывающей ошибку в противном случае.
Объекты сокетов, которые не вызвали этот метод (и соответствующие соединения) будут закрыты, когда объект сокета будет освобожден сборщиком мусора Lua или текущий HTTP-запрос клиента завершит обработку.
Эта функция была впервые представлена в релизе v0.5.7.
udpsock:settimeout
синтаксис: udpsock:settimeout(time)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Устанавливает значение таймаута в миллисекундах для последующих операций сокета (например, receive).
Настройки, выполненные этим методом, имеют приоритет над настройками директив конфигурации, такими как lua_socket_read_timeout.
Эта функция была впервые представлена в релизе v0.5.7.
ngx.socket.stream
Просто псевдоним для ngx.socket.tcp. Если сокет типа stream также может подключаться к сокету Unix-домена, то предпочтительнее использовать это имя API.
Эта функция API была впервые добавлена в релизе v0.10.1.
ngx.socket.tcp
синтаксис: tcpsock = ngx.socket.tcp()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Создает и возвращает объект сокета TCP или сокета Unix-домена, ориентированного на потоки (также известный как один тип объектов "сокета"). Для этого объекта поддерживаются следующие методы:
- connect
- sslhandshake
- send
- receive
- close
- settimeout
- settimeouts
- setoption
- receiveuntil
- setkeepalive
- getreusedtimes
Он предназначен для совместимости с API TCP библиотеки LuaSocket, но является 100% асинхронным изначально. Кроме того, мы представили некоторые новые API для предоставления дополнительных функций.
Объект сокета, созданный этой функцией API, имеет точно такой же срок жизни, как и обработчик Lua, который его создает. Поэтому никогда не передавайте объект сокета другому обработчику Lua (включая функции обратного вызова ngx.timer) и никогда не используйте объект сокета в разных запросах NGINX.
Для каждого подключаемого соединения объекта сокета, если вы не закрываете его явно (через close) или не помещаете его обратно в пул подключений (через setkeepalive), он автоматически закрывается, когда происходит одно из следующих двух событий:
- текущий обработчик запроса завершается, или
- значение объекта Lua-сокета собирается сборщиком мусора Lua.
Критические ошибки в операциях с сокетами всегда автоматически закрывают текущее соединение (обратите внимание, что ошибка таймаута чтения — единственная ошибка, которая не является критической), и если вы вызываете close на закрытом соединении, вы получите ошибку «закрыто».
Начиная с версии 0.9.9, объект cosocket здесь является полнодуплексным, то есть «лёгкий поток» чтения и «лёгкий поток» записи могут работать с одним объектом cosocket одновременно (оба «лёгких потока» должны принадлежать одному обработчику Lua, см. причины выше). Однако вы не можете иметь два «лёгких потока», одновременно читающих (или записывающих или подключающихся) к одному cosocket, иначе вы можете получить ошибку типа «сокет занят чтением» при вызове методов объекта cosocket.
Эта функция была впервые представлена в версии v0.5.0rc1.
См. также ngx.socket.udp.
tcpsock:connect
Синтаксис: ok, err = tcpsock:connect(host, port, options_table?)
Синтаксис: ok, err = tcpsock:connect("unix:/path/to/unix-domain.socket", options_table?)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Попытка подключить объект сокета TCP к удалённому серверу или к файлу сокета Unix-доменной области без блокировки.
Перед фактическим разрешением имени хоста и подключением к удалённому бэкенду этот метод всегда ищет в пуле соединений подходящие свободные соединения, созданные предыдущими вызовами этого метода (или функцией ngx.socket.connect).
В качестве аргумента host можно указать как IP-адреса, так и имена доменов. В случае имён доменов этот метод будет использовать динамический разрешитель ядра Nginx для анализа имени домена без блокировки, и необходимо настроить директиву resolver в файле nginx.conf следующим образом:
resolver 8.8.8.8; # use Google's public DNS nameserver
Если сервер имён возвращает несколько IP-адресов для имени хоста, этот метод выберет один случайным образом.
В случае ошибки метод возвращает nil, за которым следует строка, описывающая ошибку. В случае успеха метод возвращает 1.
Вот пример подключения к TCP-серверу:
location /test {
resolver 8.8.8.8;
content_by_lua_block {
local sock = ngx.socket.tcp()
local ok, err = sock:connect("www.google.com", 80)
if not ok then
ngx.say("failed to connect to google: ", err)
return
end
ngx.say("successfully connected to google!")
sock:close()
}
} Также возможно подключение к файлу сокета Unix-доменной области:
local sock = ngx.socket.tcp()
local ok, err = sock:connect("unix:/tmp/memcached.sock")
if not ok then
ngx.say("failed to connect to the memcached unix domain socket: ", err)
return
end предполагая, что memcached (или что-то другое) прослушивает файл сокета Unix-доменной области /tmp/memcached.sock.
Таймаут для операции подключения управляется директивой конфигурации lua_socket_connect_timeout и методом settimeout. Приоритет имеет последний. Например:
local sock = ngx.socket.tcp() sock:settimeout(1000) -- one second timeout local ok, err = sock:connect(host, port)
Важно здесь вызвать метод settimeout перед вызовом этого метода.
Вызов этого метода на уже подключённом объекте сокета заставит первоначальное соединение сначала закрыть.
В качестве последнего аргумента этого метода можно указать необязательную Lua-таблицу для указания различных параметров подключения:
-
poolуказать пользовательское имя для используемого пула соединений. Если опущено, имя пула соединений будет сгенерировано из шаблона строки"<host>:<port>"или"<unix-socket-path>".
Поддержка аргумента options table была впервые добавлена в версии v0.5.7.
Этот метод был впервые представлен в версии v0.5.0rc1.
tcpsock:sslhandshake
Синтаксис: session, err = tcpsock:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Выполняет рукопожатие SSL/TLS для текущего установленного соединения.
Необязательный аргумент reused_session может принять предыдущее значение userdata сессии SSL, возвращённое предыдущим вызовом sslhandshake для точно такого же целевого объекта. Для кратковременных соединений повторное использование сессий SSL, как правило, ускоряет рукопожатие в разы, но не так полезно, если включён пул соединений. Этот аргумент по умолчанию равен nil. Если этот аргумент принимает значение булевого типа false, то значение userdata текущей SSL-сессии не возвращается этим вызовом, а возвращается только булевое значение Lua; в противном случае текущая SSL-сессия всегда возвращается в качестве первого аргумента в случае успеха.
Необязательный аргумент server_name используется для указания имени сервера для нового расширения TLS Server Name Indication (SNI). Использование SNI позволяет разным серверам совместно использовать один IP-адрес на стороне сервера. Кроме того, при включённой проверке SSL этот аргумент server_name также используется для проверки имени сервера, указанного в сертификате сервера, отправленном от удалённого сервера.
Необязательный аргумент ssl_verify принимает булево значение Lua для управления выполнением проверки SSL. При установке в значение true сертификат сервера будет проверен в соответствии с сертификатами CA, указанными директивой lua_ssl_trusted_certificate. Возможно, также потребуется настроить директиву lua_ssl_verify_depth для управления глубиной следования по цепочке сертификатов. Кроме того, если аргумент ssl_verify имеет значение true, а аргумент server_name также указан, последний будет использован для проверки имени сервера в сертификате сервера.
Необязательный аргумент send_status_req принимает булево значение, которое управляет отправкой запроса OCSP в запросе SSL-рукопожатия (который предназначен для запроса OCSP-стаплерования).
Для соединений, которые уже выполнили SSL/TLS-рукопожатие, этот метод возвращается немедленно.
Этот метод был впервые представлен в версии v0.9.11.
tcpsock:send
Синтаксис: bytes, err = tcpsock:send(data)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Отправляет данные без блокировки по текущему соединению TCP или Unix-доменного сокета.
Этот метод является синхронной операцией, которая не вернётся, пока все данные не будут отправлены в буфер отправки системного сокета или не произойдёт ошибка.
В случае успеха возвращается общее количество отправленных байтов. В противном случае возвращается nil и строка, описывающая ошибку.
Входной аргумент data может быть строкой Lua или (вложенной) Lua-таблицей, содержащей фрагменты строк. В случае аргументов типа таблица этот метод будет копировать все фрагменты строк по частям в подлежащие буферы отправки сокета Nginx, что обычно оптимальнее, чем выполнять операции конкатенации строк в Lua.
Таймаут для операции отправки управляется директивой конфигурации lua_socket_send_timeout и методом settimeout. Приоритет имеет последний. Например:
sock:settimeout(1000) -- one second timeout local bytes, err = sock:send(request)
Важно здесь вызвать метод settimeout перед вызовом этого метода.
В случае любых ошибок соединения этот метод всегда автоматически закрывает текущее соединение.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:receive
Синтаксис: data, err, partial = tcpsock:receive(size)
Синтаксис: data, err, partial = tcpsock:receive(pattern?)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Получает данные из подключённого сокета в соответствии с шаблоном чтения или размером.
Этот метод является синхронной операцией, как и метод send, и на 100% неблокирующий.
В случае успеха возвращаются полученные данные; в случае ошибки возвращается nil со строкой, описывающей ошибку, и частично полученные данные.
Если указан числовой аргумент (включая строки, похожие на числа), то он интерпретируется как размер. Этот метод не вернётся, пока не прочитает данные ровно этого размера или не произойдёт ошибка.
Если указана строка, не похожая на число, то она интерпретируется как «шаблон». Поддерживаются следующие шаблоны:
-
'*a': считывает из сокета до закрытия соединения. Никакой перевода концевых символов не выполняется; -
'*l': считывает строку текста из сокета. Строка завершается символомLine Feed(LF) (ASCII 10), необязательно предваряемым символомCarriage Return(CR) (ASCII 13). Символы CR и LF не включаются в возвращаемую строку. Фактически, все символы CR игнорируются шаблоном.
Если аргумент не указан, то предполагается шаблон '*l', то есть шаблон чтения строки.
Таймаут для операции чтения управляется директивой конфигурации lua_socket_read_timeout и методом settimeout. Приоритет имеет последний. Например:
sock:settimeout(1000) -- one second timeout
local line, err, partial = sock:receive()
if not line then
ngx.say("failed to read a line: ", err)
return
end
ngx.say("successfully read a line: ", line) Важно здесь вызвать метод settimeout перед вызовом этого метода.
Начиная с версии v0.8.8, этот метод больше не автоматически закрывает текущее соединение при возникновении ошибки таймаута чтения. При возникновении других ошибок соединения этот метод всегда автоматически закрывает соединение.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:receiveuntil
Синтаксис: iterator = tcpsock:receiveuntil(pattern, options?)
Контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Этот метод возвращает итераторную функцию Lua, которую можно вызывать для чтения потока данных до тех пор, пока не встретится указанный шаблон или не произойдёт ошибка.
Вот пример использования этого метода для чтения потока данных с последовательностью разделителей --abcedhb:
local reader = sock:receiveuntil("\r\n--abcedhb")
local data, err, partial = reader()
if not data then
ngx.say("failed to read the data stream: ", err)
end
ngx.say("read the data stream: ", data) Если функция вызывается без аргументов, то итераторная функция возвращает полученные данные непосредственно перед указанной строкой шаблона в входящем потоке данных. Итак, для примера выше, если входящий поток данных составляет 'hello, world! -agentzh\r\n--abcedhb blah blah', то будет возвращена строка 'hello, world! -agentzh'.
В случае ошибки итераторная функция вернёт nil вместе со строкой, описывающей ошибку, и частичными прочитанными байтами данных.
Итераторная функция может быть вызвана несколько раз и может быть безопасно смешана с другими вызовами методов cosocket или другими вызовами итераторных функций.
Функция-итератор ведет себя иначе (т.е., как настоящий итератор), когда вызывается с аргументом size. То есть, она будет читать этот size данных при каждом вызове и вернет nil на последнем вызове (либо увидит граничный шаблон, либо столкнется с ошибкой). Для последнего успешного вызова функции-итератора значение возврата err также будет nil. Функция-итератор будет сброшена после последнего успешного вызова, вернувшего данные nil и ошибку nil. Рассмотрим следующий пример:
local reader = sock:receiveuntil("\r\n--abcedhb")
while true do
local data, err, partial = reader(4)
if not data then
if err then
ngx.say("failed to read the data stream: ", err)
break
end
ngx.say("read done")
break
end
ngx.say("read chunk: [", data, "]")
end Тогда для входящего потока данных 'hello, world! -agentzh\r\n--abcedhb blah blah' мы получим следующий вывод из приведённого выше примера кода:
read chunk: [hell] read chunk: [o, w] read chunk: [orld] read chunk: [! -a] read chunk: [gent] read chunk: [zh] read done
Обратите внимание, что фактические возвращаемые данные могут быть немного длиннее, чем предел размера, указанный аргументом size, когда граничный шаблон имеет неоднозначность для потоковой обработки парсинга. Вблизи границы потока данных строка данных, фактически возвращённая, также может быть короче предела размера.
Таймаут для операции чтения функции-итератора управляется директивой конфигурации lua_socket_read_timeout и методом settimeout. При этом приоритет имеет последний. Например:
local readline = sock:receiveuntil("\r\n")
sock:settimeout(1000) -- one second timeout
line, err, partial = readline()
if not line then
ngx.say("failed to read a line: ", err)
return
end
ngx.say("successfully read a line: ", line) Важно вызвать метод settimeout до вызова функции-итератора (обратите внимание, что вызов receiveuntil здесь не имеет значения).
Начиная с версии v0.5.1, этот метод также принимает необязательный аргумент таблицы options для управления поведением. Поддерживаются следующие опции:
inclusive
Аргумент inclusive принимает булево значение, чтобы управлять включением строки шаблона в возвращаемую строку данных. По умолчанию установлено значение false. Например,
local reader = tcpsock:receiveuntil("_END_", { inclusive = true })
local data = reader()
ngx.say(data) Тогда для входного потока данных "hello world _END_ blah blah blah", пример выше выведет hello world _END_, включая саму строку шаблона _END_.
Начиная с версии v0.8.8, этот метод больше не автоматически закрывает текущее соединение при возникновении ошибки таймаута чтения. Для других ошибок соединения этот метод всегда автоматически закрывает соединение.
Этот метод был впервые представлен в версии v0.5.0rc1.
tcpsock:close
синтаксис: ok, err = tcpsock:close()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Закрывает текущий сокет TCP или сокет доменной Unix-системы. Возвращает 1 в случае успеха и возвращает nil со строкой, описывающей ошибку в противном случае.
Обратите внимание, что нет необходимости вызывать этот метод для объектов сокетов, которые вызвали метод setkeepalive, поскольку объект сокета уже закрыт (и текущее соединение сохраняется в встроенном пуле соединений).
Объекты сокетов, не вызывавшие этот метод (и связанные соединения), будут закрыты, когда объект сокета будет освобожден сборщиком мусора Lua (Garbage Collector) или завершится обработка текущего HTTP-запроса клиента.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:settimeout
синтаксис: tcpsock:settimeout(time)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Устанавливает значение таймаута в миллисекундах для последующих операций с сокетом (connect, receive и итераторы, возвращаемые из receiveuntil).
Настройки, выполненные этим методом, имеют приоритет над директивами конфигурации, т.е. lua_socket_connect_timeout, lua_socket_send_timeout и lua_socket_read_timeout.
Обратите внимание, что этот метод не влияет на настройку lua_socket_keepalive_timeout; для этой цели следует использовать аргумент timeout метода setkeepalive.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:settimeouts
синтаксис: tcpsock:settimeouts(connect_timeout, send_timeout, read_timeout)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Устанавливает соответственно время ожидания подключения, отправки и чтения в миллисекундах для последующих операций с сокетом (connect, send, receive и итераторы, возвращаемые из receiveuntil).
Настройки, выполненные этим методом, имеют приоритет над директивами конфигурации, т.е. lua_socket_connect_timeout, lua_socket_send_timeout и lua_socket_read_timeout.
Рекомендуется использовать settimeouts вместо settimeout.
Обратите внимание, что этот метод не влияет на настройку lua_socket_keepalive_timeout; для этой цели следует использовать аргумент timeout метода setkeepalive.
Эта функция была впервые представлена в версии v0.10.7.
tcpsock:setoption
синтаксис: tcpsock:setoption(option, value?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Эта функция добавлена для совместимости с API LuaSocket и пока ничего не делает. Её функциональность будет реализована в будущем.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:setkeepalive
синтаксис: ok, err = tcpsock:setkeepalive(timeout?, size?)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Немедленно помещает текущее соединение сокета в встроенный пул соединений cosocket и поддерживает его до тех пор, пока другие вызовы метода connect не запросят его или не истечёт максимальный тайм-аут бездействия.
Первый необязательный аргумент, timeout, может быть использован для указания максимального тайм-аута бездействия (в миллисекундах) для текущего соединения. Если опущен, используется значение по умолчанию из директивы конфигурации lua_socket_keepalive_timeout. Если значение 0 задано, то интервал таймаута не ограничен.
Второй необязательный аргумент, size, может быть использован для указания максимального числа соединений, разрешенных в пуле соединений для текущего сервера (т.е. для текущей пары хост-порт или пути файла сокета доменной Unix-системы). Обратите внимание, что размер пула соединений нельзя изменить после его создания. Если этот аргумент опущен, используется значение по умолчанию из директивы конфигурации lua_socket_pool_size.
Когда пул соединений превышает допустимый предел размера, соединение, наименее недавно использовавшееся (бездействующее), уже находящееся в пуле, будет закрыто, чтобы освободить место для текущего соединения.
Обратите внимание, что пул соединений cosocket относится к каждому рабочему процессу Nginx, а не к каждому экземпляру сервера Nginx, поэтому предел размера, указанный здесь, также относится к каждому отдельному рабочему процессу Nginx.
Бездействующие соединения в пуле будут отслеживаться на наличие каких-либо исключительных событий, таких как прерывание соединения или неожиданный приход данных на линии, в которых случае данное соединение будет закрыто и удалено из пула.
В случае успеха этот метод возвращает 1; в противном случае возвращает nil и строку, описывающую ошибку.
Если системный буфер приема для текущего соединения содержит непрочитанные данные, этот метод вернёт сообщение об ошибке «соединение в сомнительном состоянии» (как второе возвращаемое значение), так как предыдущая сессия оставила непрочитанные данные для следующей сессии, и соединение небезопасно для повторного использования.
Этот метод также заставляет текущий объект cosocket перейти в состояние «закрытый», поэтому нет необходимости вручную вызывать метод close на нём после этого.
Эта функция была впервые представлена в версии v0.5.0rc1.
tcpsock:getreusedtimes
синтаксис: count, err = tcpsock:getreusedtimes()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Этот метод возвращает количество (успешных) повторных использований текущего соединения. В случае ошибки возвращает nil и строку, описывающую ошибку.
Если текущее соединение не из встроенного пула соединений, то этот метод всегда возвращает 0, то есть соединение ещё не использовалось повторно. Если соединение из пула соединений, то возвращаемое значение всегда не равно нулю. Таким образом, этот метод также можно использовать для определения, поступает ли текущее соединение из пула.
Эта функция была впервые представлена в версии v0.5.0rc1.
ngx.socket.connect
синтаксис: tcpsock, err = ngx.socket.connect(host, port)
синтаксис: tcpsock, err = ngx.socket.connect("unix:/path/to/unix-domain.socket")
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Эта функция является сокращением для объединения вызовов ngx.socket.tcp() и метода connect() в одну операцию. Она реализована следующим образом:
local sock = ngx.socket.tcp() local ok, err = sock:connect(...) if not ok then return nil, err end return sock
Нет способа использовать метод settimeout для указания таймаута подключения для этого метода, и директива lua_socket_connect_timeout должна быть установлена во время конфигурации.
Эта функция была впервые представлена в версии v0.5.0rc1.
ngx.get_phase
синтаксис: str = ngx.get_phase()
контекст: init_by_lua*, init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает имя текущей фазы выполнения. Возможные возвращаемые значения:
-
initдля контекста init_by_lua*. -
init_workerдля контекста init_worker_by_lua*. -
ssl_certдля контекста ssl_certificate_by_lua*. -
ssl_session_fetchдля контекста ssl_session_fetch_by_lua*. -
ssl_session_storeдля контекста ssl_session_store_by_lua*. -
setдля контекста set_by_lua*. -
rewriteдля контекста rewrite_by_lua*. -
balancerдля контекста balancer_by_lua*. -
accessдля контекста access_by_lua*. -
contentдля контекста content_by_lua*. -
header_filterдля контекста header_filter_by_lua*. -
body_filterдля контекста body_filter_by_lua*. -
logдля контекста log_by_lua*. -
timerдля контекста функций обратного вызова пользователя для ngx.timer.*.
Этот API был впервые представлен в v0.5.10 версии.
ngx.thread.spawn
синтаксис: co = ngx.thread.spawn(func, arg1, arg2, ...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Создаёт новый пользовательский "лёгкий поток" с функцией Lua func и необязательными аргументами arg1, arg2 и т.д. Возвращает объект Lua-потока (или Lua-корутины), представляющий этот "лёгкий поток".
"Лёгкие потоки" — это особый вид Lua-корутин, планируемых модулем ngx_lua.
Перед тем, как ngx.thread.spawn вернётся, функция func будет вызвана с этими необязательными аргументами до тех пор, пока она не вернётся, не прервётся с ошибкой или не будет передана в ожидании I/O-операций через API Nginx для Lua (например, tcpsock:receive).
После того, как ngx.thread.spawn вернётся, созданный "лёгкий поток" будет продолжать работу асинхронно, обычно при различных событиях ввода-вывода.
Все блоки Lua-кода, выполняемые с помощью rewrite_by_lua, access_by_lua и content_by_lua, находятся в шаблонном "лёгком потоке", созданном автоматически модулем ngx_lua. Такие шаблонные "лёгкие потоки" также называются "входными потоками".
По умолчанию соответствующий обработчик Nginx (например, обработчик rewrite_by_lua) не завершается, пока
- как "входной поток", так и все пользовательские "лёгкие потоки" не завершатся;
- "лёгкий поток" (как "входной", так и пользовательский) не прервётся путём вызова ngx.exit, ngx.exec, ngx.redirect или ngx.req.set_uri(uri, true);
- "входной поток" не завершится с ошибкой Lua.
Однако, когда пользовательский "лёгкий поток" завершается с ошибкой Lua, он не прерывает другие работающие "лёгкие потоки", в отличие от "входного потока".
Из-за ограничений в модели субзапросов Nginx, в общем случае не разрешается прерывать запущенный субзапрос Nginx. Поэтому также запрещено прерывать работающий "лёгкий поток", который ожидает один или несколько субзапросов Nginx. Вы должны вызвать ngx.thread.wait, чтобы дождаться завершения "лёгкого потока" перед выходом из "мира". Заметное исключение здесь заключается в том, что вы можете прервать ожидающие субзапросы, вызвав ngx.exit только со статусом ngx.ERROR (-1), 408, 444 или 499.
"Лёгкие потоки" не планируются прерывисто. Другими словами, автоматического временного разделения не выполняется. "Лёгкий поток" будет продолжать монопольно использовать ЦП до тех пор, пока:
- оператор ввода-вывода (без блокировки) не может быть завершён за один запуск;
- он не вызовет coroutine.yield, чтобы активно отказаться от выполнения;
- он не прервётся из-за ошибки Lua или вызова ngx.exit, ngx.exec, ngx.redirect или ngx.req.set_uri(uri, true).
В двух первых случаях "лёгкий поток" обычно будет возобновлён позже планировщиком ngx_lua, если не произойдёт событие "остановка мира".
Пользовательские "лёгкие потоки" могут создавать "лёгкие потоки" сами. Обычные пользовательские корутины, созданные с помощью coroutine.create, также могут создавать "лёгкие потоки". Корутина (будь то обычная Lua-корутина или "лёгкий поток"), которая непосредственно создаёт "лёгкий поток", называется "родительской корутиной" для созданного "лёгкого потока".
Родительская корутина может вызвать ngx.thread.wait, чтобы дождаться завершения своего дочернего "лёгкого потока".
Вы можете вызвать coroutine.status() и coroutine.yield() для "лёгких потоков".
Статус "лёгкого потока" корутины может быть "зомби", если:
- текущий "лёгкий поток" уже завершился (успешно или с ошибкой);
- его родительская корутина всё ещё жива;
- его родительская корутина не ожидает его с помощью ngx.thread.wait.
Следующий пример демонстрирует использование coroutine.yield() в "лёгких потоках" для ручного временного разделения:
local yield = coroutine.yield
function f()
local self = coroutine.running()
ngx.say("f 1")
yield(self)
ngx.say("f 2")
yield(self)
ngx.say("f 3")
end
local self = coroutine.running()
ngx.say("0")
yield(self)
ngx.say("1")
ngx.thread.spawn(f)
ngx.say("2")
yield(self)
ngx.say("3")
yield(self)
ngx.say("4") Затем он выведет:
0 1 f 1 2 f 2 3 f 3 4
"Лёгкие потоки" в основном полезны для выполнения одновременных запросов к upstream в одном обработчике запросов Nginx, как обобщённая версия ngx.location.capture_multi, которая может работать со всем API Nginx для Lua. Следующий пример демонстрирует параллельные запросы к MySQL, Memcached и upstream-HTTP-сервисам в одном Lua-обработчике и вывод результатов в том порядке, в котором они фактически возвращаются (похоже на модель BigPipe Facebook):
-- query mysql, memcached, and a remote http service at the same time,
-- output the results in the order that they
-- actually return the results.
local mysql = require "resty.mysql"
local memcached = require "resty.memcached"
local function query_mysql()
local db = mysql:new()
db:connect{
host = "127.0.0.1",
port = 3306,
database = "test",
user = "monty",
password = "mypass"
}
local res, err, errno, sqlstate =
db:query("select * from cats order by id asc")
db:set_keepalive(0, 100)
ngx.say("mysql done: ", cjson.encode(res))
end
local function query_memcached()
local memc = memcached:new()
memc:connect("127.0.0.1", 11211)
local res, err = memc:get("some_key")
ngx.say("memcached done: ", res)
end
local function query_http()
local res = ngx.location.capture("/my-http-proxy")
ngx.say("http done: ", res.body)
end
ngx.thread.spawn(query_mysql) -- create thread 1
ngx.thread.spawn(query_memcached) -- create thread 2
ngx.thread.spawn(query_http) -- create thread 3 Этот API был впервые включён в v0.7.0 версии.
ngx.thread.wait
синтаксис: ok, res1, res2, ... = ngx.thread.wait(thread1, thread2, ...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*
Ожидает завершения одного или нескольких дочерних "лёгких потоков" и возвращает результаты первого завершившегося "лёгкого потока" (успешно или с ошибкой).
Аргументы thread1, thread2 и т.д. — объекты Lua-потоков, возвращённые предыдущими вызовами ngx.thread.spawn.
Значения возврата имеют точно такое же значение, как и coroutine.resume, то есть первое возвращаемое значение — булево значение, указывающее, завершился ли "лёгкий поток" успешно или нет, а последующие значения — значения возврата пользовательской Lua-функции, использованной для создания "лёгкого потока" (в случае успеха) или объект ошибки (в случае неудачи).
Только непосредственная "родительская корутина" может ожидать своего дочернего "лёгкого потока", в противном случае будет поднято исключение Lua.
Следующий пример демонстрирует использование ngx.thread.wait и ngx.location.capture для эмуляции ngx.location.capture_multi:
local capture = ngx.location.capture
local spawn = ngx.thread.spawn
local wait = ngx.thread.wait
local say = ngx.say
local function fetch(uri)
return capture(uri)
end
local threads = {
spawn(fetch, "/foo"),
spawn(fetch, "/bar"),
spawn(fetch, "/baz")
}
for i = 1, #threads do
local ok, res = wait(threads[i])
if not ok then
say(i, ": failed to run: ", res)
else
say(i, ": status: ", res.status)
say(i, ": body: ", res.body)
end
end Здесь по существу реализуется модель "ожидание всех".
Ниже приведён пример, демонстрирующий модель "ожидание любого":
function f()
ngx.sleep(0.2)
ngx.say("f: hello")
return "f done"
end
function g()
ngx.sleep(0.1)
ngx.say("g: hello")
return "g done"
end
local tf, err = ngx.thread.spawn(f)
if not tf then
ngx.say("failed to spawn thread f: ", err)
return
end
ngx.say("f thread created: ", coroutine.status(tf))
local tg, err = ngx.thread.spawn(g)
if not tg then
ngx.say("failed to spawn thread g: ", err)
return
end
ngx.say("g thread created: ", coroutine.status(tg))
ok, res = ngx.thread.wait(tf, tg)
if not ok then
ngx.say("failed to wait: ", res)
return
end
ngx.say("res: ", res)
-- stop the "world", aborting other running threads
ngx.exit(ngx.OK) И он выведет следующий результат:
f thread created: running g thread created: running g: hello res: g done
Этот API был впервые включён в v0.7.0 версии.
ngx.thread.kill
синтаксис: ok, err = ngx.thread.kill(thread)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, ngx.timer.*
Уничтожает работающий "лёгкий поток", созданный с помощью ngx.thread.spawn. Возвращает true при успехе или nil, а строку, описывающую ошибку, в противном случае.
Согласно текущей реализации, только родительская корутина (или "лёгкий поток") может убить поток. Также, запущенный "лёгкий поток" с ожидающими субзапросами NGINX (например, инициированными ngx.location.capture) не может быть убит из-за ограничения в ядре NGINX.
Этот API был впервые включён в v0.9.9 версии.
ngx.on_abort
синтаксис: ok, err = ngx.on_abort(callback)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*
Регистрирует пользовательскую Lua-функцию в качестве обратного вызова, который автоматически вызывается, когда клиент преждевременно закрывает соединение (потока).
Возвращает 1, если обратный вызов зарегистрирован успешно, или возвращает nil и строку, описывающую ошибку, в противном случае.
Все API Nginx для Lua могут быть использованы в функции обратного вызова, потому что функция выполняется в специальном "лёгком потоке", как и эти "лёгкие потоки", созданные с помощью ngx.thread.spawn.
Функция обратного вызова может самостоятельно определить, что делать с событием прерывания клиента. Например, она может просто проигнорировать событие, не выполняя никаких действий, и текущий обработчик Lua-запроса продолжит выполнение без прерываний. Функция обратного вызова также может принять решение о завершении всего путём вызова ngx.exit, например:
local function my_cleanup() -- custom cleanup work goes here, like cancelling a pending DB transaction -- now abort all the "light threads" running in the current request handler ngx.exit(499) end local ok, err = ngx.on_abort(my_cleanup) if not ok then ngx.log(ngx.ERR, "failed to register the on_abort callback: ", err) ngx.exit(500) end
Если lua_check_client_abort установлено в off (что является значением по умолчанию), то этот вызов всегда возвращает сообщение об ошибке "lua_check_client_abort is off".
Согласно текущей реализации, эта функция может быть вызвана только один раз в обработчике одного запроса; последующие вызовы вернут сообщение об ошибке "duplicate call".
Этот API был впервые представлен в v0.7.4 версии.
См. также lua_check_client_abort.
ngx.timer.at
синтаксис: hdl, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Создаёт таймер Nginx с пользовательской функцией обратного вызова и необязательными пользовательскими аргументами.
Первый аргумент, delay, задаёт задержку таймера в секундах. Можно указывать дробные секунды, например, 0.001, что означает 1 миллисекунду. 0 задержка также может быть указана, в этом случае таймер истечёт немедленно после того, как текущий обработчик передаст выполнение.
Второй аргумент, callback, может быть любой функцией Lua, которая будет вызвана позже в фоновом "лёгком потоке" после указанной задержки. Пользовательский обратный вызов будет автоматически вызван ядром Nginx с аргументами premature, user_arg1, user_arg2 и т. д., где аргумент premature принимает булево значение, указывающее, произошла ли преждевременная истечение таймера, а user_arg1, user_arg2 и т. д. — это дополнительные пользовательские аргументы, указанные при вызове ngx.timer.at в качестве оставшихся аргументов.
Преждевременное истечение таймера происходит, когда процесс Nginx-рабочего пытается завершиться, например, при перезагрузке конфигурации Nginx, вызванной сигналом HUP, или при завершении работы сервера Nginx. Когда рабочий процесс Nginx пытается завершиться, вы больше не можете вызывать ngx.timer.at для создания новых таймеров с ненулевыми задержками, и в этом случае ngx.timer.at вернёт значение "условное ложь" и строку, описывающую ошибку, то есть "процесс завершается".
Начиная с версии v0.9.3, разрешено создавать таймеры с нулевой задержкой, даже когда процесс рабочего Nginx начинает завершаться.
Когда таймер истекает, пользовательский код Lua в обратном вызове таймера выполняется в "лёгком потоке", полностью отделённом от исходного запроса, создавшего таймер. Поэтому объекты с таким же сроком жизни, как запрос, их создавший, например, сокеты, не могут быть разделены между исходным запросом и функцией обратного вызова таймера.
Вот простой пример:
location / {
...
log_by_lua_block {
local function push_data(premature, uri, args, status)
-- push the data uri, args, and status to the remote
-- via ngx.socket.tcp or ngx.socket.udp
-- (one may want to buffer the data in Lua a bit to
-- save I/O operations)
end
local ok, err = ngx.timer.at(0, push_data,
ngx.var.uri, ngx.var.args, ngx.header.status)
if not ok then
ngx.log(ngx.ERR, "failed to create timer: ", err)
return
end
}
} Также можно создать бесконечные повторяющиеся таймеры, например, таймер, срабатывающий каждые 5 секунды, вызывая ngx.timer.at рекурсивно в функции обратного вызова таймера. Вот такой пример:
local delay = 5
local handler
handler = function (premature)
-- do some routine job in Lua just like a cron job
if premature then
return
end
local ok, err = ngx.timer.at(delay, handler)
if not ok then
ngx.log(ngx.ERR, "failed to create the timer: ", err)
return
end
end
local ok, err = ngx.timer.at(delay, handler)
if not ok then
ngx.log(ngx.ERR, "failed to create the timer: ", err)
return
end Тем не менее, рекомендуется использовать функцию API ngx.timer.every для создания повторяющихся таймеров, поскольку она более надёжна.
Поскольку обратные вызовы таймеров выполняются в фоновом режиме, и их время выполнения не добавляется к времени ответа любого клиентского запроса, они могут легко накапливаться на сервере и исчерпать системные ресурсы из-за ошибок программирования на Lua или просто из-за большого количества клиентского трафика. Чтобы предотвратить такие серьёзные последствия, как сбой сервера Nginx, в нём есть встроенные ограничения как на количество "ожидающих таймеров", так и на количество "работающих таймеров" в процессе рабочего Nginx. "Ожидающие таймеры" — это таймеры, которые ещё не истекли, а "работающие таймеры" — это те, чьи пользовательские обратные вызовы в настоящее время выполняются.
Максимальное количество ожидающих таймеров, разрешённых в рабочем процессе Nginx, контролируется директивой lua_max_pending_timers. Максимальное количество работающих таймеров контролируется директивой lua_max_running_timers.
Согласно текущей реализации, каждый "работающий таймер" займёт одну (фиктивную) запись соединения из глобального списка записей соединений, настроенного стандартной директивой worker_connections в nginx.conf. Поэтому убедитесь, что директива worker_connections установлена достаточно большой, чтобы учесть как реальные соединения, так и фиктивные соединения, необходимые для обратных вызовов таймеров (как ограничено директивой lua_max_running_timers).
Многие API Lua для Nginx разрешены в контексте обратных вызовов таймеров, такие как сокеты для потоков/датаграмм (ngx.socket.tcp и ngx.socket.udp), словари общей памяти (ngx.shared.DICT), пользовательские корутины (coroutine.*), пользовательские "лёгкие потоки" (ngx.thread.*), ngx.exit, ngx.now/ngx.time, ngx.md5/ngx.sha1_bin — все разрешены. Но API подзапросов (например, ngx.location.capture), API ngx.req.*, API вывода вниз по потоку (например, ngx.say, ngx.print и ngx.flush) явным образом отключены в этом контексте.
Вы можете передавать большинство стандартных значений Lua (null, булевы значения, числа, строки, таблицы, замыкания, дескрипторы файлов и т. д.) в обратный вызов таймера, либо явно в качестве пользовательских аргументов, либо неявно в качестве верхних значений для замыкания обратного вызова. Однако существуют исключения: вы не можете передавать объекты потоков, возвращаемые coroutine.create и ngx.thread.spawn, или объекты сокетов, возвращаемые ngx.socket.tcp, ngx.socket.udp и ngx.req.socket, так как срок жизни этих объектов связан с контекстом запроса, который их создал, а обратный вызов таймера отделён от контекста создающего запроса (по дизайну) и выполняется в собственном (фиктивном) контексте запроса. Если вы попытаетесь разделить объекты потоков или сокетов через границу создающего запроса, то получите ошибку "no co ctx found" (для потоков) или "bad request" (для сокетов). Однако создавать все эти объекты внутри вашего обратного вызова таймера можно.
Этот API был впервые представлен в релизе v0.8.0.
ngx.timer.every
синтаксис: hdl, err = ngx.timer.every(delay, callback, user_arg1, user_arg2, ...)
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогично функции API ngx.timer.at, но
-
delayне может быть нулём, - таймер будет создаваться каждые
delayсекунды до тех пор, пока текущий процесс Nginx-рабочего не начнёт завершаться.
При успехе возвращает значение "условное истина" (но не true). В противном случае возвращает значение "условное ложь" и строку, описывающую ошибку.
Этот API также учитывает lua_max_pending_timers и lua_max_running_timers.
Этот API был впервые представлен в релизе v0.10.9.
ngx.timer.running_count
синтаксис: count = ngx.timer.running_count()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает количество таймеров, которые в данный момент выполняются.
Эта директива была впервые представлена в релизе v0.9.20.
ngx.timer.pending_count
синтаксис: count = ngx.timer.pending_count()
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возвращает количество ожидающих таймеров.
Эта директива была впервые представлена в релизе v0.9.20.
ngx.config.subsystem
синтаксис: subsystem = ngx.config.subsystem
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Это строковое поле указывает текущую подсистему Nginx, на которой основан текущий Lua-окружение. Для данного модуля это поле всегда принимает строковое значение "http". Для ngx_stream_lua_module, однако, это поле принимает значение "stream".
Это поле было впервые представлено в 0.10.1.
ngx.config.debug
синтаксис: debug = ngx.config.debug
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Это булево поле указывает, является ли текущий Nginx отладочной сборкой, т. е. собранной с опцией ./configure --with-debug.
Это поле было впервые представлено в 0.8.7.
ngx.config.prefix
синтаксис: prefix = ngx.config.prefix()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Возвращает путь "префикса" сервера Nginx, как определённый командной строкой -p при запуске исполняемого файла nginx, или путь, указанный командной строкой --prefix при сборке Nginx с помощью скрипта ./configure.
Эта функция была впервые представлена в 0.9.2.
ngx.config.nginx_version
синтаксис: ver = ngx.config.nginx_version
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Это поле принимает целочисленное значение, обозначающее номер версии текущего ядра Nginx, используемого. Например, номер версии 1.4.3 соответствует числу Lua 1004003.
Этот API был впервые представлен в релизе 0.9.3.
ngx.config.nginx_configure
синтаксис: str = ngx.config.nginx_configure()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*
Эта функция возвращает строку аргументов команды NGINX ./configure.
Этот API был впервые представлен в релизе 0.9.5.
ngx.config.ngx_lua_version
синтаксис: ver = ngx.config.ngx_lua_version
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*
Это поле принимает целочисленное значение, указывающее номер версии текущего ngx_lua модуля, используемого в данный момент. Например, номер версии 0.9.3 приводит к числу Lua 9003.
Этот API был впервые представлен в релизе 0.9.3.
ngx.worker.exiting
синтаксис: exiting = ngx.worker.exiting()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Эта функция возвращает булево значение, указывающее, уже ли начался процесс выхода текущего процесса Nginx worker. Выход процесса Nginx worker происходит при завершении работы сервера Nginx или при перезагрузке конфигурации (перезагрузка по HUP).
Этот API был впервые представлен в релизе 0.9.3.
ngx.worker.pid
синтаксис: pid = ngx.worker.pid()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Эта функция возвращает число Lua для идентификатора процесса (PID) текущего процесса Nginx worker. Этот API более эффективен, чем ngx.var.pid, и может использоваться в контекстах, где API ngx.var.VARIABLE не может быть использован (например, в init_worker_by_lua).
Этот API был впервые представлен в релизе 0.9.5.
ngx.worker.count
синтаксис: count = ngx.worker.count()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_by_lua*, init_worker_by_lua*
Возвращает общее количество процессов Nginx worker (т.е. значение, настроенное директивой worker_processes в nginx.conf).
Этот API был впервые представлен в релизе 0.9.20.
ngx.worker.id
синтаксис: count = ngx.worker.id()
контекст: set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, init_worker_by_lua*
Возвращает порядковый номер текущего процесса Nginx worker (начиная с 0).
Таким образом, если общее количество процессов равно N, то этот метод может вернуть число от 0 до N - 1 (включительно).
Эта функция возвращает осмысленные значения только для NGINX 1.9.1+. В более ранних версиях NGINX она всегда возвращает nil.
См. также ngx.worker.count.
Этот API был впервые представлен в релизе 0.9.20.
ngx.semaphore
синтаксис: local semaphore = require "ngx.semaphore"
Этот модуль Lua реализует API семафора классического стиля для эффективной синхронизации между различными "лёгкими потоками". Также поддерживается совместное использование семафора между разными "лёгкими потоками", созданными в разных (запросных) контекстах, при условии, что "лёгкие потоки" находятся в одном процессе NGINX worker, и включена директива lua_code_cache (что является стандартным значением).
Этот модуль Lua не поставляется с самим модулем ngx_lua, а поставляется с библиотекой lua-resty-core.
Для получения более подробной информации обратитесь к документации этого модуля Lua в lua-resty-core.
Для этой функции требуется как минимум ngx_lua v0.10.0.
ngx.balancer
синтаксис: local balancer = require "ngx.balancer"
Это модуль Lua, который предоставляет API Lua для определения полностью динамических балансировщиков нагрузки на чистом Lua.
Этот модуль Lua не поставляется с самим модулем ngx_lua, а поставляется с библиотекой lua-resty-core.
Для получения более подробной информации обратитесь к документации этого модуля Lua в lua-resty-core.
Для этой функции требуется как минимум ngx_lua v0.10.0.
ngx.ssl
синтаксис: local ssl = require "ngx.ssl"
Этот модуль Lua предоставляет функции API для управления процессом рукопожатия SSL в контекстах, таких как ssl_certificate_by_lua*.
Этот модуль Lua не поставляется с самим модулем ngx_lua, а поставляется с библиотекой lua-resty-core.
Для получения более подробной информации обратитесь к документации этого модуля Lua для получения более подробной информации.
Для этой функции требуется как минимум ngx_lua v0.10.0.
ngx.ocsp
синтаксис: local ocsp = require "ngx.ocsp"
Этот модуль Lua предоставляет API для выполнения запросов OCSP, проверки ответов OCSP и установки OCSP-стапля.
Обычно этот модуль используется вместе с модулем ngx.ssl в контексте ssl_certificate_by_lua*.
Этот модуль Lua не поставляется с самим модулем ngx_lua, а поставляется с библиотекой lua-resty-core.
Для получения более подробной информации обратитесь к документации этого модуля Lua.
Для этой функции требуется как минимум ngx_lua v0.10.0.
ndk.set_var.DIRECTIVE
синтаксис: res = ndk.set_var.DIRECTIVE_NAME
контекст: init_worker_by_lua*, set_by_lua*, rewrite_by_lua*, access_by_lua*, content_by_lua*, header_filter_by_lua*, body_filter_by_lua*, log_by_lua*, ngx.timer.*, balancer_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Этот механизм позволяет вызывать другие директивы C-модулей nginx, которые реализованы подмодулем ndk_set_var_value submodule's set_var Nginx Devel Kit (NDK).
Например, следующие директивы модуля set-misc-nginx-module могут быть вызваны таким образом:
- set_quote_sql_str
- set_quote_pgsql_str
- set_quote_json_str
- set_unescape_uri
- set_escape_uri
- set_encode_base32
- set_decode_base32
- set_encode_base64
- set_decode_base64
- set_encode_hex
- set_decode_hex
- set_sha1
- set_md5
Например,
local res = ndk.set_var.set_escape_uri('a/b');
-- now res == 'a%2fb' Аналогичным образом, следующие директивы, предоставляемые модулем encrypted-session-nginx-module, также могут быть вызваны из Lua:
Для использования этой функции необходим модуль ngx_devel_kit.
coroutine.create
синтаксис: co = coroutine.create(f)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Создаёт пользовательскую корутину Lua с функцией Lua и возвращает объект корутины.
Аналогично стандартному API Lua coroutine.create, но работает в контексте корутин Lua, созданных ngx_lua.
Этот API стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые представлен в релизе v0.6.0.
coroutine.resume
синтаксис: ok, ... = coroutine.resume(co, ...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Возобновляет выполнение объекта пользовательской корутины Lua, ранее приостановленной или только что созданной.
Аналогично стандартному API Lua coroutine.resume, но работает в контексте корутин Lua, созданных ngx_lua.
Этот API стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые представлен в релизе v0.6.0.
coroutine.yield
синтаксис: ... = coroutine.yield(...)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Приостанавливает выполнение текущей пользовательской корутины Lua.
Аналогично стандартному API Lua coroutine.yield, но работает в контексте корутин Lua, созданных ngx_lua.
Этот API стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые представлен в релизе v0.6.0.
coroutine.wrap
синтаксис: co = coroutine.wrap(f)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Аналогичен стандартному API Lua coroutine.wrap, но работает в контексте Lua-корутин, созданных ngx_lua.
Этот API впервые стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые представлен в релизе v0.6.0.
coroutine.running
синтаксис: co = coroutine.running()
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Идентичен стандартному API Lua coroutine.running.
Этот API впервые стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые включён в релизе v0.6.0.
coroutine.status
синтаксис: status = coroutine.status(co)
контекст: rewrite_by_lua*, access_by_lua*, content_by_lua*, init_by_lua*, ngx.timer.*, header_filter_by_lua*, body_filter_by_lua*, ssl_certificate_by_lua*, ssl_session_fetch_by_lua*, ssl_session_store_by_lua*
Идентичен стандартному API Lua coroutine.status.
Этот API впервые стал доступен в контексте init_by_lua* начиная с 0.9.2.
Этот API был впервые включён в релизе v0.6.0.
Устаревшие разделы
Этот раздел содержит устаревшие разделы документации, которые были переименованы или удалены, чтобы существующие ссылки в сети оставались действительными.
Специальные последовательности PCRE
Этот раздел был переименован в Специальные последовательности экранирования.
© 2009–2017 Xiaozhe Wang (chaoslawful)
© 2009–2018 Yichun "agentzh" Zhang (章亦春), OpenResty Inc.
Licensed under the BSD License.
https://github.com/openresty/lua-nginx-module/tree/v0.10.13/