借助 nginx proxy 模块我们可以给 ngx_lua 很方便地实现非阻塞 HTTP 客户端功能,即使用一个被 proxy 模块处理的内部 location 作为 HTTP client stub,然后通过 ngx_lua 中的 location.capture 接口调用它访问外部 URL。当然为了能解析外部域名,还需要指定 nginx 的 resolver 地址以开启 proxy 模块的域名解析功能。
下面就是一个简单的网页编码转换网关的 nginx 配置(需要事先安装 lua-iconv模块):
Nginx 配置代码
- http
- {
- ...
- # 指定域名解析服务器地址
- resolver 127.0.0.1;
- ...
- server
- {
- ...
- # http client stub
- location /http_client
- {
- internal;
- proxy_pass $arg_url;
- }
- location /web_iconv
- {
- content_by_lua '
- local from, to, url = ngx.var.arg_f, ngx.var.arg_t, ngx.var.arg_u
- local capture = ngx.location.capture
- local print = ngx.print
- local iconv = require("iconv")
- local cd = iconv.new(to or "utf8", from or "gbk")
- local res = capture("/http_client?url=" .. url)
- local ostr, err = cd:iconv(res.body)
- print(ostr)
- ';
- }
- ...
- }
- ...
- }
测试一下吧:
- $ curl 'http://localhost/web_iconv?f=gbk&t=utf8&u=http://www.baidu.com/'
当然,由于 nginx proxy 模块仅支持 HTTP/1.0 协议,因此在负载很高的情况下(例如访问 REST API)效率并不高。后续我们将开发支持 HTTP/1.1 协议的代理模块,实现 keep-alive 和 pipelining 等 HTTP/1.1 高级特性,以便在 ngx_lua 中方便地进行高效率的外部 HTTP 协议访问。
Update: nginx proxy 模块在目标 url 不含路径时会默认使用父请求的路径,故在之前的例子里,如果 参数 u 是 http://www.baidu.com 而不是 http://www.baidu.com/,则 proxy 模块实际去请求的 url 将是 http://www.baidu.com/web_iconv?f=gbk&t=utf8&u=http://www.baidu.com ,显然这并非我们期望的结果。因此目前如果要借用 proxy 模块作为 http client,就必须显式指明目标 url 的路径。切记!
本文地址:http://www.92csz.com/56/1002.html如非注明则为本站原创文章,欢迎转载。转载请注明转载自:moon's blog
看不懂 😮