NGINX has the
nginx_lua
module developed by Openresty.org that can be used to leverage Lua scripting. The module integrates Lua threads into the NGINX event model to enable asynchronous code execution. The module shares the loaded Lua libraries across all requests but segregates request contexts using Lua threads, thus resulting in a small memory footprint.
This module is not enabled by default and needs to be built with NGINX. The module requires the Lua 5.1 version with the LuaJIT 2.0/ 2.1 interpreter. Download the latest version of the module from https://github.com/openresty/lua-nginx-module/releases. You can also use the following command:
$ wget https://github.com/openresty/lua-nginx-module/archive/v0.9.15.tar.gz $ tar -xzvf v0.9.15.tar.gz
The module also requires ngx_develt_kit
. The latest version of the kit can be downloaded from https://github.com/simpl/ngx_devel_kit/releases. You can also use the following command:
$ wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz $ tar -xzvf v0.2.19.tar.gz
We need to build these modules with NGINX, but before we do that, we need to export Lua and the LuaJIT library as system variables. Lua and LuaJIT should be available in /usr/local/lib/lua/
and /usr/local/include/luajit-2.0
respectively:
$ export LUAJIT_LIB=/usr/local/lib $ export LUAJIT_INC=/usr/local/include/luajit-2.0
Next, configure NGINX to build the downloaded modules using the configure
command. In addition to configuring the modules using the --add-module
option, we also need to specify the luajit
binary path to the linker:
$ ./configure --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro,-rpath,/usr/local/bin/luajit' --prefix=/usr/share/nginx –conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-pcre-jit --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-pcre=/home/ubuntu/nginx/pcre-8.36 --add-module=/home/ubuntu/nginx/ngx_devel_kit-0.2.19 --add-module=/home/ubuntu/nginx/lua-nginx-module-0.9.15
After configuring the NGINX build, generate, and install the binary using make
commands, as shown here:
$ make $ sudo make install
Validate the NGINX installation using the -V
option:
$ nginx -V nginx version: nginx/1.7.9 built by gcc 4.8.2 (Ubuntu 4.8.2-19ubuntu1) configure arguments: -with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro,-rpath,/usr/local/bin/luajit' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-pcre-jit --with-http_realip_module --with-http_addition_module --with-http_sub_module --with-pcre=/home/ubuntu/nginx/pcre-8.36 --add-module=/home/ubuntu/nginx/ngx_devel_kit-0.2.19 --add-module=/home/ubuntu/nginx/lua-nginx-module-0.9.15
On some platforms, the nginx -v
command may give the following error due to the loading of shared libraries:
error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
In order to fix the error, append the /usr/local/lib/
path to the shared library path by executing the following command:
$ LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH
While working with Lua directives, it is important to understand that NGINX processes a request in different life cycle phases. Each of the NGINX modules is executed in one of these phases. The following is a list of important phases of the NGINX request life cycle:
HttpRewriteModule
is executed in this phase if the request requires a location rewriteHttpAccessModule
is executed in this phase to determine whether the request should be allowed, denied, or authenticatedtry_files
blockThe ngx_lua
module provides the following directives to enable execution of the Lua code in one of the phases of NGINX execution.
This directive specifies the lookup path for Lua scripts used in set_by_lua
, content_by_lua
, and other directives.
This directive specifies the Lua code (as a string) executed by NGINX's master process at the global Lua VM level. The code can register Lua's global variables and import Lua modules that can be used later in other Lua directives. Here's an example:
init_by_lua 'cjson = require "cjson"';
The init_by_lua_file
directive is similar to init_by_lua
. It executes the code specified in a file to set the global context. Both directives are available under the http
section of an NGINX configuration.
This directive specifies the Lua code (as a string), a return
variable, and certain optional arguments. It executes the code using the passed arguments and provides the value in the specified variable. Here's an example:
set_by_lua $sum 'return (10 + 20)'; echo $sum;
Arguments passed to the Lua code can be accessed using the ngx.arg[i]
directive. The directive can only return a single value from the code. If multiple values are required, we need to use the ngx.var.VariableName
directive to create multiple variables. Here's an example:
set_by_lua $sum 'return (ngx.arg[1] + ngx.arg[2])' 10 20; echo $sum;
The set_by_lua_file
directive is similar to set_by_lua
. It executes the code specified in a file using optional parameters and returns the value in the specified variable. Both directives are available under the if (in location)
, location
, and server
sections of an NGINX configuration.
This directive acts as a content provider and executes the Lua code (as a string) to generate an NGINX response. It is important to note that the directive must not be used with other content handles, such as Proxy, in the same location block.
The content_by_lua_file
directive is similar to content_by_lua
. It executes the code specified in a file to generate an NGINX response. Both directives are available under the location
and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { content_by_lua 'ngx.say("hello ! Content from lua")'; }
NGINX allows the manipulation of response headers using Lua. The code can add new header fields or manipulate/delete existing response headers. The header_filter_by_lua
directive executes the Lua code as a response header filter. The code can access response headers using ngx.header.HeaderFieldName
variable.
The header_filter_by_lua_file
directive is similar to header_filter_by_lua
. It executes the code specified in a file to manipulate response headers. Both directives are available under the http
, server
, location
, and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { content_by_lua 'ngx.say("hello ! Content from lua")'; header_filter_by_lua 'ngx.header.X-Source = "LuaScript"'; }
The directive executes during the output-body-filter
phase of NGINX and can be used to manipulate the output body. The complete response body is passed in the ngx.arg[1]
variable. The Lua code can alter the contents of the variable to return a new output body. The ngx.arg[2]
variable contains the eof
flag.
The body_filter_by_lua_file
directive is similar to body_filter_by_lua
. It executes the code specified in a file to filter the output body. Both directives are available under the http
, server
, location
, and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { content_by_lua 'ngx.say("hello ! Content from lua")'; header_filter_by_lua 'ngx.header.content_length = nil'; body_filter_by_lua 'ngx.arg[1]=string.upper("from body filer"..ngx.arg[1]) '; }
In the HTTP protocol, the Content-Length
header field signifies the length of the message body. On the client side, the protocol determines the size of the message transferred, known as the transfer length. The two lengths should be the same. If the two lengths are going to be different, then the length of the message body should not be specified. Thus, it is always recommended that you clear the Content-Length
header field when the Lua code modifies the body length.
The directive executes the Lua code during the access phase of NGINX after the execution of ngx_http_access_module
.
The access_by_lua_file
directive is similar to access_by_lua
. It executes code specified in a file to determine access. Both directives are available under the http
, server
, location
, and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { content_by_lua 'ngx.say("hello ! Content from lua")'; access_by_lua ' if ngx.var.remote_addr == "192.168.2.111" then ngx.exit(ngx.HTTP_FORBIDDEN) end'; }
The rewrite_by_lua
directive executes Lua code during the rewrite phase of NGINX after the execution of ngx_http_rewrite_module
.
The rewrite_by_lua_file
directive is similar to rewrite_by_lua
. It executes the code specified in a file during the rewrite phase. Both directives are available under the http
, server
, location
, and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { content_by_lua 'ngx.say("hello ! Content from lua")'; rewrite_by_lua ' if ngx.var.remote_addr == "192.168.2.111" then ngx.redirect("/forbidden.html") end'; }
The log_by_lua
directive executes the Lua code during the log
request phase of NGINX. The code does not replace NGINX access logs, but can do sundry things, such as tracking request times, logging messages, and so on. The messages logged using ngx.log()
will be sent to the NGINX error log. It is important to note that the request body is not accessible in this API.
The log_by_lua_file
directive is similar to log_by_lua
. It executes the code specified in a file during the log-request
phase. Both directives are available under the http
, server
, location
, and if (in location)
sections of an NGINX configuration. Here's an example:
location /content { echo "hello world!" log_by_lua 'ngx.log(ngx.NOTICE,"logging request response")'; }
18.119.138.202