Nginx中使用安装lua支持

[TOC]

Nginx中使用lua

主要是通过在编译NGINX时添加lua模块和lua的jit需要LuaJIT-2.0.4.tar.gz,ngx_devel_kit,lua-nginx-module

然后在NGINX中配置lua代码解析路径,使NGINX直接将请求转给lua

如下:

./configure --add-module=/root/ngx_devel_kit-0.3.0  --add-module=/root/lua-nginx-module-0.10.8

相当于说是在NGINX中直接编写lua代码

编译NGINX并安装Lua,不带openresty

下载安装LuaJIT-2.0.4.tar.gz

cd /opt \
&& wget -c http://luajit.org/download/LuaJIT-2.0.4.tar.gz\
&& tar xzvf LuaJIT-2.0.4.tar.gz\
&& cd LuaJIT-2.0.4\
&& make install PREFIX=/usr/local/luajit
# luaJit安装完之后默认存储的路径是/usr/local/luajit/
# 所以下面可以直接设置环境变量即可

#注意设置环境变量!后面NGINX会用到

export LUAJIT_LIB=/usr/local/luajit/lib\
&& export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0

下载解压ngx_devel_kit

wget https://github.com/simpl/ngx_devel_kit/archive/v0.3.0.tar.gz\
&& tar -xzvf v0.3.0.tar.gz

下载解压lua-nginx-module

wget https://github.com/openresty/lua-nginx-module/archive/v0.10.8.tar.gz\
&& tar -xzvf v0.10.8.tar.gz

安装nginx-1.10.3.tar.gz

#注意ngx_devel_kit和lua-nginx-module以实际解压路径为准

# make -j2如果报错:objs/Makefile:591: recipe for target 'objs/src/core/ngx_murmurhash.o' failed
# 我在ubuntu18.04下有这个错误
# 在objs/Makefile中将 -Werror 删除,对于warnings忽略
# vim objs/Makefile 找到第三行的CFLAGS = -I/usr/local/luajit/include/luajit-2.0  -pipe  -O -W -Wall -Wpointer-arith -Wno-unused -Werror -g  -DNDK_SET_VAR
# 删掉-Werrori 即可 具体可以参考NGINX篇的NGINX常见错误收集


# 这里我只编译了luajit的扩展如果需要别的, 可以在nginx篇或docker中找到NGINX的编译语句复制进来

wget http://nginx.org/download/nginx-1.10.3.tar.gz\
&& tar -xzvf nginx-1.10.3.tar.gz\
&& cd nginx-1.10.3\
&& ./configure --add-module=/opt/ngx_devel_kit-0.3.0 --add-module=/opt/lua-nginx-module-0.10.8\
&& make -j2\
&& make install


#将nginx做成命令

ln -s /usr/local/nginx/sbin/nginx /usr/bin/nginx\
&& cd /usr/local/nginx/conf/

Nginx中配置lua

lua的指令方式配置

# 在server 中添加一个localtion

location /lua {
          # 关闭缓存,这样调试时每次修改lua代码不需要reload nginx;但是正式环境一定记得开启缓存
          lua_code_cache off;
            default_type 'text/plain';
            # 这里可以直接写lua代码,记得用引号括起来
            # 必须用ngx.say("XXX")输出内容,因为print("XXX")的内容会输出到log中
            content_by_lua 'ngx.say("hello, lua")';
        }

lua文件方式

#在server 中添加一个localtion

location /lua {

  # 关闭缓存,这样调试时每次修改lua代码不需要reload nginx;但是正式环境一定记得开启缓存
  lua_code_cache off;
    default_type 'text/html';
    # 相对于nginx安装目录 也可以使用绝对路径
    # 在这里的文件中使用print("XXX")是无法在页面中显示的
    # 必须用ngx.say("XXX")输出内容,因为print("XXX")的内容会输出到log中
    # print定向到了log中去,所以界面上面无法查看到;
    content_by_lua_file conf/lua/test.lua;
}

#test.lua文件内容

ngx.say("hello world,I'm lua");

启动nginx(已经做了软连接了,可以在任何目录启动)

# 如果报错nginx: error while loading shared libraries: libluajit-5.1.so.2: cannot open shared object file: No such file or directory
# 使用下面命令建立变量(具体原因可以看Linux篇的常见问题收集)
export LD_LIBRARY_PATH=/usr/local/luajit/lib:$LD_LIBRARY_PATH
# 或者使用下面命令 加载lua库(具体原因可以看Linux篇的常见问题收集)
echo "/usr/local/luajit/lib" >> /etc/ld.so.conf && ldconfig
# 记得需要在编译 luajit 的时候 make install PREFIX=/usr/local/luajit

