openresty开发系列30--openresty中使用http模块
OpenResty默认没有提供Http客户端,需要使用第三方提供的插件 我们可以从github上搜索相应的客户端,比如https://github.com/pintsized/lua-resty-http 安装方法:将 lua-resty-http/lib/resty/ 目录下的 http.lua 和 http_headers.lua 两个文件拷贝到 /usr/local/openresty/lualib/resty 目录下即可 (假设 OpenResty 安装目录为 /usr/local/openresty) local res, err = httpc:request_uri(uri, { method = "POST/GET", ---请求方式 query = str, ---get方式传参数 body = str, ---post方式传参数 path = "url" ----路径 headers = { ---header参数 ["Content-Type"] = "application/json", } }) 示例:编写模拟请求天猫的查询 --引入http模块 local http = require("resty.http") --创建http客户端实例 local httpc = http:new() local resp,err = httpc:request_uri("https://list.tmall.com", { method = "GET", ---请求方式 --path="/search_product.htm?q=ipone", query="q=iphone", ---get方式传参数 body="name='jack'&age=18", ---post方式传参数 path="/search_product.htm", ----路径 ---header参数 headers = {["User-Agent"]="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"} }) if not resp then ngx.say("request error:",err) return end --获取状态码 ngx.status = resp.status --获取响应信息 --响应头中的Transfer-Encoding和Connection可以忽略,因为这个数据是当前server输出的。 --获取遍历返回的头信息 for k, v in pairs(resp.headers) do if k ~= "Transfer-Encoding" and k ~= "Connection" then ngx.header[k] =v end if type(v) == "table" then ngx.log(ngx.WARN,"table:"..k, ": ", table.concat(v, ", ")) else ngx.log(ngx.WARN,"one:"..k, ": ", v) end end ngx.say("end") --响应体 ngx.say(resp.body) httpc:close() httpc:close() # 后台日志 # /usr/local/openresty/nginx]# tail -f logs/debug.log 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:ufe-result: A6, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Date: Fri, 23 Aug 2019 09:58:04 GMT, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Location: https://login.taobao.com/jump?target=https%3A%2F%2Flist.tmall.com%2Fsearch_product.htm%3Ftbpm%3D1%26q%3Diphone, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Connection: keep-alive, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:EagleEye-TraceId: 0bfa16f315665542845385751e42fa, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Strict-Transport-Security: max-age=0, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Content-Length: 0, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Timing-Allow-Origin: *, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164" 2019/08/23 17:58:04 [warn] 25373#0: *131 [lua] testhttp02.lua:32: one:Server: Tengine/Aserver, client: 192.168.10.164, server: www.server1.com, request: "GET /testhttp02 HTTP/1.1", host: "192.168.10.164"
------------------------------------------------------- 发现报错 request error :no resolver defined to resolve "list.tmall.com" 此错误是因为要配置DNS解析器resolver 8.8.8.8,否则域名是无法解析的。 在nginx.conf配置文件中 http模块加上resolver 8.8.8.8; Google提供的免费DNS服务器的IP地址 配置好后,重启nginx --------------------------------------------------------- 访问https错误,因为我们访问的https,需要配置ssl证书 在nginx配置文件中,server虚拟主机模块设置 lua_ssl_verify_depth 2; lua_ssl_trusted_certificate "/etc/ssl/certs/ca-bundle.crt"; -------------------------------------------------------- http模块应用场景很多,这里只简单介绍了一下http模块的使用 还有很多openresty模块,可以参考 https://github.com/bungle/awesome-resty 以suning.com为例: local http = require("resty.http") --创建http客户端实例 local httpc = http:new() local resp,err = httpc:request_uri("http://issm.suning.com", { method = "GET", path="/productDetail_P11271.htm", headers = {["User-Agent"]="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"} }) if not resp then ngx.say("request error:",err) return end --获取状态码 ngx.status = resp.status --获取响应信息 --响应头中的Transfer-Encoding和Connection可以忽略,因为这个数据是当前server输出的。 for k,v in pairs(resp.headers) do if k ~= "Transfer-Encoding" and k ~= "Connection" then ngx.header[k] =v end end --响应体 ngx.say(resp.body) httpc:close()
配置示例
# cat /usr/local/openresty/nginx/conf/nginx.conf worker_processes 4; #pid logs/nginx.pid; events { worker_connections 10240; } http { include mime.types; default_type text/html; sendfile on; keepalive_timeout 65; resolver 8.8.8.8; server { listen 80; server_name www.server1.com; lua_ssl_verify_depth 2; lua_ssl_trusted_certificate "/etc/ssl/certs/ca-bundle.crt"; location /tmall { access_by_lua_file /usr/local/lua/tmall.lua; } location / { root html; index index.html index.htm; } error_page 500 502 503 504 /50x.html; location = /50x.html { root html; } } }
lua脚本
# cat /usr/local/lua/tmall.lua --引入http模块 local http = require("resty.http") --创建http客户端实例 local httpc = http:new() local resp,err = httpc:request_uri("https://list.tmall.com", { method = "GET", ---请求方式 --path="/search_product.htm?q=ipone", query="q=iphone", ---get方式传参数 body="name='jack'&age=18", ---post方式传参数 path="/search_product.htm", ----路径 ---header参数 headers = {["User-Agent"]="Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36"} }) if not resp then ngx.say("request error:",err) return end --获取状态码 ngx.status = resp.status --获取响应信息 --响应头中的Transfer-Encoding和Connection可以忽略,因为这个数据是当前server输出的。 --获取遍历返回的头信息 for k, v in pairs(resp.headers) do if k ~= "Transfer-Encoding" and k ~= "Connection" then ngx.header[k] =v end if type(v) == "table" then ngx.log(ngx.WARN,"table:"..k, ": ", table.concat(v, ", ")) else ngx.log(ngx.WARN,"one:"..k, ": ", v) end end ngx.say("end") --响应体 ngx.say(resp.body) httpc:close()