httpc library based cf frameworks implemented internally prepared socket http client library.
httpc built-in SSL support libraries, without the use of agents can request a third-party interface.
httpc support header, args, body, timeout request is set, the perfect support for a variety of httpc invocation.
API Introduction
before httpc library need to manually import httpc library: local httpc = require "httpc"
.
httpc.get(domain, HEADER, ARGS, TIMEOUT)
Call the get method for domain will launch a HTTP GET request.
in line with the definition of a domain is the URL specification string;
HEADER array is a key-value, typically to add a custom header;
ARGS request parameters for the key-value array for the GET method will automatically be formatted as: args[n][1]=args[n][2]&args[n+1][1]=args[n+1][2]
;
Httpc maximum timeout TIMEOUT request;
httpc.post(domain, HEADER, BODY, TIMEOUT)
Call the post method for domain will launch a HTTP POST request, this method content-type
will be set to: application/x-www-form-urlencoded
.
in line with the definition of a domain is the URL specification string;
HEADER array is a key-value, typically to add a custom header; Content-Type is not supported and disposed Content-Length;
BODY is a key-value array for the POST method will be automatically formatted as: body[n][1]=body[n][2]&body[n+1][1]=body[n+1][2]
;
Httpc maximum timeout TIMEOUT request;
httpc.json(domain, HEADER, JSON, TIMEOUT)
json method for domain will launch a http POST request method. content-type
will be set to: application/json
.
HEADER array is a key-value, typically to add a custom header; Content-Type is not supported and disposed Content-Length;
JSON must be a string type;
Httpc maximum timeout TIMEOUT request;
httpc.file(domain, HEADER, FILES, TIMEOUT)
Methods for domain file will launch a http POST request.
HEADER array is a key-value, typically to add a custom header; Content-Type is not supported and disposed Content-Length;
FILES is a key-value array, each item includes:. Name (name), filename (file name), file (file contents), type (file type) Optional attributes such as file type.
Httpc maximum timeout TIMEOUT request;
httpc return value
All interfaces are httpc requests will return two values: code
, response
code for the http protocol status code, response body response (string type).
Parameter is incorrect, the connection is broken and other errors, as the code will be nil, response to the error message.
"Disposable HTTP request"
What is a one-time httpc request it?
Every time we use the library when httpc http request third-party interface, the interface will close the connection after return. This side is also no problem in daily use.
But when we need to repeatedly request the same interface, complete each request to close the connection is clearly not as efficient, and now we try to use a http class objects to solve this problem.
Note: httpc class object can not interface with a different domain name of the connection, which will return an error to the calling user.
httpc library class object using introduced
To use httpc the class
need to import httpc of class libraries, import way: local httpc = require "httpc.class"
.
Before initiation request httpc required, the need to create a httpc objects, such as: local hc = httpc:new {}
. Httpc After completion of the object is created and initialized, using the same manner as shown in the above-described API.
hc
And httpc
have the same API, but requires the use of different ways, such as call: hc:get
, hc:post
, hc:json
, hc:file
.
Once the hc
call is completed when used, you need to show the hc:close()
way to close the httpc create and destroy objects in connection httpc.
Start practice
Now, let us learn to use the above API to use in practice.
1. Start a library of httpd web server
In main.lua
starting one httpd
of the server.
local httpd = require "httpd"
local json = require "json"
local app = httpd:new("httpd")
app:listen("", 8080)
app:run()
复制代码
1. Add a routing API ip address for attribution to inquiries
Let's use httpd
the library to start a server service, and provide external IP attribution to query interface
app:api('/ip', function(content)
local httpc = require "httpc"
local args = content.args
if not args or not args['ip'] then
return json.encode({
code = 400,
msg = "错误的接口调用方式",
data = json.null,
})
end
local code, response = httpc.get("http://freeapi.ipip.net/"..args["ip"])
if code ~= 200 then
return json.encode({
code = 401,
msg = "获取数据失败",
data = json.null,
})
end
return response
end)
复制代码
Now let's code has been completed open the browser, type:! http://localhost:8090/ip?ip=8.8.8.8
View return data.
2. Query multiple IP addresses attribution
A request corresponds to a return is the nature of the HTTP protocol! But we often encounter business scenarios batch requests, we used this example to design a batch request / return.
Let us assume that the client will send a POST request, body type and which contains as a json array IP: ip_list = {1.1.1.1, 8.8.8.8, 114.114.114.114}.
After the server receives this array, the need for these ip-time location information is returned to the client.
app:api('/ips', function(content)
local httpc = require "httpc.class"
if not content.json then
return json.encode({
code = 400,
msg = "错误的调用参数",
data = json.null,
})
end
local args = json.decode(content.body)
if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' then
return json.encode({
code = 400,
msg = "错误的参数类型",
data = json.null,
})
end
local hc = httpc:new {}
local ret = { code = 200 , data = {}}
for _, ip in ipairs(args['ip_list']) do
local code, response = hc:get("http://freeapi.ipip.net/"..ip)
ret['data'][#ret['data']+1] = json.decode(response)
end
return json.encode(ret)
end)
复制代码
Since ordinary browser POST can not send json, let's use the curl
command-line tools for testing:
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
复制代码
Return data as follows:
{"code":200,"data":[["CLOUDFLARE.COM","CLOUDFLARE.COM","","",""],["GOOGLE.COM","GOOGLE.COM","","","level3.com"],["114DNS.COM","114DNS.COM","","",""]]}
复制代码
3. continuous optimization.
The above example seems to have been perfect! We used to keep connected were three requests, which have reduced consumption of connection (TCP handshake) requested 50%.
But for us it is highly desirable properties: Each request needs to wait until after a request is processed in order to continue to initiate new request, this approach is clearly not enough to satisfy us.
Under such circumstances, httpc
the library provides a called multi_request
method of particular use in here .
This approach allows us to simultaneously send dozens of hundreds of requests to solve the problem of blocking a single connection.
4. Concurrent Request
Now, let me use the httpc
library's multi_request
approach to interface to multiple concurrent requests, to reduce the problems caused by blocking the connection.
app:api('/ips_multi', function (content)
local httpc = require "httpc"
if not content.json then
return json.encode({
code = 400,
msg = "错误的调用参数",
data = json.null,
})
end
local args = json.decode(content.body)
if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' then
return json.encode({
code = 400,
msg = "错误的参数类型",
data = json.null,
})
end
local requests = {}
local responses = { code = 200, data = {}}
for _, ip in ipairs(args["ip_list"]) do
requests[#requests+1] = {
domain = "http://freeapi.ipip.net/"..ip,
method = "get",
}
end
local ok, ret = httpc.multi_request(requests)
for _, res in ipairs(ret) do
responses['data'][#responses['data'] + 1] = res
end
return json.encode(responses)
end)
复制代码
OK, now let's re-use curl
tools for testing:
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
复制代码
We can see from the time cf response to a request, the response time consuming again reduced by 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
复制代码
The full code
local httpd = require "httpd"
local json = require "json"
local app = httpd:new("httpd")
app:api('/ip', function(content)
local httpc = require "httpc"
local args = content.args
if not args or not args['ip'] then
return json.encode({
code = 400,
msg = "错误的接口调用方式",
data = json.null,
})
end
local code, response = httpc.get("http://freeapi.ipip.net/"..args["ip"])
if code ~= 200 then
return json.encode({
code = 401,
msg = "获取数据失败",
data = json.null,
})
end
return response
end)
app:api('/ips', function(content)
local httpc = require "httpc.class"
if not content.json then
return json.encode({
code = 400,
msg = "错误的调用参数",
data = json.null,
})
end
local args = json.decode(content.body)
if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' then
return json.encode({
code = 400,
msg = "错误的参数类型",
data = json.null,
})
end
local hc = httpc:new {}
local ret = { code = 200 , data = {}}
for _, ip in ipairs(args['ip_list']) do
local code, response = hc:get("http://freeapi.ipip.net/"..ip)
ret['data'][#ret['data']+1] = json.decode(response)
end
return json.encode(ret)
end)
app:api('/ips_multi', function (content)
local httpc = require "httpc"
if not content.json then
return json.encode({
code = 400,
msg = "错误的调用参数",
data = json.null,
})
end
local args = json.decode(content.body)
if type(args) ~= 'table' or type(args['ip_list']) ~= 'table' then
return json.encode({
code = 400,
msg = "错误的参数类型",
data = json.null,
})
end
local requests = {}
local responses = { code = 200, data = {}}
for _, ip in ipairs(args["ip_list"]) do
requests[#requests+1] = {
domain = "http://freeapi.ipip.net/"..ip,
method = "get",
}
end
local ok, ret = httpc.multi_request(requests)
for _, res in ipairs(ret) do
responses['data'][#responses['data'] + 1] = res
end
return json.encode(responses)
end)
app:listen("", 8090)
app:run()
复制代码
Continue studying
The next chapter we will learn how to use httpd library written Websocket.
Reproduced in: https: //juejin.im/post/5d09cc88f265da1ba56b220d