直接使用 nginx命令进行启动

通过openresty安装全部环境, 安装openresty的两种方式

官方地址https://openresty.org

如果要在NGINX中使用lua来连接Redis就必须要用到openresty

如果只是mysql的话直接用luarocks安装luasql即可

但是NGINX一般肯定是要用Redis的

如果非要用第一种方式来做安装NGINX的lua_module的话, 单独安装openresty应该也可以

但是我没试过, 我想关键点应该是在于

lua_package_path "/usr/local/openresty/lualib?.lua;;"; #lua 模块
lua_package_cpath "/usr/local/openresty/lualib?.so;;"; #c模块

安装openresty之后把这两句话配好应该就没有问题了

当然了我自己是非常喜欢直接用openresty 的因为他把所有东西都安好了, 只要配置NGINX就行了.

自动安装模式安装 openresty,提供官方的预编译包

参考https://openresty.org/cn/linux-packages.html

自动安装这种,一般会安装到'/usr/local/openresty/'中

同时会将nginx luajit等等全部安装都这里,比如NGINX就在/usr/local/openresty/nginx

这时候我们cd 进去使用sbin/nginx -V 可以看到Nginx几乎所有的扩展,包括luajit等全部安装了

这时候只要我们配置好conf/nginx.conf即可使用lua了

  • /usr/local/openresty/luajit :luajit 环境,luajit 类似于 java 的 jit,即即时编译,lua 是一种解释语言,通过 luajit 可以 即时编译 lua 代码到机器代码,得到很好的性能;
  • /usr/local/openresty/lualib:要使用的 lua 库,里边提供了一些默认的 lua 库,如 redis,json 库等,也可以把一些自 己开发的或第三方的放在这;
  • /usr/local/openresty/nginx :安装的 nginx; 通过 /usr/local/openresty/nginx/sbin/nginx -V 查看 nginx 版本和安装的模块

Ubuntu

# 导入我们的 GPG 密钥:
# 可以能需要 apt-get install gnupg gnupg2 gnupg1
wget -qO - https://openresty.org/package/pubkey.gpg | sudo apt-key add -

# 安装 add-apt-repository 命令
# (之后你可以删除这个包以及对应的关联包)
sudo apt-get -y install software-properties-common

# 添加我们官方 official APT 仓库:
sudo add-apt-repository -y "deb http://openresty.org/package/ubuntu $(lsb_release -sc) main"

# 更新 APT 索引:
sudo apt-get update

# 然后就可以像下面这样安装软件包,比如 openresty:
sudo apt-get install openresty

# 这个包同时也推荐安装 openresty-opm 和 openresty-restydoc 包,所以后面两个包会缺省安装上。如果你不想自动关联安装,可以用下面方法关闭自动关联安装:
sudo apt-get install --no-install-recommends openresty

# 可以通过下面命令查看安装目录
whereis openresty

手动安装openresty,编译安装

参考https://openresty.org/cn/installation.html

如果在编译安装时make的时候报错openssl_***之类的错误,一般认为是openssl的接口有改动

这时候我们可以用openresty新版本,或者根据openresty使用openssl版本即可.

同样的,我们在手动编译的时候也是会将openresty很多自带的东西安装过去

而且还可以通过--prefix=XXX参数指定安装的目录, 通过--with-XX安装额外的模块,通过--add-module添加自定义的第三方模块

Ubuntu

# 默认, --prefix=/usr/local/openresty 程序会被安装到/usr/local/openresty目录。

apt-get install wget libpcre3-dev libssl-dev perl make build-essential curl\
&& wget https://openresty.org/download/openresty-1.13.6.2.tar.gz\
&& tar -xzvf openresty-1.13.6.2.tar.gz && cd openresty-1.13.6.2/\
&&./configure
# 可以指定各种选项,比如
./configure --prefix=/opt/openresty \
            --with-luajit \
            --without-http_redis2_module \
            --with-http_iconv_module \
            --with-http_postgres_module
# 试着使用 ./configure --help 查看更多的选项。
    --with*** 安装一些内置/集成的模块
    --with-http_realip_module 取用户真实 ip 模块
    -with-pcre Perl 兼容的达式模块
    --with-luajit 集成 luajit 模块
    --add-module 添加自定义的第三方模块,如此次的 ngx_che_purge
    .....

