Quick Lua Web Development Guide (7) - an efficient interface calls - httpc library

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-typewill 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-typewill 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, responsecode 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 classneed 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.

hcAnd httpchave the same API, but requires the use of different ways, such as call: hc:get, hc:post, hc:json, hc:file.

Once the hccall 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.luastarting one httpdof 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 httpdthe 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.8View 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 curlcommand-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, httpcthe library provides a called multi_requestmethod 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 httpclibrary's multi_requestapproach 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 curltools 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

Guess you like

Origin blog.csdn.net/weixin_34253539/article/details/93181015