[code.openresty] Openresty Nginx API for Lua -上

Nginx API for Lua

介绍

各种各样的 *_by_lua_by_lua_block*_by_lua_file配置指令在nginx.conf文件中作为Lua API的网关。下面描述的Nginx Lua API只能在这些配置指令上下文中的用户Lua代码中被调用。

这个API是通过两个标准包ngxndk的形式暴露给Lua。这些包都是在ngx_lua的默认全局范围内并且在ngx_lua指令中总是可用的。

这个包可以像下面这样引入外部Lua模块:


      local say = ngx.say

      local _M = {}

      function _M.foo(a)
          say(a)
      encode_args

      return _M

强烈不建议使用package.seeall 标记,原因是它的各种负面作用。

直接在外部Lua模块require包也是可行的:


    local ngx = require "ngx"
    local ndk = require "ndk"

require这些包的能力是在v0.2.1rc19版本中被介绍的。

在用户代码中的网络I/O操作只能通过Nginx Lua API调用来完成,这是偶遇nginx事件循环可能阻塞另一方面性能可能急剧下降。相对少量数据的磁盘操作可以通过使用标准的Lua io库来完成但是只要有可能大文件读写就应该被避免这是因为他们会显著的阻塞Nginx进程。为了最好的表现,强烈建议指派所有的网络和磁盘I/O操作给Nginx的子请求(通过ngx.location.capture方法或者类似的)。

ngx.arg

语法: val = ngx.arg[index]

上下文: set_by_luabody_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;
        }

这将会写出883256的和。

当这个表在body_filter_by_lua的上下文中被使用时,第一个元素包含输出过滤代码的输入数据块并且第二个元素包含表明“eof”标记的boolean标记,用来表明整个输出数据流的结束。

传递到下游Nginx输出过滤器的数据块和“eof”标记也可以被复写然后直接赋值给相应表元素。当被设置为nil或者一个空Lua字符串值给ngx.arg[1],没有数据块将会被传递给下游的Nginx过滤器。

ngx.var.VARIABLE

语法: ngx.var.VAR_NAME

上下文: 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.Foonil值会清除$FooNginx变量。

      ngx.var.args = nil

注意 当读取Nginx变量时,Nginx会在每个请求内存池分配内存而且只会在请求终止后释放。所以当你需要在你的Lua代码里面从多次读取一个Nginx变量,以自己的变量来缓存Nginx变来那个,例如,


  local val = ngx.var.some_var
  -- use the val repeatedly later

为了防止(临时的)在当前请求生命周期中的内存泄漏。另一种方法是使用ngx.ctx表来缓存结果。

没有定义域的Nginx变来那个和nil是等价的,而未初始化的(但是已经定义了)Nginx变量和一个空的Lua字符串是等价的。

这个API需要一个相对昂贵的元方法调用并且建议在热代码路径中避免使用它。

Core constants

上下文: init_by_lua,set_by_lua,rewrite_by_lua,access_by_lua,content_by_luaheader_filter_by_lua,body_filter_by_lua,log_by_lua,ngx.timer.,balancer_by_lua,ssl_certificate_by_lua,ssl_session_fetch_by_luassl_session_store_by_lua**


      ngx.OK(0)
      ngx.ERROR (-1)
      ngx.AGAIN (-2)
      ngx.DONE (-4)
      ngx.DECLINED (-5)

注意这些常量里面仅有3各是被Nginx API for Lua接受的。(例如,ngx.exit 接受 NGX_OK,NGX_ERROR,和NGX_DECLINED作为输入)


    ngx.null

这个ngx.null常量是一个NULL轻量级用户数据,经常用在Lua table里面表示nil值,并且和lua-cjson库中的cjson.null常量相似。这个常量首先在v0.5.0rc5版本中被介绍。

这个ngx.DECLINED常量首先在v0.5.0rc19版本中被介绍。

HTTP method constants

上下文: init_by_lua,set_by_lua,rewrite_by_lua,access_by_lua,ccontent_by_lua,header_filter_by_lua,body_filter_by_lua,log_by_lua,ngx.timer.balancer_by_lua,ssl_certificate_by_luassl_session_fetch_by_luassl_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_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.capturengx.location.capture_multi方法调用中。

HTTP status constants

上下文: 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_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_UPGREADE_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_METHOND_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.9.20 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 log level constants

