W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
實現(xiàn)一個最最簡單的數(shù)學計算:加、減、乘、除,給大家演示如何搭建簡單的 API Server。
按照前面幾章的寫法,先來看看加法、減法示例代碼:
worker_processes 1; #nginx worker 數(shù)量
error_log logs/error.log; #指定錯誤日志文件路徑
events {
worker_connections 1024;
}
http {
server {
listen 80;
# 加法
location /addition {
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.say(args.a + args.b)
}
}
# 減法
location /subtraction {
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.say(args.a - args.b)
}
}
# 乘法
location /multiplication {
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.say(args.a * args.b)
}
}
# 除法
location /division {
content_by_lua_block {
local args = ngx.req.get_uri_args()
ngx.say(args.a / args.b)
}
}
}
}
代碼寫多了一眼就可以看出來,這么簡單的加減乘除,居然寫了這么長,而且還要對每個 API 都寫一個 location ,作為有追求的人士,怎能容忍這種代碼風格?
基于這兩點要求,可以改成下面的版本,看上去有那么幾分模樣的樣子:
nginx.conf 內(nèi)容:
worker_processes 1; #nginx worker 數(shù)量
error_log logs/error.log; #指定錯誤日志文件路徑
events {
worker_connections 1024;
}
http {
# 設置默認 lua 搜索路徑,添加 lua 路徑
# 此處寫相對路徑時,對啟動 nginx 的路徑有要求,必須在 nginx 目錄下啟動,require 找不到
# comm.param 絕對路徑當然也沒問題,但是不可移植,因此應使用變量 $prefix 或
# ${prefix},OR 會替換為 nginx 的 prefix path。
# lua_package_path 'lua/?.lua;/blah/?.lua;;';
lua_package_path '$prefix/lua/?.lua;/blah/?.lua;;';
# 這里設置為 off,是為了避免每次修改之后都要重新 reload 的麻煩。
# 在生產(chǎn)環(huán)境上務必確保 lua_code_cache 設置成 on。
lua_code_cache off;
server {
listen 80;
# 在代碼路徑中使用nginx變量
# 注意: nginx var 的變量一定要謹慎,否則將會帶來非常大的風險
location ~ ^/api/([-_a-zA-Z0-9/]+) {
# 準入階段完成參數(shù)驗證
access_by_lua_file lua/access_check.lua;
#內(nèi)容生成階段
content_by_lua_file lua/$1.lua;
}
}
}
其他文件內(nèi)容:
--========== {$prefix}/lua/addition.lua
local args = ngx.req.get_uri_args()
ngx.say(args.a + args.b)
--========== {$prefix}/lua/subtraction.lua
local args = ngx.req.get_uri_args()
ngx.say(args.a - args.b)
--========== {$prefix}/lua/multiplication.lua
local args = ngx.req.get_uri_args()
ngx.say(args.a * args.b)
--========== {$prefix}/lua/division.lua
local args = ngx.req.get_uri_args()
ngx.say(args.a / args.b)
既然對外提供的是 API Server,作為一個服務端程序員,怎么可以容忍輸入?yún)?shù)不檢查呢?萬一對方送過來的不是數(shù)字或者為空,這些都要過濾掉嘛。參數(shù)檢查過濾的方法是統(tǒng)一,在這幾個 API 中如何共享這個方法呢?這時候就需要 Lua 模塊來完成了。
nginx.conf 內(nèi)容:
worker_processes 1; #nginx worker 數(shù)量
error_log logs/error.log; #指定錯誤日志文件路徑
events {
worker_connections 1024;
}
http {
server {
listen 80;
# 在代碼路徑中使用nginx變量
# 注意: nginx var 的變量一定要謹慎,否則將會帶來非常大的風險
location ~ ^/api/([-_a-zA-Z0-9/]+) {
access_by_lua_file lua/access_check.lua;
content_by_lua_file lua/$1.lua;
}
}
}
新增文件內(nèi)容:
--========== {$prefix}/lua/comm/param.lua
local _M = {}
-- 對輸入?yún)?shù)逐個進行校驗,只要有一個不是數(shù)字類型,則返回 false
function _M.is_number(...)
local arg = {...}
local num
for _,v in ipairs(arg) do
num = tonumber(v)
if nil == num then
return false
end
end
return true
end
return _M
--========== {$prefix}/lua/access_check.lua
local param= require("comm.param")
local args = ngx.req.get_uri_args()
if not args.a or not args.b or not param.is_number(args.a, args.b) then
ngx.exit(ngx.HTTP_BAD_REQUEST)
return
end
看看curl測試結果吧:
$ nginx curl '127.0.0.1:80/api/addition?a=1'
<html>
<head><title>400 Bad Request</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<hr><center>openresty/1.9.3.1</center>
</body>
</html>
$ nginx curl '127.0.0.1:80/api/addition?a=1&b=3'
4
基本是按照預期執(zhí)行的。參數(shù)不全、錯誤時,會提示400錯誤。正常處理,可以返回預期結果。
來整體看一下目前的目錄關系:
.
├── conf
│ ├── nginx.conf
├── logs
│ ├── error.log
│ └── nginx.pid
├── lua
│ ├── access_check.lua
│ ├── addition.lua
│ ├── subtraction.lua
│ ├── multiplication.lua
│ ├── division.lua
│ └── comm
│ └── param.lua
└── sbin
└── nginx
怎么樣,有點 magic 的味道不?其實你的接口越是規(guī)范,有固定規(guī)律可尋,那么 OpenResty 就總是很容易能找到適合你的位置。當然這里你也可以把 ?access_check.lua
? 內(nèi)容分別復制到加、減、乘、除實現(xiàn)的四個 Lua 文件中,肯定也是能用的。這里只是為了給大家提供更多的玩法,需要的時候可以有更多的選擇。
本章目的是搭建一個簡單API Server,記住這絕對不是終極版本。這里面還有很多需要進一步去考慮的地方,但是作為最基本的框架已經(jīng)有了。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: