ngx.location.capture

用法:

local res = ngx.location.capture(uri, options)

发起一个同步非阻塞的nginx子请求,uri是internal的。

返回的res是个table,索引依次是status(值是number类型)、body(值是string类型)、header(值是table类型)、truncated(值是boolean类型)

context: rewrite_by_lua*, access_by_lua*, content_by_lua*

Issues a synchronous but still non-blocking Nginx Subrequest using uri.

Nginx's subrequests provide a powerful way to make non-blocking internal requests to other locations configured with disk file directory or any other nginx C modules like ngx_proxyngx_fastcgingx_memcngx_postgresngx_drizzle, and even ngx_lua itself and etc etc etc.

Also note that subrequests just mimic the HTTP interface but there is no extra HTTP/TCP traffic nor IPC involved. Everything works internally, efficiently, on the C level.

Subrequests are completely different from HTTP 301/302 redirection (via ngx.redirect) and internal redirection (via ngx.exec).

You should always read the request body (by either calling ngx.req.read_body or configuring lua_need_request_body on) before initiating a subrequest.

This API function (as well as ngx.location.capture_multi) always buffers the whole response body of the subrequest in memory. Thus, you should use cosockets and streaming processing instead if you have to handle large subrequest responses.

Here is a basic example:

 res = ngx.location.capture(uri)

Returns a Lua table with 4 slots: res.statusres.headerres.body, and res.truncated.

res.status holds the response status code for the subrequest response.

res.header holds all the response headers of the subrequest and it is a normal Lua table. For multi-value response headers, the value is a Lua (array) table that holds all the values in the order that they appear. For instance, if the subrequest response headers contain the following lines:

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

Then res.header["Set-Cookie"] will be evaluated to the table value {"a=3", "foo=bar", "baz=blah"}.

res.body holds the subrequest's response body data, which might be truncated. You always need to check the res.truncated boolean flag to see if res.body contains truncated data. The data truncation here can only be caused by those unrecoverable errors in your subrequests like the cases that the remote end aborts the connection prematurely in the middle of the response body data stream or a read timeout happens when your subrequest is receiving the response body data from the remote.

URI query strings can be concatenated to URI itself, for instance,

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

Named locations like @foo are not allowed due to a limitation in the nginx core. Use normal locations combined with the internal directive to prepare internal-only locations.

An optional option table can be fed as the second argument, which supports the options:

  • method specify the subrequest's request method, which only accepts constants like ngx.HTTP_POST.
  • body specify the subrequest's request body (string value only).
  • args specify the subrequest's URI query arguments (both string value and Lua tables are accepted)
  • ctx specify a Lua table to be the ngx.ctx table for the subrequest. It can be the current request's ngx.ctx table, which effectively makes the parent and its subrequest to share exactly the same context table. This option was first introduced in the v0.3.1rc25 release.
  • vars take a Lua table which holds the values to set the specified Nginx variables in the subrequest as this option's value. This option was first introduced in the v0.3.1rc31 release.
  • copy_all_vars specify whether to copy over all the Nginx variable values of the current request to the subrequest in question. modifications of the nginx variables in the subrequest will not affect the current (parent) request. This option was first introduced in the v0.3.1rc31 release.
  • share_all_vars specify whether to share all the Nginx variables of the subrequest with the current (parent) request. modifications of the Nginx variables in the subrequest will affect the current (parent) request. Enabling this option may lead to hard-to-debug issues due to bad side-effects and is considered bad and harmful. Only enable this option when you completely know what you are doing.
  • always_forward_body when set to true, the current (parent) request's request body will always be forwarded to the subrequest being created if the body option is not specified. The request body read by either ngx.req.read_body() or lua_need_request_body on will be directly forwarded to the subrequest without copying the whole request body data when creating the subrequest (no matter the request body data is buffered in memory buffers or temporary files). By default, this option is false and when the body option is not specified, the request body of the current (parent) request is only forwarded when the subrequest takes the PUT or POST request method.