上下文: 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**

将参数值写入ngx error.log文件,以ngx.NOTICE日志级别。

它等价于

  ngx.log(ngx.NOTICE, ...)
``

Lua `nil` 参数是接受的并且结果为文字的`"nil"`字符串同时Lua boolean结果为文字的`"true"`或`"false"`字符串。并且`ngx.null`常量会产生`"null"`字符串输出。

在Nginx核心里面有一个硬编码的`2048`字节限制了错误信息的长度。这个显示包含了尾部的换行和头部的时间戳。如果信息长度超过了限制,Nginx会相应的截断信息文本。这个限制可以被修改,通过编辑 在Nginx源码树中`src/core/ngx.log.h`文件中的`NGX_MAX_ERROR_STR`宏定义。

### 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**

这个表可以用来存储每个请求上下文中的数据并且有一个和当前请求(正如Nginx变量)完全相同的生命周期。

参考下面的例子,

```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 持续存在request请求的rewrite,access,和content阶段。

每个请求,包含子请求,包含它自己的table副本,例如:


    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闭包和嵌套的表,可以被插入到这个“神奇的”表。它还允许注册自定义的元表。

通过一个新的Lua table来覆盖ngx.ctx也是支持的,例如,


    ngx.ctx = { foo = 32, bar = 54}

在被用在init_worker_by_lua*的上下文中被使用时,这个表和当前的Lua处理器有者同样的生命周期。

这个ngx.ctx查找需要相对昂贵的元方法调用并且它比明确的在你自己的方法参数里面传递当前请求数据相比要慢的多。所以不要滥用这个API来保存你自己方法的参数因为它经常有一些相当的性能影响。

因为元方法的魔法,不要在Lua模块级别在你自己方法范围之外"local"那个ngx.ctx表,根据worker-level data sharing。例如:下面是错误的:


      -- 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*

使用uri发出一个同步的但是仍然是非阻塞的 Nginx 子请求

Nginx的子请求提供一个强大的的方法来发出一个非阻塞内部请求,到磁盘文件目录配置的其他location,或者任何nginx C模块如ngx_proxy,ngx_fastcgi,ngx_memc,ngx_postgres,ngx_drizzle,甚至ngx_lua本身等等。

还要注意,subrequest模拟HTTP接口,但是没有额外的HTTP流量和IPC。一切在内部工作,高效的,在C级别。

子请求和HTTP 301/302重定向(通过ngx.redirect)和内部重定向(通过ngx.exec)是完全不一样的。

在开始一个子请求之前,你总是应该读取reqeust body(通过调用ngx.req.read_body或者配置lua_need_request_body on)。

这个API方法(ngx.location.capture_multi也一样)总是缓冲子请求的整个response body到内存中。因此,你应该使用cosockets和流处理来替代,如果你需要处理较大的子请求response的话。

这里有个基本的例子:


    res = ngx.location.capture(uri)

将返回一个Lua表,包含4个插槽:res.status,res.header,res.body,和res.truncated

res.status包含了子请求的响应的响应状态码。

res.header包含了所有子请求的响应头,并且它是一个普通的Lua table。对于多值得响应头,这个值是一个Lua(数组) table,包含了按照顺序出现所有的值。例如:如果子请求响应头包含下面的行:


    Set-Cookie: a = 3
    Set-Cookie: foo = bar
    Set-Cookie: baz = blah

那么res.header["Set-Cookie"]将会等价于表值{"a=3","foo=bar","baz=blah"}

res.body包含了子请求的响应body数据,有可能被截取掉。你一直需要检查res.truncated的boolean标记来检查res.body是否包含截取的数据。这个数据的截取仅仅可能是因为在你子请求中不可恢复的错误造成的,例如远程终端在响应body数据流传输的中间过早的终端连接或者当你子请求在从远端接收响应数据时读取时间超时。

URI查询字符串可以被连接到URI他自身上,例如,


    res = ngx.location.capture('/foo/bar?a=3&b=4')

像一些命名的location例如@foo由于Nginx内核的限制是不允许的。使用普通的location结合internal指令来准备只能内部调用的location。

一个可选的参数表可以作为第二个参数,支持的选项:

  • method
    指定子请求的请求方法,只能接受常量例如 ngx.HTTP_POST

  • body
    指定子请求的请求body (只支持string字符串)

  • args
    指定子请求URI查询字符串 (同时接受字符串值和Lua table)

  • ctx
    通过ngx.ctx表来指定子请求的一个Lua table。它可以是当前请求的ngx.ctx表,将会影响父请求和它的子请求来精确的共享同样的context table。这个选项首先在v0.3.1rc25版本中被介绍。

  • vars
    使用一个包含设置特殊Nginx变量的Lua table到子请求中,通过这个选项的值。这个选项首先在v0.3.1rc31版本中被介绍。

  • copy_all_vars
    指定是否复制当前请求的所有nginx变量到子请求中。在子请求中更改这个nginx变量将不会影响当前(父)请求。这个选项首先在v0.3.1rc31版本中被介绍。

  • share_all_vars

指定子请求是否共享当前(父)请求中的所有Nginx变量。在子请求中更改Nginx变量将会影响当前(父)请求。开启这个选项将会导致难以debug的问题,因为负面影响并且它是不好喝有害的。只有你完全清楚你自己在干什么的时候再开启这个选项。

  • alway_forward_body

当设置为true,当前(父)请求的请求body将会被一直转发给创建的子请求中,如果没有设置body选项的话。通过ngx.req.read_body()或者lua_need_request_body on读取的请求body将会被直接转发给子请求而不需要在创建子请求时复制整个请求body数据(不论请求body数据是缓冲在内存缓冲区还是在临时文件中)。在默认情况下,这个选项是false并且当body选项没有被指定的时候,这个当前(父)请求的请求body将只会被转发给通过PUT或者POST请求方法的子请求中。

发出一个POST子请求时,例如,可以像下面这样:


    res = ngx.location.capture(
          '/foo/bar',
          { method = ngx.HTTP_POST, body = 'hello,world' }
      )

参阅除了POST请求的其他子请求方法。
method选项默认是ngx.HTTP_GET

这个args选项可以指定额外的URI参数,例如,


    ngx.location.capture('/foo?a=1',
        { args = { b = 3,c = ':' } }
    )

这个等价于


    ngx.loation.captur('/foo?a=1&b=3&c=%3a')

也就是说,这个方法将避免根据URI规则的key和value。并且连接他们为一个完整的查询字符串。这个Lua table的形式传递args参数和使用ngx.encode_args方法是完全相同的。

这个args选项可以设置普通的查询字符串:

    ngx.location.capture('foo?a=1',{ args = 'b=3&c=%3a' })

这个方法和以前的例子是完全一样的。

这个share_all_vars选项控制是够共享nginx变量,从当前的请求到它的子请求中。

如果这个选项设置的是true,那么当前请求和关联的子请求将会共享相同的Nginx变量范围。因此,在子请求中更改的nginx变量将会影响当前的请求。

应该注意的的是使用这个选项作为变量范围共享将会发生难以预料的影响。一般是推荐argsvars,或者copy_all_vars选项。


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

访问location /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_varscopy_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 table来作为子请求的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代码正确处理。原始的请求header应该被忽略掉,通过在子请求的location中设置proxy_pass_request_headersoff

当没有指定body选项并且always_forward_body选项为false(默认值),这个POSTPUST子请求会继承父请求的body(如果可能的话)。

这里有个硬编码的限制数,限制每个主请求同时并发的子请求数量。在nginx的老版本中,这个限制是50并且在更前的版本中,Nginx 1.1.x之前,这个数量增加到200个并发子请求。当超出这个限制,下面的错误信息将会被添加到error.log文件中:

  [error] 13983#0: *1 subrequests cycle while processing "/uri"

如果需要的话,这个限制可以被更改,通过修改Nginx源码树种的nginx/src/http/ngx_http_request.h文件中定义的NGX_HTTP_MAX_SUBREQUEST宏。

另请参阅通过subrequest directives of other modules配置的capture location的限制、

ngx.location.capture_multi

语法: res1,res2,... = ngx.location.capture_multi( {uri,options?},{uri,options?}, ... })

上下文: rewrite_by_lua&$42;, access_by_lua, content_by_lua**

正如[ngx.location.capture],但是支持并行运行多个子请求。

这个方法通过输入table产生几个并行的子请求并且以同样的顺序返回他们的值。例如,


      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 table可以用在request和response中,当发起的子请求的数量事前不知道的时候。


    -- construct the request 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.capure =
      function (uri,args)
          return ngx.location.capture_multi({ uri,args })
      end

另请参阅在subrequest directives of other modules中配置的capture location的一些限制。

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*

读和写当前请求的响应状态。这应该在发出响应headers之前被调用。


      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**

设置,添加,或者清除当前请求的HEADER将要被发送的响应头。

在header名称中的下划线(_)在默认情况下会被替换成为连字符(-)。这个转化通过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']

多值的headers可以通过这种方式发送:


    ngx.header['Set-Cookie'] = { 'a=32;path=/','b=4;path=/'}

将会在响应的headers中产生:


    Set-Cookie: a=32; path=/
    Set-Cookie: b=4;path=/

只接受Lua table (类似Content-Type这些只接受一个值的标准header,只有table中的最后一个值才会起作用)


    ngx.header.content_type = {'a', 'b'}

等价于


    ngx.header.content_type = 'b'

设置这个插槽为nil将会影响它从响应头中被移出:


    ngx.header["X-My-Header"] = nil;

同样也适用于赋值一个空的表:


    ngx.header["X-My-Header"] = {};

在发送完响应头(明确的通过ngx.send_headers 或者隐式的通过nginx.print或类似的)将会跑出一个Lua异常。

读取ngx.header.HEADER将会返回响应头中名为HEADER的值。

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

对于多值得header,所有的header的值将会按照顺序手机并且作为一个Lua table返回。例如,response headers


    Foo: bar
    Foo: baz

将会得到结果


  {"bar", "baz"}

将会被通过ngx.header.Foo读取时返回。

注意ngx.header不是一个普通的Lua table并且同样的,他也不能通过Lua ipairs方法来迭代。

为了读取 request headers,使用ngx.req.get_headers 方法来代替。

ngx.resp.get_headers

语法: headers = 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 table,持有当前请求的所有的当前的响应headers


    local h = ngx.resp.get_headers()
    for k,v in pairs(h) do
        ...
    end

这个方法和[ngx.req.get_headers]有着同样的特征除了获取的是响应头而不是请求头。

这个接口首先在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*

返回一个boolean值标记当前的请求是否是一个“内部请求”,例如,一个从nginx服务器端那边生成的请求而不是从客户端那边。

这个接口首先在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.nowngx.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*

以Lua数字的形式返回表示当前request的HTTP版本。

当前可能的值有 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*

返回当前Nginx服务器收到的原始的HTTP协议header。

默认情况下,这个请求line和结尾的CR LF终结符也会被包含,例如,


    ngx.print(ngx.req.raw_header())

会得到类似下面的:

      GET /t HTTP/1.1
      Host:localhost
      Connection:close
      Foo:bar

你可以指定可选的no_request_line参数为true来从结果中排出请求line.例如,


      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"这种而不是数字型的method constants

如果当前的请求是一个Nginx子请求,那么将会返回子请求的方法名称。

这个方法首先在v0.7.17版本中被介绍。

另请参阅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参数来复写当前请求的请求方法。当前只有数字型的method constants 是支持的。例如ngx.HTTP_POSTngx.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字符串兵器不能是0长度,否则一个Lua异常将会被抛出。

这个可选的jump参数可以触发location重新匹配(或者location跳过),作为ngx_http_rewrite_modulerewrite 指令,也就是说,当jumptrue(默认是false),这个方法将永远不会返回并且它将告诉Nginx来尝试通过新的URI在后面post-rewrite阶段执行重新搜索location并且跳转到新的location中。

另一方面Location跳转将不会被触发,并且只有当前请求的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参数只能在rewrite_by_lua中被设置为true。在其他上下文中使用jump参数是禁止的并且会跑出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**

通过args参数来重写当前请求中的URI请求参数。这个args参数既可以是Lua string,例如


    ngx.req.set_uri_args("a=3&b=hello%20world")

或者一个包含查询参数的key-value对的Lua table,例如


    ngx.req.set_uri_args({ a = 3, b = "hello world" })

当是后面的情况时,这个方法将参数的中的key和value将不需要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 = 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**

返回一个持有所有当前请求URL查询参数的Lua表。


    location = /test {
        content_by_lua_block {
            local args = ngx.req.get_uri_args()
            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

多次出现的参数key会得到一个table,持有所有的值,这些值按顺序排列,共用同一个key。

key和value不按照URI转义规则转义。在上面的设置中,GET /test?a%20b=1%61+2会产生:


    a b: 1a 2

参数中没有=<value>部分的被当做是一个boolean参数。GET /test?foo&bar 会产生:


    foo:true
    bar:true

也就是说,他们会使用Lua boolean值ture。然而,他们和参数中种使用空字符串的不同。GET /test?foo=&bar=将会得到这样的结果


  foo:
  bar:

key为空的参数将会被丢弃。例如GET /test?=hello&=world将会导致一个空的输出。

支持在运行过程中通过nginx变量$args(或者Lua里面的 ngx.var.args)来更新查询参数。


    ngx.var.args = "a=3&b=42"
    local args = ngx.req.get_uri_args()

这里的args table将一直是这个样子


 {a = 3, b = 42}

而不管实际请求的字符串是什么。

注意,默认最大解析100个请求参数(包括这些有着同样名称的)并且额外的请求参数会被默默的丢弃,以防止拒绝服务式攻击。

然而,这个max_args函数参数可以用来覆盖这个极限:


 local args = ngx.req.get_uri_args(10)

这个参数可以设置为0,来限制和处理所有的请求参数:


  local args = 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**

返回一个包含了所有当前POST请求参数的Lua table(MIME类型 application/x-www-form-urlencoded的)。首先调用ngx.req.read_body来读取request body或者启用lua_need_request_body指令来避免异常。


 location = /test {
     content_by_lua_block {
         ngx.req.read_body()
         local args, err = ngx.req.get_post_args()
         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

会产生如下的响应body


 foo: bar
 bar: baz, blah

多次出现的参数key会得到一个table,持有所有的值,这些值按顺序排列,共用同一个key。

key和value不按照URI转义规则转义。在上面的设置中,


 # POST request with body 'a%20b=1%61+2'
 $ curl -d 'a%20b=1%61+2' localhost/test

会产生


 a b: 1a 2

参数中没有=<value>部分的被当做是一个boolean参数。GET /test?foo&bar 会产生:


    foo:true
    bar:true

也就是说,他们会使用Lua boolean值ture。然而,他们和参数中种使用空字符串的不同。POST /test使用请求 body foo=&bar= 将会返回如下的信息。


 foo:
 bar:

key为空的参数将会被丢弃。例如POST /test 使用body =hello&=world 将会导致一个空的输出。

注意,默认最大解析100个请求参数(包括这些有着同样名称的)并且额外的请求参数会被默默的丢弃,以防止拒绝服务式攻击。

然而,这个max_args函数参数可以用来覆盖这个极限:


 local args = ngx.req.get_post_args(10)

这个参数可以设置为0,来限制和处理所有的请求参数:


 local args = ngx.req.get_post_args(0)

强烈不建议覆盖掉max_args参数。

ngx.req.get_headers

语法: headers = ngx.req.get_headers(max_headers?, raw?)

context: set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua, header_filter_by_lua, body_filter_by_lua, log_by_lua*

返回一个包含当前所有请求headers的Lua table。


 local h = ngx.req.get_headers()
 for k, v in pairs(h) do
     ...
 end

要读取个别的header:


 ngx.say("Host: ", ngx.req.get_headers()["Host"])

注意ngx.var.HEADER API调用,使用内核的$http_HEADER变量,可能更适合读取个别的请求header。

对于多个实体的请求header例如:


 Foo: foo
 Foo: bar
 Foo: baz

ngx.req.get_headers()["Foo"]的值将会是一个Lua(array) table,例如:


 {"foo", "bar", "baz"}

注意,默认最大解析100个请求参数(包括这些有着同样名称的)并且额外的请求参数会被默默的丢弃,以防止拒绝服务式攻击。

然而,这个max_headers函数参数可以用来覆盖这个极限:


 local headers = ngx.req.get_headers(10)

这个参数可以设置为0,来限制和处理所有的请求参数:


 local headers = ngx.req.get_headers(0)

强烈不建议覆盖掉max_args参数。

0.6.9版本开始,所有在Lua table中返回的header名称被默认转换成纯小写形式的,除了raw参数被设置为true(默认是false)。

并且,默认情况下,一个__index原方法被加入到结果Lua table中并且会是说是有的key规范为纯小写形式,将所有连字符下划线转换为下划线形式,以防止查找不到。例如,如果给出了一个 My-Foo-Header的请求header,那么下面的调用都能成功的获取这个header的值:


 ngx.say(headers.my_foo_header)
 ngx.say(headers["My-Foo-Header"])
 ngx.say(headers["my-foo-header"])

raw参数被设置为true后,这个_index元方法将不会被添加。

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名称为 header_name转换为header_value,覆盖任何现有的。

默认情况下,所有ngx.location.capturengx.location.capture_multi发起的子请求将会继承新的header。

这里有个设置Content-Type header的例子:


 ngx.req.set_header("Content-Type", "text/css")

这个header_value可以使用列表数据,例如。


 ngx.req.set_header("Foo", {"a", "abc"})

将会产生两个新的request headers:


 Foo: a
 Foo: abc

并且如果存在老的Foo headers的话将会被覆盖掉。

当这个 header_value 参数是nil,这个请求header将会被移除。所以


 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的请求header。当前请求中存在的子请求将不会受到影响,但是随后产生的子请求默认会继承这个修改。

ngx.req.read_body

语法: ngx.req.read_body()

上下文: rewrite_by_lua, access_by_lua, content_by_lua*

同步的读取客户端的请求body而不会阻塞Nginx事件循环。


 ngx.req.read_body()
 local args = ngx.req.get_post_args()

如果事先已经读取了请求body,通过开启lua_need_request_body或者使用其他模块。那么这个方法不运行并且会直接返回。

如果这个请求body已经被明确的丢弃了,无论是通过ngx.req.discard_body 方法或者使用其他模块,那么这个方法不运行并且会直接返回。

在发生错误的情况下,如在读取数据时发生连接错误,这个方法将会抛出一个Lua异常 或者 立即终止当前的请求返回一个500错误码。

使用这个方法读取request body数据可以在后面通过ngx.req.get_body_data 重新取回,或者,作为另一种选择,使用ngx.req.get_body_file获取body数据缓存到磁盘的临时文件名称。这个取决于:

  1. 是否当前的请求body已经比client_body_buffer_size要大。

  2. 并且是否client_body_in_file_only已经被开启了。

假使当前请求可能有请求bidy并且请求body数据不是所需的,这个ngx.req.discard_body方法必须被用来明确地丢弃请求body来避免在HTTP 1.1长连接或者HTTP 1.1管道技术中发生中断的事情。

这个方法首先在 v0.3.1rc17版本中被介绍。

ngx.req.discard_body

语法: ngx.req.discard_body()

上下文: rewrite_by_lua, access_by_lua, content_by_lua*

明确地丢弃请求body,例如,在连接中读取数据并立即将其丢弃(不使用请求主体)。

这个方法是异步调用并且会立即返回。

如果这个请求body已经被读取了,这个方法什么也不做并且会立即返回。

这个方法首先在v0.3.1rc17版本中被介绍。

另请参阅 [ngx.req.read_body](#ngxreqread_body。

ngx.req.get_body_data

语法: data = ngx.req.get_body_data()

上下文: rewrite_by_lua, access_by_lua, content_by_lua, log_by_lua**

重新获取内存中的请求body数据。它将会返回一个Lua字符串而不是一个持有所有解析过的请求参数的Lua table。如果需要一个Lua table使用ngx.req.get_post_args方法代替。

这个方法将会返回nil如果

  1. 请求body没有没读取,
  2. 请求body已经被读取到磁盘临时文件里面,
  3. 或者请求body只有0长度。

如果这个请求body还没有被读取,先调用ngx.req.read_body (或者启用lua_need_request_body)来强制这个模块读取请求body。然而不建议这么做)。

如果这个请求body已经被读到磁盘文件里面了,试着调用ngx.req.get_body_file方法。

强制将请求body存到内存中,试着使用client_body_buffer_sizeclient_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*

重新获取已经在文件内部的请求body数据的文件名称。如果请求body没有被读取或者已经被读取到内存中了,将返回nil值。

返回的文件是只读的并且通常被Nginx的内存池清除掉。它不应该被认为的修改,重命名或者在Lua代码里面移除。

如果这个请求body还没有被读取,先调用ngx.req.read_body (或者启用lua_need_request_body)来强制这个模块读取请求body。然而不建议这么做)。

如果这个请求body已经被读到内存里面了,试着调用ngx.req.get_body_data方法代替。

为了强制将请求body存到文件中,试着开启client_body_in_file_only

这个方法首先在v0.3.1rc17版本中被介绍。

另请参阅 ngx.req.get_body_data.

ngx.req.set_body_data

语法: ngx.req.set_body_data(data)

上下文: rewrite_by_lua, access_by_lua, content_by_lua*

使用data参数指定的内存数据来设置当前请求中的请求body。

如果当前请求的请求body没有被读取,那么将会被适当的丢弃。如果当前请求的请求body已经被读取到内存或者缓存到磁盘文件中,那么老的请求body的内存将会被释放或者磁盘文件将会被立即清除,分别的。

这个方法首先在v0.3.1rc17版本中被介绍。

另请参阅ngx.req.set_body_file.

ngx.req.set_body_file

语法: ngx.req.set_body_file(file_name, auto_clean?)

上下文: rewrite_by_lua, access_by_lua, content_by_lua*

通过使用file_name参数中指定的在文件中的数据来设置当前请求的请求body。

如果选项auto_clean参数被赋值为一个true值,那么这个文件将会在请求完成或者这个方法下次被调用或者ngx.req.set_body_data被在同一个请求中调用的时候被清除掉。

请保证通过file_name参数指定的文件存在并且是被Nginx工作进程可读取的,用过设置恰当的权限来避免Lua异常错误。

如果当前请求的请求body没有被读取,那么将会被适当的丢弃如果当前请求的请求body已经被读取到内存或者缓存到磁盘文件,那么老的请求body内存将会被释放或者磁盘文件将会被立即清除,分别的。

这个方法首先在v0.3.1rc18版本中被介绍。

另请参阅 ngx.req.set_body_data.

ngx.req.init_body

语法: ngx.req.init_body(buffer_size?)

上下文: set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua**

为当前请求创建一个空白的请求body并且为后续请求body数据的写入初始化缓冲,通过ngx.req.append_bodyngx.req.finish_body接口。

如果指定了buffer_size参数,那么它的值将被用来设置为通过ngx.req.append_body写入body时的内存缓冲区的大小。
如果这个参数被省略,那么通过标准client_body_buffer_size指令指定的值将会被用来做替代。

当对于请求body,数据不能被内存缓冲区来保存时,这个数据将会被刷新到一个临时文件中,就如同在Nginx内核中的标准的请求body读取器一样。

当所有的数据已经被添加到当前的请求body之后,调用ngx.req.finish_body是非常重要的。同时,当这个方法和ngx.req.socket同时使用的时候,它需要在这个方法之前调用ngx.req.socket否则你会得到"request body already exists" 的错误信息。

这个方法使用经常如下:


 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_bodyngx.req.finish_bodyngx.req.socket一起使用来在纯Lua中实现有效率的输入过滤器( rewrite_by_lua* 或者 access_by_lua*的上下文中),同时可以和其他Nginx内存处理器或者负载均衡模块例如ngx_http_proxy_modulengx_http_fastcgi_module一起使用。

这个方法首先在v0.5.11版本中被介绍。

ngx.req.append_body

语法: ngx.req.append_body(data_chunk)

上下文: set_by_lua, rewrite_by_lua, access_by_lua, content_by_lua**

追加通过data_chunk参数指定的新的数据块到通过调用ngx.req.init_body创建的请求body中。

当对于请求body,数据不能被内存缓冲区来保存时,这个数据将会被刷新到一个临时文件中,就如同在Nginx内核中的标准的请求body读取器一样。

当所有的数据已经被添加到当前的请求body之后,调用ngx.req.finish_body是非常重要的。

当这个方法和ngx.req.init_body, ngx.req.finish_body,和ngx.req.socket同时使用,来在纯Lua中实现有效率的输入过滤器( rewrite_by_lua* 或者 access_by_lua*的上下文中),同时可以和其他Nginx内存处理器或者负载均衡模块例如ngx_http_proxy_modulengx_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_bodyngx.req.append_body调用创建的新的请求body的构造过程。

这个方法可以和ngx.req.init_body, ngx.req.append_body,和ngx.req.socket同时使用,来在纯Lua中实现有效率的输入过滤器( rewrite_by_lua* 或者 access_by_lua*的上下文中),同时可以和其他Nginx内存处理器或者负载均衡模块例如ngx_http_proxy_modulengx_http_fastcgi_module一起使用。

这个方法首先在v0.5.11版本中被介绍。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容