# 安装文件
make -j2 && make install

# 可以通过下面命令查看安装目录
whereis openresty

配置NGINX

#lua模块路径,多个之间”;”分隔,其中”;;”表示默认搜索路径
默认到/usr/local/openresty/nginx下找到nginx的配置文件
在 http 部分添加如下配置
lua_package_path "/usr/local/openresty/lualib?.lua;;"; #lua 模块
lua_package_cpath "/usr/local/openresty/lualib?.so;;"; #c模块

为了方便开发我们在 /usr/servers/nginx/conf 目录下创建一个 lua.conf
在 nginx.conf 中的 http 部分添加 include lua.conf 包含此文件片段
include lua.conf;

在 lua.conf 中 server 部分添加如下配置
server {
        listen 500;
        server_name _; 
        
        location /lua { 
            default_type 'text/html';
            content_by_lua 'ngx.say("hello Im lua code")'; 
        }   
}

# 检查配置
/usr/local/openresty/nginx/sbin/nginx -t

# 重新加载NGINX配置
/usr/local/openresty/nginx/sbin/nginx -s reload

# 测试完毕,将lua的代码改为通过文件加载
server {
        listen 500;
        server_name _; 
        
        location /lua { 
            default_type 'text/html';
            lua_code_cache off;
            content_by_lua_file conf/lua/test.lua;
        }   
}

nginx lua模块常用指令

其实有一个pdf文档叫<跟我学Nginx+lua开发>里面对模块的讲解更好,有各种案例,虽然对模块讲的比较少,但是基本上够用了.

lua_code_cache 是否开启代码缓存.

语法:lua_code_cache on | off
默认: on
适用上下文:http、server、location、location if
这个指令是指定是否开启lua的代码编译缓存,开发时可以设置为off,以便lua文件实时生效,如果是生产线上,为了性能,建议开启。
关闭代码缓存后,我们在NGINX中的lua文件汇总的代码有变动,不用重启NGINX.

content_by_lua 指定lua代码块,但是v0.9.17以后不要再用

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用init_by_lua_block指令。

支持正则

充当“内容处理程序”,并为每个请求执行< Lua -script-str>中指定的Lua代码字符串。

Lua代码可以进行API调用,并在独立的全局环境(即沙箱)中作为新生成的协程执行。

# 可以直接在这里写lua程序
content_by_lua 'ngx.say("hello, lua")';

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")
 }

content_by_lua_file 指定Lua代码的路径

支持正则

指定Lua代码的路径,可以是相对路径也可以是绝对路径.相对路径必须以conf/开始

与content_by_lua等价,除了指定的文件包含Lua代码,或者从v0.5.0rc32发行版开始,执行Lua/LuaJIT字节码。

可以在字符串中使用Nginx变量来提供灵活性。然而,这有一些风险,通常不建议这样做。

当一个相对路径如foo/bar时。给定lua,它们将被转换为绝对路径,相对于启动Nginx服务器时由-p path命令行选项确定的服务器前缀路径。

当打开Lua代码缓存时(默认情况下),用户代码在第一个请求时加载一次并缓存,每次修改Lua源文件时都必须重新加载Nginx配置。通过在Nginx. conf中关闭lua_code_cache以避免重新加载Nginx,可以在开发期间暂时禁用Lua代码缓存。

Nginx变量在文件路径中支持动态调度,例如:

 location ~ ^/app/([-_a-zA-Z0-9/]+) {
     set $path $1;
     content_by_lua_file /path/to/lua/app/root/$path.lua;
 }

我的案例

    content_by_lua_file conf/lua/test.lua;

lua_package_path 设置set_by_lua、content_by_lua等脚本指定的Lua模块搜索路径

语法:lua_package_path 
默认:LUA_PATH环境变量的内容或Lua的编译内默认值。
适用上下文:http
设置set_by_lua、content_by_lua等脚本指定的Lua模块搜索路径。路径字符串为标准Lua路径形式,且;;可用于表示原始搜索路径。。
例如:lua_package_path "/opt/nginx/conf/www/?.lua;;";
具体的路径设置要参考lua的模块机制

init_by_lua 初始化一些lua的全局变量的代码块,以便后续的代码使用

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

从这段配置代码,我们可以看出,其实这个指令就是初始化一些lua的全局变量的代码块,以便后续的代码使用。

语法:init_by_lua 
适用上下文:http


