lua web快速开发指南(7) - 高效的接口调用 - httpc库
httpc库基于cf框架都内部实现的socket编写的http client库.
httpc库内置SSL支持, 在不使用代理的情况下就可以请求第三方接口.
httpc支持header、args、body、timeout请求设置, 完美支持各种httpc调用方式.
API介绍
httpc库使用前需要手动导入httpc库: local httpc = require "httpc"
.
httpc.get(domain, HEADER, ARGS, TIMEOUT)
调用get方法将会对domain发起一次HTTP GET请求.
domain是一个符合URL定义规范的字符串;
HEADER是一个key-value数组, 一般用于添加自定义头部;
ARGS为请求参数的key-value数组, 对于GET方法将会自动格式化为:args[n][1]=args[n][2]&args[n+1][1]=args[n+1][2]
;
TIMEOUT为httpc请求的最大超时时间;
httpc.post(domain, HEADER, BODY, TIMEOUT)
调用post方法将会对domain发起一次HTTP POST请求, 此方法的content-type
会被设置为:application/x-www-form-urlencoded
.
domain是一个符合URL定义规范的字符串;
HEADER是一个key-value数组, 一般用于添加自定义头部; 不支持Content-Type与Content-Length设置;
BODY是一个key-value数组, 对于POST方法将会自动格式化为:body[n][1]=body[n][2]&body[n+1][1]=body[n+1][2]
;
TIMEOUT为httpc请求的最大超时时间;
httpc.json(domain, HEADER, JSON, TIMEOUT)
json方法将会对domain发起一次http POST请求. 此方法的content-type
会被设置为:application/json
.
HEADER是一个key-value数组, 一般用于添加自定义头部; 不支持Content-Type与Content-Length设置;
JSON必须是一个字符串类型;
TIMEOUT为httpc请求的最大超时时间;
httpc.file(domain, HEADER, FILES, TIMEOUT)
file方法将会对domain发起一次http POST请求.
HEADER是一个key-value数组, 一般用于添加自定义头部; 不支持Content-Type与Content-Length设置;
FILES是一个key-value数组, 每个item包含: name(名称), filename(文件名), file(文件内容), type(文件类型)等属性. 文件类型可选.
TIMEOUT为httpc请求的最大超时时间;
httpc 返回值
所有httpc请求接口均会有2个返回值: code
, response
. code为http协议状态码, response为回应body(字符串类型).
参数不正确, 连接被断开等其它错误, code将会为nil, response为错误信息.
“一次性HTTP请求”
什么是一次性httpc请求呢?
每次我们使用httpc库在请求第三方http接口的时候, 都会在接口返回后关闭连接. 这在日常使用中一边也没什么问题.
但是当我们需要多次请求同一个接口的时候, 每次请求完毕就关闭连接显然不是那么高效, 现在我们尝试使用一个http class对象来解决这个问题.
注意: httpc class对象不能对不同域名的接口使用同一个连接, 这会返回一个错误调用给使用者.
httpc库的class对象使用介绍
要使用httpc的class
需要导入httpc的class库, 导入方式为: local httpc = require "httpc.class"
.
当需要使用httpc发起请求之前, 需要先创建一个httpc的对象, 如: local hc = httpc:new {}
. httpc对象创建与初始化完毕后, 使用方式同上述API所示.
hc
与httpc
拥有相同的API, 但是需要使用不同的调用方式. 如: hc:get
、hc:post
、hc:json
、hc:file
.
一旦hc
使用完毕时, 需要显示的调用hc:close()
方法来关闭创建的httpc对象并销毁httpc的连接.
开始实践
现在, 让我们将上面学到的API使用方式运用到实践中.
1. 启动一个httpd库的web server
在main.lua
中启动一个httpd
的server.
local httpd = require "httpd"
local json = require "json"local app = httpd:new("httpd")app:listen("", 8080)app:run()
1. 增加一个API路由用于ip地址归属地查询
我们先利用httpd
库启动一个server服务, 并且对外提供IP归属地查询接口
app:api('/ip', function(content)local httpc = require "httpc"local args = content.argsif not args or not args['ip'] thenreturn json.encode({code = 400,msg = "错误的接口调用方式",data = json.null,})endlocal code, response = httpc.get("http://freeapi.ipip.net/"..args["ip"])if code ~= 200 thenreturn json.encode({code = 401,msg = "获取数据失败",data = json.null,})endreturn response
end)
现在代码已经完成! 让我们打开浏览器输入:http://localhost:8090/ip?ip=8.8.8.8
查看返回数据.
2. 查询多个IP地址的归属地
一个请求对应一次回是HTTP协议的本质! 但是我们经常会遇到批量请求的业务场景, 我们就以此来设计一个批量请求/返回的例子.
让我们假设客户端将会发送一次POST请求, body为json类型并且里面包含一个IP数组: ip_list = {1.1.1.1, 8.8.8.8, 114.114.114.114}.
服务端在接受到这个数组之后, 需要将这ip的归属地信息一次性返回给客户端.
app:api('/ips', function(content)local httpc = require "httpc.class"if not content.json thenreturn json.encode({code = 400,msg = "错误的调用参数",data = json.null,})endlocal args = json.decode(content.body)if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' thenreturn json.encode({code = 400,msg = "错误的参数类型",data = json.null,})endlocal hc = httpc:new {}local ret = { code = 200 , data = {}}for _, ip in ipairs(args['ip_list']) dolocal code, response = hc:get("http://freeapi.ipip.net/"..ip)ret['data'][#ret['data']+1] = json.decode(response)endhc:close()return json.encode(ret)
end)
由于普通浏览器POST无法发送json, 让我们使用curl
命令行工具进行测试:
curl -H "Content-Type: application/json" -X POST -d '{"ip_list":["1.1.1.1","8.8.8.8","114.114.114.114"]}' http://localhost:8090/ip
返回数据如下:
{"code":200,"data":[["CLOUDFLARE.COM","CLOUDFLARE.COM","","",""],["GOOGLE.COM","GOOGLE.COM","","","level3.com"],["114DNS.COM","114DNS.COM","","",""]]}
3. 持续优化.
上述例子似乎已经非常完美! 我们利用连接保持的方式进行了3次请求, 这样已经缩短了请求50%的连接消耗(TCP握手).
但是对于非常需要性能的我们来说: 每次请求需要等到上一个请求处理完毕后才能继续发起新的请求, 这样的方式显然还不足以满足我们.
这样的情况下, httpc
库提供了一个叫multi_request
的方法. 具体使用方法在这里.
这个方法可以让我们同时发送几十上百个请求来解决单个连接阻塞的问题.
4. 并发请求
现在, 让我使用httpc
库的multi_request
方法来并发请求多个接口, 减少连接阻塞带来的问题.
app:api('/ips_multi', function (content)local httpc = require "httpc"if not content.json thenreturn json.encode({code = 400,msg = "错误的调用参数",data = json.null,})endlocal args = json.decode(content.body)if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' thenreturn json.encode({code = 400,msg = "错误的参数类型",data = json.null,})endlocal requests = {}local responses = { code = 200, data = {}}for _, ip in ipairs(args["ip_list"]) dorequests[#requests+1] = {domain = "http://freeapi.ipip.net/"..ip,method = "get",}endlocal ok, ret = httpc.multi_request(requests)for _, res in ipairs(ret) doresponses['data'][#responses['data'] + 1] = resendreturn json.encode(responses)
end)
好的, 现在让我们再次使用curl
工具进行测试:
curl -H "Content-Type: application/json" -X POST -d '{"ip_list":["1.1.1.1","8.8.8.8","114.114.114.114"]}' http://localhost:8090/ips_multi
我们可以从cf的请求回应时间看到, 响应时间消耗再次降低了50%.
[candy@MacBookPro:~/Documents/core_framework] $ ./cfadmin
[2019/06/16 17:45:21] [INFO] httpd正在监听: 0.0.0.0:8090
[2019/06/16 17:45:21] [INFO] httpd正在运行Web Server服务...
[2019/06/16 17:45:23] - ::1 - ::1 - /ips_multi - POST - 200 - req_time: 0.140253/Sec
[2019/06/16 17:45:38] - ::1 - ::1 - /ips - POST - 200 - req_time: 0.288286/Sec
完整的代码
local httpd = require "httpd"
local httpc = require "httpc"
local json = require "json"local app = httpd:new("httpd")app:api('/ip', function(content)local httpc = require "httpc"local args = content.argsif not args or not args['ip'] thenreturn json.encode({code = 400,msg = "错误的接口调用方式",data = json.null,})endlocal code, response = httpc.get("http://freeapi.ipip.net/"..args["ip"])if code ~= 200 thenreturn json.encode({code = 401,msg = "获取数据失败",data = json.null,})endreturn response
end)app:api('/ips', function(content)local httpc = require "httpc.class"if not content.json thenreturn json.encode({code = 400,msg = "错误的调用参数",data = json.null,})endlocal args = json.decode(content.body)if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' thenreturn json.encode({code = 400,msg = "错误的参数类型",data = json.null,})endlocal hc = httpc:new {}local ret = { code = 200 , data = {}}for _, ip in ipairs(args['ip_list']) dolocal code, response = hc:get("http://freeapi.ipip.net/"..ip)ret['data'][#ret['data']+1] = json.decode(response)endhc:close()return json.encode(ret)
end)app:api('/ips_multi', function (content)local httpc = require "httpc"if not content.json thenreturn json.encode({code = 400,msg = "错误的调用参数",data = json.null,})endlocal args = json.decode(content.body)if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' thenreturn json.encode({code = 400,msg = "错误的参数类型",data = json.null,})endlocal requests = {}local responses = { code = 200, data = {}}for _, ip in ipairs(args["ip_list"]) dorequests[#requests+1] = {domain = "http://freeapi.ipip.net/"..ip,method = "get",}endlocal ok, ret = httpc.multi_request(requests)for _, res in ipairs(ret) doresponses['data'][#responses['data'] + 1] = resendreturn json.encode(responses)
end)app:listen("", 8090)app:run()
继续学习
下一章节我们将学习如何使用httpd库编写Websocket.
lua web快速开发指南(7) - 高效的接口调用 - httpc库相关推荐
- lua web快速开发指南(1) - 初识cf框架
作者: 水果糖的小铺子(CandyMi) cf是什么? cf全称为: CoreFramework. 一个基于Reactor事件驱动与协程的lua高性能网络框架, 目前主要面向HTTP Applicat ...
- Google Web App开发指南
http://www.html5rocks.com/webappfieldguide/case-studies/case-study-intro/ 第一章:什么是Web Apps? 很多人向我问起学习 ...
- Vue全家桶快速开发指南
Vue全家桶快速开发指南着手与项目 环境配置 安装npm 安装vuecli4.x 构建项目 图形化构建 命令行配置 代码目录 vue-router 定义组件 组件的作用 如何定义组件 在需要他显示的h ...
- Cordova跨平台Web App开发指南(安卓篇)
Cordova跨平台Web App开发指南(安卓篇) 打包ios包必须用苹果系统,没钱买IOS设备,这里只介绍Android平台打包 一.Cordova简介' 在进行Cordova开发之前, 先花点时 ...
- Oracle WebCenter 11g 快速开发指南--翻译(一)
第一章:开发者快速开发指南 作为一个开发者,如果你准备建立一个WebCenter Portal application ,你需要一个好的路线图,来指导你从什么地方开始,提供初始化的经验:本章首先解决开 ...
- 开放下载!《AliOS Things快速开发指南》
简介:<AliOS Things快速开发指南>手把手教你从环境准备到线上.线下开发调试,更有两大典型场景实践等你参与.你的物联网开发从这里开始!快来get新技能吧~ AliOS Thing ...
- Apache PDFbox快速开发指南
Apache PDFbox快速开发指南 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.介绍 Apache PDFbox是一个开源的.基于Java的. ...
- 基于WEB快速开发平台的轻量ERP
传统的企业系统更多是以电脑软件端的应用形式运行,但是随着信息技术的发展进步以及企业对系统应用需求的提升,基于B/S的网页版的系统受到越来越多企业的青睐,那么Web网页版ERP软件系统相较于电脑端软件有 ...
- DigWS 短消息和WapPush 快速开发指南-接口介绍
DigWS 短消息和WapPush 快速开发指南-接口介绍 SendSms:发送短消息 Parameter<?xml:namespace prefix = o /> Description ...
最新文章
- 一位数据科学家的私房工具清单
- 项目管理(6):备战pmp
- DISCUZ X3.0 积分增减以及记录
- mysql mycat 路由规则_Mycat水平拆分之十种分片规则
- struct对象可能分配在托管堆上吗
- [导入]十大经典误会
- VB.Net + asp.net的一个web系统,使用SQL2000数据库 现在运行时偶尔会出现一个奇怪现象,一个用户登录时,登录后的界面竟然是另一个用户...
- 组合索引怎么应该怎么选取引导列?
- tcpdf html 格式重叠,使用TCPDF进行HTML呈现(PHP)
- 如何获取ppt内的视频文件
- 1分钟让你的App 适配 锤子OneStep
- MySQL 核心知识点
- 012_SSS_ Improving Diffusion Model Efficiency Through Patching
- matlab 巴特沃斯滤波
- virustotal采集案例
- XTU 1242 Yada Number 巧妙打表
- 浅谈Qt和C++的关系
- java电商快递费收取_电商系统设计之运费模板(上)
- ssd测试软件cy,SSD检测几个小细节
- Pycharm:设置python脚本文件头