Issuing a POST subrequest, for example, can be done as follows

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

See HTTP method constants methods other than POST. The method option is ngx.HTTP_GET by default.

The args option can specify extra URI arguments, for instance,

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

is equivalent to

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

that is, this method will escape argument keys and values according to URI rules and concatenate them together into a complete query string. The format for the Lua table passed as the args argument is identical to the format used in the ngx.encode_args method.

The args option can also take plain query strings:

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

This is functionally identical to the previous examples.

The share_all_vars option controls whether to share nginx variables among the current request and its subrequests. If this option is set to true, then the current request and associated subrequests will share the same Nginx variable scope. Hence, changes to Nginx variables made by a subrequest will affect the current request.

Care should be taken in using this option as variable scope sharing can have unexpected side effects. The argsvars, or copy_all_vars options are generally preferable instead.

This option is set to false by default

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

Accessing location /lua gives

/other dog: hello world
/lua: hello world

The copy_all_vars option provides a copy of the parent request's Nginx variables to subrequests when such subrequests are issued. Changes made to these variables by such subrequests will not affect the parent request or any other subrequests sharing the parent request's variables.

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

Request GET /lua will give the output

/other dog: hello world
/lua: hello

Note that if both share_all_vars and copy_all_vars are set to true, then share_all_vars takes precedence.

In addition to the two settings above, it is possible to specify values for variables in the subrequest using the vars option. These variables are set after the sharing or copying of variables has been evaluated, and provides a more efficient method of passing specific values to a subrequest over encoding them as URL arguments and unescaping them in the Nginx config file.

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

Accessing /lua will yield the output

dog = hello
cat = 32

The ctx option can be used to specify a custom Lua table to serve as the ngx.ctx table for the subrequest.

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

Then request GET /lua gives

bar
nil

It is also possible to use this ctx option to share the same ngx.ctx table between the current (parent) request and the subrequest:

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

Request GET /lua yields the output

bar

Note that subrequests issued by ngx.location.capture inherit all the request headers of the current request by default and that this may have unexpected side effects on the subrequest responses. For example, when using the standard ngx_proxymodule to serve subrequests, an "Accept-Encoding: gzip" header in the main request may result in gzipped responses that cannot be handled properly in Lua code. Original request headers should be ignored by setting proxy_pass_request_headersto off in subrequest locations.

When the body option is not specified and the always_forward_body option is false (the default value), the POST and PUTsubrequests will inherit the request bodies of the parent request (if any).

There is a hard-coded upper limit on the number of concurrent subrequests possible for every main request. In older versions of Nginx, the limit was 50 concurrent subrequests and in more recent versions, Nginx 1.1.x onwards, this was increased to 200 concurrent subrequests. When this limit is exceeded, the following error message is added to the error.log file:

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

The limit can be manually modified if required by editing the definition of the NGX_HTTP_MAX_SUBREQUESTS macro in the nginx/src/http/ngx_http_request.h file in the Nginx source tree.

Please also refer to restrictions on capturing locations configured by subrequest directives of other modules.