init_by_lua 'cjson = require "cjson"';

server {
    location = /api {
        content_by_lua '
            ngx.say(cjson.encode({dog = 5, cat = 6}))
        ';
    }
}

init_by_lua_block 初始化一些lua的全局变量的代码块,以便后续的代码使用。

从这段配置代码,我们可以看出,其实这个指令就是初始化一些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})
         }
     }
 }

init_by_lua_file 初始化一些lua的全局变量的代码文件,以便后续的代码使用。

init_worker_by_lua 在启用主进程时,在每个Nginx工作进程启动时运行指定的Lua代码

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

这个指令最初是在v0.9.5版本中引入的。

自v0.10.12发布以来,这个钩子不再在缓存管理器和缓存加载器进程中运行。

类似于上面的init_by_lua_*,不过是作用在work进程的,先于work进程启动而调用。

在启用主进程时,在每个Nginx工作进程启动时运行指定的Lua代码。当主进程被禁用时,这个钩子将在init_by_lua*之后运行。

这个钩子通常用于为每个worker创建重复发生的计时器(通过ngx.timer)。用于后端健康检查或其他定时例行工作。下面是一个例子,

 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
 ';

init_worker_by_lua_block在启用主进程时,在每个Nginx工作进程启动时运行指定的Lua代码

与init_worker_by_lua指令类似,只是该指令将Lua源直接内联到一对花括号({})中,而不是在NGINX字符串文本中(这需要特殊的字符转义)。

 init_worker_by_lua_block {
     print("I need no extra escaping here, for example: \r\nblah")
 }

init_worker_by_lua_file在启用主进程时,在每个Nginx工作进程启动时运行指定的Lua代码

类似于init_worker_by_lua,但是接受Lua源文件或Lua字节码文件的文件路径。

这个指令最初是在v0.9.5版本中引入的。

自v0.10.12发布以来,这个钩子不再在缓存管理器和缓存加载器进程中运行。


set_by_lua 让nginx的变量与lua的变量相互作用赋值。

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用set_by_lua_block指令。

语法:set_by_lua $res  [$arg1 $arg2 ...]
适用上下文:server、location、location if

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";
}

set_by_lua_block 让nginx的变量与lua的变量相互作用赋值.

  1. 这个指令将Lua源直接内联到一对花括号({})中,而不是在NGINX字符串文本中(这需要特殊的字符转义),并且

  2. 这个指令不支持像set_by_lua中的那样在Lua脚本之后附加参数。

set_by_lua_block $res { return 32 + math.cos(32) }
 # $res now has the value "32.834223360507" or alike.

set_by_lua_file 让nginx的变量与lua的变量相互作用赋值

rewrite_by_lua 实现重定向

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

充当重写阶段处理程序,并为每个请求执行< Lua -script-str>中指定的Lua代码字符串。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也在子请求中运行。

rewrite_by_lua_block 实现重定向

与rewrite_by_lua指令类似,只是这个指令将Lua源代码内联到一对花括号({})中,而不是在NGINX字符串文本中(这需要特殊的字符转义)。

 rewrite_by_lua_block {
     do_something("hello, world!\nhiya\n")
 }

rewrite_by_lua_file 实现重定向

access_by_lua

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

access_by_lua_block

access_by_lua_file

header_filter_by_lua 用lua的代码去指定http响应的 header一些内容。

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

在< Lua -script-str>中指定的se Lua代码,用于定义输出头过滤器。

请注意,以下API函数目前在此上下文中被禁用:

输出API函数(例如,ngx)。说罢,ngx.send_headers) 控制API函数(例如,ngx)。重定向和ngx.exec) 子请求API函数(例如,ngx.location)。捕获和ngx.location.capture_multi) Cosocket API函数(例如,ngx.socket)。tcp和ngx.req.socket)。 下面是一个在我们的Lua头过滤器中覆盖响应头(或者如果没有添加响应头)的例子:

 location / {
     proxy_pass http://mybackend;
     header_filter_by_lua 'ngx.header.Foo = "blah"';
 }

header_filter_by_lua_block 用lua的代码去指定http响应的 header一些内容。

header_filter_by_lua_file 用lua的代码去指定http响应的 header一些内容。

body_filter_by_lua 这个指令可以用来修改http的响应正文的。

注意,在v0.9.17发行版之后,不鼓励使用这个指令。而是使用rewrite_by_lua_block指令。

使用< Lua -script-str>中指定的Lua代码定义输出体过滤器。

