lua
优质
小牛编辑
135浏览
2023-12-01
这是为方便使用脚本语言LUA进行web应用开发准备的。
来看代码:
#include <mongols/lua_server.hpp>
int main(int, char**) {
int port = 9090;
const char* host = "127.0.0.1";
mongols::lua_server
server(host, port, 5000, 8096, 0);
server.set_root_path("html/lua");
server.set_enable_bootstrap(true);
server.run("html/lua/package/?.lua;", "html/lua/package/?.so;");
}
local echo = {}
function echo.concat(...)
local text=''
for i,v in ipairs({...}) do
text=text..tostring(v)
end
return text
end
return echo
`
local echo=require('echo')
mongols_res:header('Content-Type','text/plain;charset=UTF-8')
mongols_res:content(echo.concat('hello,','world'))
mongols_res:status(200)
API
mongols_req
- uri
- method
- client
- param
- user_agent
- has_header
- get_header
- has_form
- get_form
- has_session
- get_session
- has_cookie
- get_cookie
- has_cache
- get_cache
mongols_res
- status
- content
- header
- session
- cache
其他
为了方便,我还在lua引擎中嵌入了一个可用于正则计算的表:mongols_regex
,内含两个函数:
- match
- match_find
其具体用法可参考以下代码:
mongols_res:header('Content-Type','text/plain;charset=UTF-8')
if mongols_req:has_form('test') then
local test=mongols_req:get_form('test')
if mongols_regex.partial_match('^[0-9]+$',test) then
mongols_res:content('int type: '..test)
elseif mongols_regex.partial_match('^[a-zA-Z]+$',test) then
mongols_res:content('string type: '..test)
else
local match=mongols_regex.match('(\\w+)[_:+-](\\w+)',test)
if #match > 0 then
local content=''
for key,value in ipairs(match) do
content =content .. 'part '..key ..' = '.. value..'\n'
end
mongols_res:content('match: \n'..content)
else
mongols_res:content('not match: '.. test)
end
end
else
mongols_res:content('not found test variable')
end
mongols_res:status(200)
为了方便json处理,我内置了一个基于json.hpp的类mongols_json,API列表如下:
- set
- get
- append
- parse_string
- parse_file
- as_xxx
- string
- bool
- double
- long
- is_xxx
- string
- bool
- double
- long
- object
- array
- size
- to_string
具体用法参考下例:
local cjson=require('cjson')
local j = mongols_json.new()
local json_str=[[
{
"employees": [
{ "firstName":"John" , "lastName":"Doe" },
{ "firstName":"Anna" , "lastName":"Smith" },
{ "firstName":"Peter" , "lastName":"Jones" }
]
}
]]
j:parse_string(json_str)
print(j:to_string())
local employees=j:get('employees')
local item=mongols_json.new()
item:set('firstName','Hello')
item:set('lastName','World')
employees:append(item)
if employees:is_array() then
local size=employees:size()
for i= 0,size-1 do
local iter=employees:get(i)
print(iter:get('firstName'):as_string()..' : ' ..iter:get('lastName'):as_string())
end
end
j:set('employees',employees)
j:set('node1','test')
j:set('node2',true)
j:set('node3',3.1415926)
j:set('node4',100)
print(j:to_string())
local value = { true, { foo = "bar" } ,{1,2,3,'test',3.2}}
local json_text = cjson.encode(value)
print(json_text)
local mj=mongols_json.new()
mj:parse_string(json_text)
print(mj:to_string())
mongols_json不认识Lua的表类型,但lua-cjson认识。所以我内置了lua-cjson。以后,还会内置一些好用常用的第三方插件。
已内置的第三方插件包括:cjson和lfs。
此外,我还内置了一个tcp客户端类mongols_tcp_client
,支持openssl。其api列表如下:
- ok
- send
- recv
具体用法可参考:
mongols_res:header('Content-Type','text/plain;charset=UTF-8')
mongols_res:status(200)
local host="www.baidu.com"
local port=443
local enable_ssl =true
local cli=mongols_tcp_client.new(host,port,enable_ssl)
local req="GET / HTTP/1.1\r\n\r\n"
if cli:ok() then
if cli:send(req) then
mongols_res:content(cli:recv(8096))
else
mongols_res:content("send failed.")
end
else
mongols_res:content("connection failed.")
end
单文件入口
单文件入口模式是web编程中常见的模式。默认情况下,lua_server没有开启对该模式的支持。欲开启此一支持,使用方法set_enable_bootstrap
。
example
下有例子代码,可参考:
--index.lua
local echo=require('echo')
local route=require('route'):get_instance()
route:add({'GET'},'^/hello/([0-9a-zA-Z]+)/?$'
,function(req,res,param)
res:content('hello,'..param[2])
res:header('Content-Type','text/plain;charset=UTF-8')
res:status(200)
end)
route:add({'GET'},'^/([0-9]+)/?$'
,function(req,res,param)
res:content(param[2])
res:header('Content-Type','text/plain;charset=UTF-8')
res:status(200)
end)
route:add({'GET','POST','PUT'},'^/(\\w+)/?$'
,function(req,res,param)
local text= echo.concat('uri: ',req:uri(),'\n','method: ',req:method(),'\n',param[2])
res:content(text)
res:header('Content-Type','text/plain;charset=UTF-8')
res:status(200)
end)
route:run(mongols_req,mongols_res)
c/c++ 模块
lua_server支持直接向服务器注册c/c++函数和类。例子:
class person {
public:
person() : name("Tom"), age(0) {
}
virtual~person() = default;
person* set_name(const std::string& name) {
this->name = name;
return this;
}
person* set_age(unsigned int age) {
this->age = age;
return this;
}
const std::string& get_name() const{
return this->name;
}
unsigned int get_age() {
return this->age;
}
private:
std::string name;
unsigned int age;
};
class studest : public person {
public:
studest() : person() {
}
virtual~studest() = default;
double get_score() {
return this->score;
}
studest* set_score(double score) {
this->score = score;
return this;
}
private:
double score;
};
//some code
server.set_function(&mongols::sha1, "sha1");
server.set_function(&mongols::md5, "md5");
server.set_class(
kaguya::UserdataMetatable<person>()
.setConstructors < person()>()
.addFunction("get_age", &person::get_age)
.addFunction("get_name", &person::get_name)
.addFunction("set_age", &person::set_age)
.addFunction("set_name", &person::set_name)
, "person");
server.set_class(
kaguya::UserdataMetatable<studest, person>()
.setConstructors < studest()>()
.addFunction("get_score", &studest::get_score)
.addFunction("set_score", &studest::set_score)
, "studest");
local template = require "resty.template"
local view=template.new('name: {{name}}\
age: {{age}}\
score: {{score}}\
text:{{text}}\
text_md5: {{md5}}\
text_sha1: {{sha1}}')
local text='hello,world'
local s=studest.new()
s:set_score(74.6):set_name("Jerry"):set_age(14)
view.name=s:get_name()
view.age=s:get_age()
view.score=s:get_score()
view.text=text
view.md5=md5(text)
view.sha1=sha1(text)
mongols_res:header('Content-Type','text/plain;charset=UTF-8')
mongols_res:content(tostring(view))
mongols_res:status(200)
所以,无需写动态库扩展了。是不是太方便?