lua-resty-requests

OpenResty 的另一个 HTTP 库

$ opm get tokers/lua-resty-requests

名称

lua-resty-requests - OpenResty 的另一个 HTTP 库。

!构建状态

    resty -e 'print(require "resty.requests".get("https://github.com", { stream = false}).content)'

状态

此 Lua 模块现在可以被认为是生产就绪的。

注意,自从v0.7.1版本发布以来,此模块开始使用 lua-resty-socket,以便在不可 yield 的阶段工作,但仍然需要付出更多努力,因此**不要**在initinit_worker阶段(或其他不可 yield 的阶段)使用它。

特性

  • HTTP/1.0、HTTP/1.1 和 HTTP/2(WIP)。

  • SSL/TLS 支持。

  • 分块数据支持。

  • 方便的接口以支持 json、授权等功能。

  • 流接口以读取主体。

  • HTTP/HTTPS 代理。

  • 延迟指标。

  • 会话支持。

概要

    local requests = require "resty.requests"
    
    -- example 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
    
    -- read all body
    local body = r:body()
    ngx.print(body)
    
    -- or you can iterate the response 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
    
    -- you can also use the non-stream mode
    -- 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)

安装

    $ luarocks install lua-resty-requests
    $ opm get tokers/lua-resty-requests
  • 手动

只需调整lua_package_pathLUA_PATH环境变量,以添加此 Lua 模块的安装路径

    /path/to/lua-resty-requests/lib/resty/?.lua;

方法

request

语法: local r, err = requests.request(method, url, opts?)

这是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, "during requests process")
        end
    }

考虑到便利性,还有一些“捷径”选项

  • auth,用于执行基本 HTTP 授权,接受一个包含userpass的 Lua 表,例如,当auth

    {
        user = "alex",
        pass = "123456"
    }

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

  • json,接受一个 Lua 表,它将被cjson序列化,序列化后的数据将作为请求主体发送,并且当同时指定jsonbody时,它具有优先级。

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

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

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

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

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

发送 HTTP GET 请求。这与以下相同

    requests.request("GET", url, opts)

语法: local r, err = requests.head(url, opts?)

发送 HTTP HEAD 请求。这与以下相同

    requests.request("HEAD", url, opts)

post

语法: local r, err = requests.post(url, opts?)

发送 HTTP POST 请求。这与以下相同

    requests.request("POST", url, opts)

put

语法: local r, err = requests.put(url, opts?)

发送 HTTP PUT 请求。这与以下相同

    requests.request("PUT", url, opts)

delete

语法: local r, err = requests.delete(url, opts?)

发送 HTTP DELETE 请求。这与以下相同

    requests.request("DELETE", url, opts)

options

语法: local r, err = requests.options(url, opts?)

发送 HTTP OPTIONS 请求。这与以下相同

    requests.request("OPTIONS", url, opts)

patch

语法: local r, err = requests.patch(url, opts?)

发送 HTTP PATCH 请求。这与以下相同

    requests.request("PATCH", url, opts)

响应对象

requests.get和其他方法将返回一个响应对象r,它可以通过以下方法和变量进行操作

  • url,从调用者传入的 URL

  • method,请求方法,例如POST

  • status_line,原始状态行(从远程接收)

  • status_code,HTTP 状态码

  • 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 3 路握手的时间成本;

    • 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 方法。

待办事项

  • 其他有趣的功能...

作者

Alex Zhang (张超) [email protected],UPYUN Inc.

版权和许可

该捆绑包本身是在 2 条款 BSD 许可下获得许可的。

版权所有 (c) 2017-2019,Alex Zhang。

本模块是在 BSD 许可条款下获得许可的。

允许以源代码和二进制形式重新分发和使用本软件,无论是否修改,只要符合以下条件

重新分发源代码必须保留上述版权声明、此条件列表和以下免责声明。以二进制形式重新分发必须在随分发提供的文档和/或其他材料中复制上述版权声明、此条件列表和以下免责声明。本软件由版权所有者和贡献者“按原样”提供,任何明示或暗示的保证,包括但不限于适销性保证和特定用途适用性保证均被排除在外。在任何情况下,版权所有者或贡献者均不对因使用本软件而造成的任何直接、间接、偶发、特殊、示范性或后果性损害(包括但不限于替代商品或服务的采购;使用、数据或利润损失;或业务中断)负责,无论其责任基础如何,无论是合同、严格责任或侵权行为(包括疏忽或其他原因),即使已告知有可能发生此类损害。

另请参阅

  • upyun-resty: https://github.com/upyun/upyun-resty

  • httpipe: https://github.com/timebug/lua-resty-httpipe

作者

Alex Zhang(张超) [email protected],UPYUN Inc.

许可证

2bsd

版本