输入数据块通过ngx传递。arg1和指示响应体数据流结束的“eof”标志通过ngx传递。arg2。

在后台,“eof”标志只是Nginx链接缓冲区的last_buf(用于主请求)或last_in_chain(用于子请求)标志。(在v0.7.14发布之前,“eof”标志在子请求中根本不起作用。)

输出数据流可以通过运行以下Lua语句立即中止:

 return ngx.ERROR

这将截断响应主体,通常会导致不完整且无效的响应。

Lua代码可以通过覆盖ngx将自己修改过的输入数据块传递给下游的Nginx输出体过滤器。带有Lua字符串或Lua字符串表的arg[1]。例如,要转换响应体中的所有小写字母,我们可以这样写:

location / {
     proxy_pass http://mybackend;
     body_filter_by_lua 'ngx.arg[1] = string.upper(ngx.arg[1])';
 }

将nil或空Lua字符串值设置为ngx时。arg[1],没有数据块将被传递到下游的Nginx输出过滤器。

同样,可以通过将boolean值设置为ngx.arg[2]来指定新的“eof”标志。例如,

 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
     ';
 }

body_filter_by_lua_block 这个指令可以用来修改http的响应正文的

与body_filter_by_lua指令类似,只是这个指令将Lua源直接内联到一对花括号({})中,而不是在NGINX字符串文本中(这需要特殊的字符转义)。

 body_filter_by_lua_block {
     local data, eof = ngx.arg[1], ngx.arg[2]
 }

body_filter_by_lua_file 这个指令可以用来修改http的响应正文的

与body_filter_by_lua等价,除了指定的文件包含Lua代码,或者从v0.5.0rc32发行版开始,执行Lua/LuaJIT字节码。

当一个相对路径如foo/bar时。给定lua,它们将被转换为绝对路径,相对于启动Nginx服务器时由-p path命令行选项确定的服务器前缀路径。

这个指令最初是在v0.5.0rc32版本中引入的。

Nginx中的Lua API

更多 Nginx Lua API 请参考 http://wiki.nginx.org/HttpLuaModule#Nginx_API_for_Lua。

配置文件

example.conf 配置文件

location ~ /lua_request/(\d+)/(\d+) {
    #设置nginx变量
    set $a $1;
    set $b $host;
    default_type "text/html";
    #nginx内容处理
    content_by_lua_file /usr/example/lua/test_request.lua; #内容体处理完成后调用
    echo_after_body "ngx.var.b $b";
}

获取请求方式和请求参数以及变量赋值

代码