lua-nginx-module模块常用命令的更多相关文章

  1. 用lua nginx module搭建一个二维码

    用lua nginx module搭建一个二维码(qr code)生成器 作者 vinoca 發布於 2014年10月31日 如果有VPS,或者开源的路由器,安装一个nginx,添加lua-nginx ...

  2. nginx 配置以及常用命令

    windows下安装以及配置nginx http://jingyan.baidu.com/article/f3e34a12a9c1c3f5eb6535d4.html 1)下载地址: http://ng ...

  3. nginx日常维护常用命令

    http://www.jb51.net/article/47750.htm 一.简明nginx常用命令 1. 启动 Nginx poechant@ubuntu:sudo ./sbin/nginx 2. ...

  4. npm 模块常用命令

    mocha mocha --compilers js:babel/register : 在babel模式下测试,默认查找test文件夹,注意此时全局不要安装babel; ./node_modules/ ...

  5. Nginx安装及常用命令

    一.选定源码目录 cd /usr/local/src 可以是任何目录,本文选定的是/usr/local/src 二.安装依赖库 yum install gcc yum install pcre-dev ...

  6. nginx实战操作(常用命令及配置)

    1. nginx介绍 2. nginx常用命令 验证配置是否正确: nginx -t 查看Nginx的详细的版本号:nginx -V 查看Nginx的简洁版本号:nginx -v 启动Nginx:st ...

  7. 【Nginx】Linux常用命令------启动、停止、重启

    启动 启动代码格式:nginx安装目录地址 -c nginx配置文件地址 例如: [root@LinuxServer sbin]# /usr/local/nginx/sbin/nginx -c /us ...

  8. python os模块 常用命令

    python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关.以下列举常用的命令 1. os.name()——判断现在正在实用的平台,Window ...

  9. 【python】os模块常用命令

    python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关.以下列举常用的命令 1. os.name()——判断现在正在实用的平台,Window ...

  10. python os模块常用命令

    python编程时,经常和文件.目录打交道,这是就离不了os模块.os模块包含普遍的操作系统功能,与具体的平台无关.以下列举常用的命令 1. os.name()——判断现在正在实用的平台,Window ...

随机推荐

  1. Qt编译,imp_CommandLineToArgvW@8问题

    Tested msvc2013. The linker can not find _imp_CommandLineToArgvW@8. It's in shell32.lib. I see qtmai ...

  2. vscode填坑之旅: vscode设置中文,设置中文不成功问题

    刚安装好的vscode界面显示中文,如何设置中文呢? 在locale.json界面设置”locale":"zh-cn"也未能实现界面为中文,在网上找了参考了,以下教程真实 ...

  3. Spark 0.9.1和Shark 0.9.1分布式安装指南

    目录 目录 1 1. 约定 1 2. 安装Scala 1 2.1. 下载 2 2.2. 安装 2 2.3. 设置环境变量 2 3. 安装Spark 2 3.1. 部署 2 3.2. 下载 3 3.3. ...

  4. src.rpm格式的RHCS源码提取

    RHCS源码下载(地址1:地址2) 参考文档(RHCS安装也配置) RHCS源码提取(参考) 方法一: (1)rpm –ivh magma-plugins-1.0.15-3.src.rpm   执行r ...

  5. c语言和java以及安卓和苹果

    苹果手机是本地,没有中间环节,速度快,基于Linux系统 安卓是通过虚拟机,影响速度 就像c语言和java c适用于架构小的地方,因为直接编译运行 而java用于架构比较大的地方,启动慢,启动之后效率 ...

  6. Android-AndroidStudio Run 'app'安装APK到设备的过程

    1.AndroidStudio 点击Run ‘app’. 2.点击Run ‘app’就会将所有.class文件用SDK工具集处理成.dex, 用SDK工具集将图片/资源/布局文件/AndroidMan ...

  7. Arcgis Android 坐标转换

    http://spatialreference.org/首先,在上面的网站查出现有的坐标srid,然后查出目标Srid. 参考api 示例代码 Point point = new Point(120. ...

  8. Backup--完整备份会打破现有的日志备份链么?

    --问题描述: --对数据库有一个周期性数据库备份和事务日志备份的维护计划,在维护计划外有工作人员对数据库进行完整备份,该备份会打乱现有的日志备份链么? --===================== ...

  9. docker-compsoe & .netcore & nginx

    1.引言 紧接上篇.NET Core容器化@Docker,这一节我们先来介绍如何使用Nginx来完成.NET Core应用的反向代理,然后再介绍多容器应用的部署问题. 2. Why Need Ngin ...

  10. Windows上编译OpenImageIO

    这里使用的是OpenImageIO 1.1.11,要将OIIO解压到[工作目录]/openimageio/oiio里面. 先要给OIIO打一个patch,patch文件是Blender提供的: 下载O ...