lua 服务器

这是为方便使用脚本语言LUA进行web应用开发准备的。

来看代码:

  1. #include <mongols/lua_server.hpp>
  2. int main(int, char**) {
  3. int port = 9090;
  4. const char* host = "127.0.0.1";
  5. mongols::lua_server
  6. server(host, port, 5000, 8096, 0/*2*/);
  7. server.set_root_path("html/lua");
  8. server.set_enable_bootstrap(true);
  9. server.run("html/lua/package/?.lua;", "html/lua/package/?.so;");
  10. }
  1. local echo = {}
  2. function echo.concat(...)
  3. local text=''
  4. for i,v in ipairs({...}) do
  5. text=text..tostring(v)
  6. end
  7. return text
  8. end
  9. return echo
  10. `
  1. local echo=require('echo')
  2. mongols_res:header('Content-Type','text/plain;charset=UTF-8')
  3. mongols_res:content(echo.concat('hello,','world'))
  4. 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,内含三个函数:

  • full_match
  • partial_match
  • match
    其具体用法可参考以下代码:
  1. mongols_res:header('Content-Type','text/plain;charset=UTF-8')
  2. if mongols_req:has_form('test') then
  3. local test=mongols_req:get_form('test')
  4. if mongols_regex.partial_match('^[0-9]+$',test) then
  5. mongols_res:content('int type: '..test)
  6. elseif mongols_regex.partial_match('^[a-zA-Z]+$',test) then
  7. mongols_res:content('string type: '..test)
  8. else
  9. local match=mongols_regex.match('(\\w+)[_:+-](\\w+)',test)
  10. if #match > 0 then
  11. local content=''
  12. for key,value in ipairs(match) do
  13. content =content .. 'part '..key ..' = '.. value..'\n'
  14. end
  15. mongols_res:content('match: \n'..content)
  16. else
  17. mongols_res:content('not match: '.. test)
  18. end
  19. end
  20. else
  21. mongols_res:content('not found test variable')
  22. end
  23. mongols_res:status(200)

为了方便json处理,我内置了一个基于jsoncpp的类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
    具体用法参考下例:
  1. local cjson=require('cjson')
  2. local j = mongols_json.new()
  3. local json_str=[[
  4. {
  5. "employees": [
  6. { "firstName":"John" , "lastName":"Doe" },
  7. { "firstName":"Anna" , "lastName":"Smith" },
  8. { "firstName":"Peter" , "lastName":"Jones" }
  9. ]
  10. }
  11. ]]
  12. j:parse_string(json_str)
  13. print(j:to_string())
  14. local employees=j:get('employees')
  15. local item=mongols_json.new()
  16. item:set('firstName','Hello')
  17. item:set('lastName','World')
  18. employees:append(item)
  19. if employees:is_array() then
  20. local size=employees:size()
  21. for i= 0,size-1 do
  22. local iter=employees:get(i)
  23. print(iter:get('firstName'):as_string()..' : ' ..iter:get('lastName'):as_string())
  24. end
  25. end
  26. j:set('employees',employees)
  27. j:set('node1','test')
  28. j:set('node2',true)
  29. j:set('node3',3.1415926)
  30. j:set('node4',100)
  31. print(j:to_string())
  32. local value = { true, { foo = "bar" } ,{1,2,3,'test',3.2}}
  33. local json_text = cjson.encode(value)
  34. print(json_text)
  35. local mj=mongols_json.new()
  36. mj:parse_string(json_text)
  37. print(mj:to_string())

mongols_json不认识Lua的表类型,但lua-cjson认识。所以我内置了lua-cjson。以后,还会内置一些好用常用的第三方插件。

单文件入口

单文件入口模式是web编程中常见的模式。默认情况下,lua_server没有开启对该模式的支持。欲开启此一支持,使用方法set_enable_bootstrap

example下有例子代码,可参考:

  1. --index.lua
  2. local echo=require('echo')
  3. local route=require('route'):get_instance()
  4. route:add({'GET'},'^/hello/([0-9a-zA-Z]+)/?$'
  5. ,function(req,res,param)
  6. res:content('hello,'..param[2])
  7. res:header('Content-Type','text/plain;charset=UTF-8')
  8. res:status(200)
  9. end)
  10. route:add({'GET'},'^/([0-9]+)/?$'
  11. ,function(req,res,param)
  12. res:content(param[2])
  13. res:header('Content-Type','text/plain;charset=UTF-8')
  14. res:status(200)
  15. end)
  16. route:add({'GET','POST','PUT'},'^/(\\w+)/?$'
  17. ,function(req,res,param)
  18. local text= echo.concat('uri: ',req:uri(),'\n','method: ',req:method(),'\n',param[2])
  19. res:content(text)
  20. res:header('Content-Type','text/plain;charset=UTF-8')
  21. res:status(200)
  22. end)
  23. route:run(mongols_req,mongols_res)

c/c++ 模块

lua_server支持直接向服务器注册c/c++函数和类。例子:

  1. class person {
  2. public:
  3. person() : name("Tom"), age(0) {
  4. }
  5. virtual~person() = default;
  6. person* set_name(const std::string& name) {
  7. this->name = name;
  8. return this;
  9. }
  10. person* set_age(unsigned int age) {
  11. this->age = age;
  12. return this;
  13. }
  14. const std::string& get_name() const{
  15. return this->name;
  16. }
  17. unsigned int get_age() {
  18. return this->age;
  19. }
  20. private:
  21. std::string name;
  22. unsigned int age;
  23. };
  24. class studest : public person {
  25. public:
  26. studest() : person() {
  27. }
  28. virtual~studest() = default;
  29. double get_score() {
  30. return this->score;
  31. }
  32. studest* set_score(double score) {
  33. this->score = score;
  34. return this;
  35. }
  36. private:
  37. double score;
  38. };
  39. //some code
  40. server.set_function(&mongols::sha1, "sha1");
  41. server.set_function(&mongols::md5, "md5");
  42. server.set_class(
  43. kaguya::UserdataMetatable<person>()
  44. .setConstructors < person()>()
  45. .addFunction("get_age", &person::get_age)
  46. .addFunction("get_name", &person::get_name)
  47. .addFunction("set_age", &person::set_age)
  48. .addFunction("set_name", &person::set_name)
  49. , "person");
  50. server.set_class(
  51. kaguya::UserdataMetatable<studest, person>()
  52. .setConstructors < studest()>()
  53. .addFunction("get_score", &studest::get_score)
  54. .addFunction("set_score", &studest::set_score)
  55. , "studest");
  1. local template = require "resty.template"
  2. local view=template.new('name: {{name}}\
  3. age: {{age}}\
  4. score: {{score}}\
  5. text:{{text}}\
  6. text_md5: {{md5}}\
  7. text_sha1: {{sha1}}')
  8. local text='hello,world'
  9. local s=studest.new()
  10. s:set_score(74.6):set_name("Jerry"):set_age(14)
  11. view.name=s:get_name()
  12. view.age=s:get_age()
  13. view.score=s:get_score()
  14. view.text=text
  15. view.md5=md5(text)
  16. view.sha1=sha1(text)
  17. mongols_res:header('Content-Type','text/plain;charset=UTF-8')
  18. mongols_res:content(tostring(view))
  19. mongols_res:status(200)

所以,无需写动态库扩展了。是不是太方便?

原文: https://mongols.hi-nginx.com/doc/lua.html