--nginx变量
local var = ngx.var
ngx.say("ngx.var.a : ", var.a, "
") ngx.say("ngx.var.b : ", var.b, "
") ngx.say("ngx.var[2] : ", var[2], "
") ngx.var.b = 2; ngx.say("
") --请求头 local headers = ngx.req.get_headers() ngx.say("headers begin", "
") ngx.say("Host : ", headers["Host"], "
") ngx.say("user-agent : ", headers["user-agent"], "
") ngx.say("user-agent : ", headers.user_agent, "
") for k, v in pairs(headers) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ","), "
") else ngx.say(k, " : ", v, "
") end end ngx.say("headers end", "
") ngx.say("
") --get请求uri参数 ngx.say("uri args begin", "
") local uri_args = ngx.req.get_uri_args() for k, v in pairs(uri_args) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ", "), "
") else ngx.say(k, ": ", v, "
") end end ngx.say("uri args end", "
") ngx.say("
") --post请求参数 ngx.req.read_body() ngx.say("post args begin", "
") local post_args = ngx.req.get_post_args() for k, v in pairs(post_args) do if type(v) == "table" then ngx.say(k, " : ", table.concat(v, ", "), "
") else ngx.say(k, ": ", v, "
") end end ngx.say("post args end", "
") ngx.say("
") --请求的http协议版本 ngx.say("ngx.req.http_version : ", ngx.req.http_version(), "
") --请求方法 ngx.say("ngx.req.get_method : ", ngx.req.get_method(), "
") --原始的请求头内容 ngx.say("ngx.req.raw_header : ", ngx.req.raw_header(), "
") --请求的body内容体 ngx.say("ngx.req.get_body_data() : ", ngx.req.get_body_data(), "
") ngx.say("
")

常用系统变量

ngx.var : nginx 变量,如果要赋值如 ngx.var.b = 2,此变量必须提前声明;另外对于 nginx location 中使用 正则捕获的捕获组可以使用 ngx.var [捕获组数字]获取;

ngx.req.get_headers:获取请求头,默认只获取前100,如果想要获取所以可以调用ngx.req.get_header s(0);获取带中划线的请求头时请使用如 headers.user_agent 这种方式;如果一个请求头有多个值,则返回的 是 table;

ngx.req.get_uri_args:获取 url 请求参数,其用法和 get_headers 类似;

ngx.req.get_post_args:获取 post 请求内容体,其用法和 get_headers 类似,但是必须提前调用 ngx.req.r ead_body() 来读取 body 体(也可以选择在 nginx 配置文件使用lua_need_request_body on;开启读取 bod y 体,但是官方不推荐);

ngx.req.raw_header:未解析的请求头字符串;

ngx.req.get_body_data:为解析的请求 body 体内容字符串。

如上方法处理一般的请求基本够用了。另外在读取 post 内容体时根据实际情况设置 client_body_buffer_size 和 client_max_body_size 来保证内容在内存而不是在文件中。

使用如下脚本测试

wget --post-data 'a=1&b=2' 'http://127.0.0.1/lua_request/1/2?a=3&b=4' -O -

输出响应

NGINX配置

location /lua_response_1 {
    default_type "text/html";
    content_by_lua_file /usr/example/lua/test_response_1.lua;
}

代码

--写响应头
ngx.header.a = "1"
--多个响应头可以使用table
ngx.header.b = { "2", "3" }
--输出响应
ngx.say("a", "b", "
") ngx.print("c", "d", "
") --200状态码退出 return ngx.exit(200) ngx.header:输出响应头; ngx.print:输出响应内容体; ngx.say:通ngx.print,但是会最后输出一个换行符; ngx.exit:指定状态码退出。

重定向

NGINX配置

location /lua_response_2 {
    default_type "text/html";
    content_by_lua_file /usr/example/lua/test_response_2.lua;
}

代码

ngx.redirect("http://jd.com", 302)

ngx.redirect:重定向;

ngx.status= 状态码,设置响应的状态码;

ngx.resp.get_headers() 获取设置的响应状态码;

ngx.send_head ers() 发送响应状态码,当调用 ngx.say/ngx.print 时自动发送响应状态码;

可以通过 ngx.headers_sent=true 判断是否发送了响应状态码。

其他 API

NGINX配置

location /lua_other {
    default_type "text/html";
    content_by_lua_file /usr/example/lua/test_other.lua;
}

代码

--未经解码的请求uri
local request_uri = ngx.var.request_uri;
ngx.say("request_uri : ", request_uri, "
"); --解码 ngx.say("decode request_uri : ", ngx.unescape_uri(request_uri), "
"); --MD5 ngx.say("ngx.md5 : ", ngx.md5("123"), "
") --http time ngx.say("ngx.http_time : ", ngx.http_time(ngx.time()), "
")
  • ngx.escape_uri/ngx.unescape_uri : uri 编码解码; • ngx.encode_args/ngx.decode_args:参数编码解码;
  • ngx.encode_base64/ngx.decode_base64:BASE64 编码解码;
  • ngx.re.match:nginx 正则表达式匹配;

Nginx 全局内存

更多 API 请参考 http://wiki.nginx.org/HttpLuaModule#ngx.shared.DICT。

Nginx 是一个 Master 进程多个 Worker 进程的工作方式,因此我们可能需要在多个 Worker 进程中共享数据,那么此时就可以使用 ngx.shared.DICT 来实现全局内存共享。

首先在 nginx.conf 的 http 部分分配内存大小

#共享全局变量,在所有worker间共享 lua_shared_dict shared_data 1m;

location /lua_shared_dict {
    default_type "text/html";
    content_by_lua_file /usr/example/lua/test_lua_shared_dict.lua;
}

代码

--1、获取全局共享内存变量
local shared_data = ngx.shared.shared_data

--2、获取字典值
local i = shared_data:get("i")
if not i then
    i = 1
    --3、惰性赋值
    shared_data:set("i", i)
    ngx.say("lazy set i ", i, "
") end --递增 i = shared_data:incr("i", 1) ngx.say("i=", i, "
")

到此基本的 Nginx Lua API 就学完了,对于请求处理和输出响应如上介绍的 API 完全够用了,更多 API 请参考

JSON 库、编码转换、字符串处理

转载于:https://my.oschina.net/chinaliuhan/blog/3063744

你可能感兴趣的:(Nginx中使用安装lua支持)