跳转至

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 字符串,值可以是:

  • GET
  • HEAD
  • POST
  • PUT
  • DELETE
  • OPTIONS
  • PATCH

第二个参数 url 仅取字面意义(即统一资源位置),例如 http://foo.com/blah?a=b,您可以省略方案前缀,默认方案将选择 http

第三个参数是一个可选的 Lua 表,包含多个选项:

  • headers 保存自定义请求头。

  • allow_redirects 指定在状态码为 301302303307308 时是否重定向到目标 URL(由 Location 头指定)。

  • redirect_max_times 指定重定向限制,默认值为 10

  • body,请求主体,可以是:

    • 一个 Lua 字符串,或
    • 一个 Lua 函数,无参数并返回一段数据(字符串)或一个空的 Lua 字符串以表示 EOF,或
    • 一个 Lua 表,每个键值对将用 & 连接,Content-Type 头将为 "application/x-www-form-urlencoded"
  • error_filter,保存一个 Lua 函数,该函数接受两个参数,stateerr。参数 err 描述错误,state 始终是以下值之一(表示当前阶段):

    • requests.CONNECT
    • requests.HANDSHAKE
    • requests.SEND_HEADER
    • requests.SEND_BODY
    • requests.RECV_HEADER
    • requests.RECV_BODY
    • requests.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 授权,接受一个包含 userpass 的 Lua 表,例如,当 auth 为:
{
    user = "alex",
    pass = "123456"
}

请求头 Authorization 将被添加,值为 Basic YWxleDoxMjM0NTY=

  • json,接受一个 Lua 表,它将通过 cjson 序列化,序列化的数据将作为请求主体发送,当同时指定 jsonbody 时,优先使用 json

  • cookie,接受一个 Lua 表,键值对将根据 Cookie 头的规则进行组织,例如 cookie 为:

{
    ["PHPSESSID"] = "298zf09hf012fh2",
    ["csrftoken"] = "u32t4o3tb3gg43"
}

Cookie 头将为 PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43

  • stream,接受一个布尔值,指定是否以流模式读取主体,默认值为 true。

state

语法: local state_name = requests.state(state)

该方法用于获取这些值的文本含义:

  • requests.CONNECT
  • requests.HANDSHAKE
  • requests.SEND_HEADER
  • requests.SEND_BODY
  • requests.RECV_HEADER
  • requests.RECV_BODY
  • requests.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)

是相同的。

语法: 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,从调用者传递的 URL
  • method,请求方法,例如 POST
  • status_line,原始状态行(从远程接收)
  • status_codeHTTP 状态码
  • http_version,响应的 HTTP 版本,例如 HTTP/1.1
  • headers,一个 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 方法。

另请参阅

GitHub

您可以在 nginx-module-requests 的 GitHub 仓库 中找到此模块的其他配置提示和文档。