requests: Yet Another HTTP library for nginx-module-lua - 为人类服务!
安装
如果您尚未设置 RPM 仓库订阅,请 注册。然后您可以继续以下步骤。
CentOS/RHEL 7 或 Amazon Linux 2
yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-requests
CentOS/RHEL 8+、Fedora Linux、Amazon Linux 2023
dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-requests
要在 NGINX 中使用此 Lua 库,请确保已安装 nginx-module-lua。
本文档描述了 lua-resty-requests v0.7.3,发布于 2019 年 7 月 18 日。
- 支持 HTTP/1.0、HTTP/1.1 和 HTTP/2(正在进行中)。
- 支持 SSL/TLS。
- 支持分块数据。
- 提供方便的接口以支持 JSON、授权等功能。
- 提供读取主体的流接口。
- 支持 HTTP/HTTPS 代理。
- 支持延迟指标。
- 支持会话。
概述
local requests = require "resty.requests"
-- 示例 URL
local url = "http://example.com/index.html"
local r, err = requests.get(url)
if not r then
ngx.log(ngx.ERR, err)
return
end
-- 读取所有主体
local body = r:body()
ngx.print(body)
-- 或者您可以迭代响应主体
-- while true do
-- local chunk, err = r:iter_content(4096)
-- if not chunk then
-- ngx.log(ngx.ERR, err)
-- return
-- end
--
-- if chunk == "" then
-- break
-- end
--
-- ngx.print(chunk)
-- end
-- 您还可以使用非流模式
-- local opts = {
-- stream = false
-- }
--
-- local r, err = requests.get(url, opts)
-- if not r then
-- ngx.log(ngx.ERR, err)
-- end
--
-- ngx.print(r.content)
-- 或者您可以使用简化方式使代码更简洁。
local r, err = requests.get { url = url, stream = false }
方法
request
语法: local r, err = requests.request(method, url, opts?) 语法: local r, err = requests.request { method = method, url = url, ... }
这是 lua-resty-requests 中的关键方法,它将返回一个 响应对象 r。如果失败,将返回 nil 和一个描述相应错误的 Lua 字符串。
第一个参数 method 是您想要使用的 HTTP 方法(与 HTTP 的语义相同),它接受一个 Lua 字符串,值可以是:
GETHEADPOSTPUTDELETEOPTIONSPATCH
第二个参数 url 仅取字面意义(即统一资源位置),例如 http://foo.com/blah?a=b,您可以省略方案前缀,默认方案将选择 http。
第三个参数是一个可选的 Lua 表,包含多个选项:
-
headers保存自定义请求头。 -
allow_redirects指定在状态码为301、302、303、307或308时是否重定向到目标 URL(由Location头指定)。 -
redirect_max_times指定重定向限制,默认值为10。 -
body,请求主体,可以是:- 一个 Lua 字符串,或
- 一个 Lua 函数,无参数并返回一段数据(字符串)或一个空的 Lua 字符串以表示 EOF,或
- 一个 Lua 表,每个键值对将用
&连接,Content-Type 头将为"application/x-www-form-urlencoded"。
-
error_filter,保存一个 Lua 函数,该函数接受两个参数,state和err。参数err描述错误,state始终是以下值之一(表示当前阶段):requests.CONNECTrequests.HANDSHAKErequests.SEND_HEADERrequests.SEND_BODYrequests.RECV_HEADERrequests.RECV_BODYrequests.CLOSE
您可以使用方法 requests.state 获取这些值的文本含义。
-
timeouts,一个类似数组的表,timeouts[1]、timeouts[2]和timeouts[3]分别表示连接超时、发送超时和读取超时(以毫秒为单位)。 -
http10指定是否应使用HTTP/1.0,默认版本为HTTP/1.1。 http20指定是否应使用HTTP/2,默认版本为HTTP/1.1。
请注意,这仍然不稳定,应谨慎使用。此外,还有一些限制,详细信息请参见 lua-resty-http2。
ssl保存一个 Lua 表,包含三个字段:verify,控制是否执行 SSL 验证。-
server_name,用于指定新 TLS 扩展服务器名称指示(SNI)的服务器名称。 -
proxies指定代理服务器,形式如下:
{
http = { host = "127.0.0.1", port = 80 },
https = { host = "192.168.1.3", port = 443 },
}
使用 HTTPS 代理时,将向代理服务器发送前置 CONNECT 请求。
hooks,也是一个 Lua 表,表示您可以用来操控请求过程部分的钩子系统。可用的钩子有:response,将在接收到响应头后立即触发。
您可以将 Lua 函数分配给钩子,这些函数接受 响应对象 作为唯一参数。
local hooks = {
response = function(r)
ngx.log(ngx.WARN, "在请求处理过程中")
end
}
考虑到便利性,还有一些“快捷方式”选项:
auth,用于进行基本 HTTP 授权,接受一个包含user和pass的 Lua 表,例如,当auth为:
{
user = "alex",
pass = "123456"
}
请求头 Authorization 将被添加,值为 Basic YWxleDoxMjM0NTY=。
-
json,接受一个 Lua 表,它将通过cjson序列化,序列化的数据将作为请求主体发送,当同时指定json和body时,优先使用json。 -
cookie,接受一个 Lua 表,键值对将根据Cookie头的规则进行组织,例如cookie为:
{
["PHPSESSID"] = "298zf09hf012fh2",
["csrftoken"] = "u32t4o3tb3gg43"
}
Cookie 头将为 PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43。
stream,接受一个布尔值,指定是否以流模式读取主体,默认值为 true。
state
语法: local state_name = requests.state(state)
该方法用于获取这些值的文本含义:
requests.CONNECTrequests.HANDSHAKErequests.SEND_HEADERrequests.SEND_BODYrequests.RECV_HEADERrequests.RECV_BODYrequests.CLOSE
如果 state 不是上述值之一,将返回 Lua 字符串 "unknown"。
get
语法: local r, err = requests.get(url, opts?) 语法: local r, err = requests.get { url = url, ... }
发送一个 HTTP GET 请求。这与
requests.request("GET", url, opts)
是相同的。
head
语法: local r, err = requests.head(url, opts?) 语法: local r, err = requests.head { url = url, ... }
发送一个 HTTP HEAD 请求。这与
requests.request("HEAD", url, opts)
是相同的。
post
语法: local r, err = requests.post(url, opts?) 语法: local r, err = requests.post { url = url, ... }
发送一个 HTTP POST 请求。这与
requests.request("POST", url, opts)
是相同的。
put
语法: local r, err = requests.put(url, opts?) 语法: local r, err = requests.put { url = url, ... }
发送一个 HTTP PUT 请求。这与
requests.request("PUT", url, opts)
是相同的。
delete
语法: local r, err = requests.delete(url, opts?) 语法: local r, err = requests.delete { url = url, ... }
发送一个 HTTP DELETE 请求。这与
requests.request("DELETE", url, opts)
是相同的。
options
语法: local r, err = requests.options(url, opts?) 语法: local r, err = requests.options { url = url, ... }
发送一个 HTTP OPTIONS 请求。这与
requests.request("OPTIONS", url, opts)
是相同的。
patch
语法: local r, err = requests.patch(url, opts?) 语法: local r, err = requests.patch { url = url, ... }
发送一个 HTTP PATCH 请求。这与
requests.request("PATCH", url, opts)
是相同的。
响应对象
像 requests.get 等方法将返回一个响应对象 r,可以通过以下方法和变量进行操作:
url,从调用者传递的 URLmethod,请求方法,例如POSTstatus_line,原始状态行(从远程接收)status_code,HTTP 状态码http_version,响应的 HTTP 版本,例如HTTP/1.1headers,一个 Lua 表,表示 HTTP 响应头(不区分大小写)close,保存一个 Lua 函数,用于关闭(保持活动)底层 TCP 连接drop,是一个 Lua 函数,用于丢弃未读的 HTTP 响应主体,在关闭时(如果有未读数据)将自动调用iter_content,也是一个 Lua 函数,每次调用时发出一部分响应主体(从分块格式解码)。
此函数接受一个可选参数 size,以指定调用者想要的主体大小,缺省时,iter_content 在响应主体为普通格式时返回 8192 字节,或在响应主体为分块格式时返回一段分块数据。
如果失败,将返回 nil 和描述错误的 Lua 字符串。
body,也保存一个 Lua 函数,返回整个响应主体。
如果失败,将返回 nil 和描述错误的 Lua 字符串。
-
json,保存一个 Lua 函数,将主体序列化为 Lua 表,注意Content-Type应为application/json。如果失败,将返回nil和错误字符串。 -
content,响应主体,仅在非流模式下有效。 -
elapsed,一个类似哈希的 Lua 表,表示每个阶段的耗时(以秒为单位)。 elapsed.connect,TCP 三次握手的耗时;elapsed.handshake,SSL/TLS 握手的耗时(如果有);elapsed.send_header,发送 HTTP 请求头的耗时;elapsed.send_body,发送 HTTP 请求主体的耗时(如果有);elapsed.read_header,接收 HTTP 响应头的耗时;elapsed.ttfb,首字节时间。
注意:当应用 HTTP/2 协议时,elapsed.send_body(如果有)将与 elapsed.send_header 相同。
会话
会话在多个请求之间持久化一些数据,例如 Cookie 数据、授权数据等。
此机制目前仍处于实验阶段。
一个简单的示例:
s = requests.session()
local r, err = s:get("https://www.example.com")
ngx.say(r:body())
会话对象具有与 requests 相同的接口,即那些 HTTP 方法。
另请参阅
- upyun-resty: https://github.com/upyun/upyun-resty
- httpipe: https://github.com/timebug/lua-resty-httpipe
GitHub
您可以在 nginx-module-requests 的 GitHub 仓库 中找到此模块的其他配置提示和文档。