Spec-Zone.ru › nginx / Lua Module

ngx_http_lua_модуль

Имя

ngx_http_lua_модуль — Встраивание возможностей Lua в серверы Nginx HTTP.

Этот модуль не входит в дистрибутив исходного кода Nginx. См. инструкции по установке.

Содержание

  • Имя
  • Статус
  • Версия
  • Синопсис
  • Описание
  • Типичные применения
  • Совместимость с Nginx
  • Установка
    • Компиляция как динамического модуля
    • Конфигурации макросов C
    • Установка на Ubuntu 11.10
  • Сообщество
    • Англоязычный список рассылки
    • Список рассылки на китайском языке
  • Репозиторий кода
  • Ошибки и исправления
  • Поддержка байт-кода Lua/LuaJIT
  • Поддержка системных переменных среды
  • Поддержка HTTP 1.0
  • Статическая компоновка чистых модулей Lua
  • Обмен данными внутри процесса Nginx Worker
  • Известные проблемы
    • Проблемы с операцией соединения TCP сокетов
    • Вызов/восстановление корутин Lua
    • Область видимости переменных Lua
    • Локации, сконфигурированные директивами дочерних запросов других модулей
    • Cosockets недоступны везде
    • Специальные последовательности экранирования
    • Смешивание с SSI не поддерживается
    • Режим SPDY не полностью поддерживается
    • Отсутствие данных в запросах с короткой цепочкой
  • TODO
  • Изменения
  • Набор тестов
  • Авторские права и лицензия
  • См. также
  • Директивы
  • API Nginx для Lua
  • Устаревшие разделы
    • Специальные последовательности PCRE

Статус

Готово к использованию в производстве.

Версия

Этот документ описывает 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:

  1. Установите LuaJIT 2.0 или 2.1 (рекомендуется) или Lua 5.1 (Lua 5.2 не поддерживается ещё). LuaJIT можно загрузить с сайта проекта LuaJIT, а Lua 5.1 — с сайта проекта Lua. Некоторые менеджеры пакетов дистрибутивов также распространяют LuaJIT и/или Lua.
  2. Загрузите последнюю версию модуля ngx_devel_kit (NDK) ЗДЕСЬ.
  3. Загрузите последнюю версию ngx_lua ЗДЕСЬ.
  4. Загрузите последнюю версию 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.

Отчеты об ошибках и исправления

Пожалуйста, отправляйте отчеты об ошибках, списки пожеланий или исправления, выполнив

  1. создание тикета в GitHub Issue Tracker,
  2. или публикацией в сообществе 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. Неправильно оптимизированный код может легко привести к трудноотлажимым гонкам при высокой нагрузке.

Если требуется совместное использование данных на уровне сервера, воспользуйтесь одним или несколькими из следующих подходов:

  1. Используйте API ngx.shared.DICT, предоставляемый этим модулем.
  2. Используйте только один процесс worker nginx и один сервер (однако это не рекомендуется, когда имеется многоядерный процессор или несколько процессоров на одном компьютере).
  3. Используйте механизмы хранения данных, такие как 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 в целом не рекомендуется, так как:

  1. неправильное использование Lua-глобалей оказывает негативное влияние на одновременные запросы, когда такие переменные должны быть локальными по области видимости,
  2. Lua-глобальные переменные требуют обращений к таблицам Lua в глобальной среде, что является вычислительно дорогостоящим, и
  3. некоторые ссылки на 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:

http://openresty.org/#Changes

Набор тестов

Для выполнения набора тестов необходимы следующие зависимости:

  • Версия 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 сторонних разработчиков:

    • lua-cjson
  • Приложения:

    • 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 Nginx Modules Directives

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 за исключением

  1. данная директива встраивает исходный код Lua непосредственно внутри пары фигурных скобок ({}) вместо строки NGINX (что требует специального экранирования символов), и
  2. данная директива не поддерживает дополнительные аргументы после скрипта 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 или более поздних версий:

https://github.com/openresty/openresty/blob/master/patches/openssl-1.0.2h-sess_set_get_cb_yield.patch

Если вы не используете ядро 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
  • print
  • 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

синтаксис: 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. Это зависит от

  1. является ли текущее тело запроса больше, чем client_body_buffer_size,
  2. и включён ли 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 если

  1. тело запроса не было прочитано,
  2. тело запроса было записано во временные файлы на диске,
  3. или размер тела запроса равен нулю.

Если тело запроса ещё не прочитано, сначала вызовите 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-трафика.

END_OF_DOCUMENT_MARKER ```

Также обратите внимание, что этот метод вызывает завершение обработки текущего запроса и что он обязательно должен быть вызван перед 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 (по умолчанию)
  • 303
  • 307
  • 308

По умолчанию это 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.

END_OF_DOCUMENT_MARKER

См. также 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 и сообщение об ошибке в противном случае.

Когда ключ не существует или уже истек в общем словаре,

  1. если аргумент init не указан или принимает значение nil, этот метод вернёт nil и строку ошибки "not found", или
  2. если аргумент 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-домена ориентированного на датаграммы (также известный как один тип объектов "сокета"). Для этого объекта поддерживаются следующие методы:

  • setpeername
  • send
  • receive
  • close
  • settimeout

Он предназначен для совместимости с 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) не завершается, пока

  1. как "входной поток", так и все пользовательские "лёгкие потоки" не завершатся;
  2. "лёгкий поток" (как "входной", так и пользовательский) не прервётся путём вызова ngx.exit, ngx.exec, ngx.redirect или ngx.req.set_uri(uri, true);
  3. "входной поток" не завершится с ошибкой Lua.

Однако, когда пользовательский "лёгкий поток" завершается с ошибкой Lua, он не прерывает другие работающие "лёгкие потоки", в отличие от "входного потока".

Из-за ограничений в модели субзапросов Nginx, в общем случае не разрешается прерывать запущенный субзапрос Nginx. Поэтому также запрещено прерывать работающий "лёгкий поток", который ожидает один или несколько субзапросов Nginx. Вы должны вызвать ngx.thread.wait, чтобы дождаться завершения "лёгкого потока" перед выходом из "мира". Заметное исключение здесь заключается в том, что вы можете прервать ожидающие субзапросы, вызвав ngx.exit только со статусом ngx.ERROR (-1), 408, 444 или 499.

"Лёгкие потоки" не планируются прерывисто. Другими словами, автоматического временного разделения не выполняется. "Лёгкий поток" будет продолжать монопольно использовать ЦП до тех пор, пока:

  1. оператор ввода-вывода (без блокировки) не может быть завершён за один запуск;
  2. он не вызовет coroutine.yield, чтобы активно отказаться от выполнения;
  3. он не прервётся из-за ошибки 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() для "лёгких потоков".

Статус "лёгкого потока" корутины может быть "зомби", если:

  1. текущий "лёгкий поток" уже завершился (успешно или с ошибкой);
  2. его родительская корутина всё ещё жива;
  3. его родительская корутина не ожидает его с помощью 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, но

  1. delay не может быть нулём,
  2. таймер будет создаваться каждые 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:

  • set_encrypt_session
  • set_decrypt_session

Для использования этой функции необходим модуль 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/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API