# OmniWeb **Repository Path**: tangulak/OmniWeb ## Basic Information - **Project Name**: OmniWeb - **Description**: 立志做一个小而精的LUA HTTP服务器 - **Primary Language**: Lua - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 14 - **Created**: 2020-07-24 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README OmniWeb ---- LUA WEB服务器 ## 特性 > 1. 小而快将是本软件的始终目标 > 2. 集成GNU libmicrohttpd(0.9.59), LuaJIT(2.1.0b3), lua-CJson, lua-resty-template, tinyxml2 > 3. 支持定时器和每日定时任务 ## 示例项目 [Team - 轻量级项目任务管理系统](https://gitee.com/love_linger/Team) **Team 2.0之后使用Go重写了!!!如需查看使用方法,请切换到Team 1.x版本** ## 配置说明 配置文件**omni.ini**: ```ini ; 基本配置 [main] port=80 ; HTTP监听端口,默认80 expire=900000 ; Storage存储数据的默认过期时间(毫秒),默认15分 verbose=no ; 是否显示详细访问日志(yes|no),默认no use_session=yes ; 是否启用session, 默认no #script_entry=script/app.lua ; 入口文件 #scheduler_script=scripts/scheduler.lua ; 时间计划加载脚本,不设置时不启用时间计划 ; 自定义错误页,只支持静态页面 [error_pages] #404=scripts/view/404.html #405=scripts/view/405.html ; 可下载文件目录列表,alias=path [shared_dirs] #upload=uploads ; 访问/upload/1.txt指向./uploads/1.txt #some=E:\1 ; 访问/some/1.txt指向E:\1\1.txt ; 其他自定义配置 ``` > [注] 配置文件的内容会写Lua全局Table`config`中。如`config.dirs.controller` ## 部署目录 参考`bin`目录 somewhere -- 用户指定文件夹 | |-- omni/omni.exe -- 发行版中下载编译好的可执行文件 |-- omni.ini -- 配置文件 | |-- www -- 静态文件(css,images,fonts,js等)存放目录 | |-- favicon.ico -- 网站favicon图标 | |-- css -- CSS | |-- js -- JS | |-- fonts -- Fonts | |-- images -- 图片 | |-- scripts -- 代码及模板存放目录 |-- app.lua -- 必需,路由定义(请求分发) |-- controller -- 控制器 |-- model -- 数据模型 |-- vendor -- LuaJIT第三方插件(推荐从luapower中找) |-- view -- 视图模板存放 ## 路由说明 1. 支持正则(Posix Regex版)路由 2. 接口 | **方法** | **说明** | | --- | --- | | router:get(filter, proc) | GET路由 | | router:post(filter, proc) | POST路由 | | router:any(filter, proc) | 无限制路由 | 3. 示例 ```lua -- 主页 router:get('^/$', function(req, rsp) custom_router(default_ctrl, default_action, req, rsp); end); -- MVC router:any('^/([A-Za-z][A-Za-z0-9_/]*)/([A-Za-z][A-Za-z0-9_]*)$', function(req, rsp, controller, action) custom_router(controller, action, req, rsp); end); -- MVC(默认ACTION) router:any('^/([A-Za-z][A-Za-z0-9_]*)$', function(req, rsp, controller) custom_router(controller, default_action, req, rsp); end); -- MVC(默认ACTION,多层controller) router:any('^/([A-Za-z][A-Za-z0-9_/]*)/$', function(req, rsp, controller) custom_router(controller, default_action, req, rsp); end); ``` ## Request表(路由处理函数proc的第一个参数) | **属性** | **说明** | | --- | --- | | url | 访问的URL,如/home/index?aa=1中/home/index为url | | method | HTTP method。GET/POST/PUT/DELETE | | remote | 客户端ip | | cookie | Cookie表 | | get | QueryString参数表。如req.get.uid等 | | post | POST请求的参数表 | | file | 上传文件的真实路径表,如:req.file.kk为FORM中name=kk的FILE存放路径 | > 【注】 > > 上传的文件会在请求结束后自行删除,如需保存,请使用os.cp(from, to)复制到其他目录 ## Response类(路由处理函数proc的第二个参数) | **方法** | **说明** | | --- | --- | | header(k, v) | 设置回应的HTTP头,如:rsp:header('Content-type', 'text/plain') | | echo(str) | 写入内容。如:rsp:echo('ssss') | | html(view[, data [, is_plain]]) | 写入内容并设置Content-type为text/html | | json(table[, set_header]) | 写入Table为JSON内容,可选设置Content-type为application/json | | file(path) | 发送文件到客户端,非强制下载 | | error(code) | 发送错误信息。需要自行控制return | | redirect(url) | 发送跳转。需要自行控制return | | cookie(k, v[, expire[, path]]) | COOKIE设置 | ## Session 1. 在omni.ini中配置`main.use_session=yes`后session才可用 2. session为全局的table,更改后自动保存 3. 清空session只需要执行`session = {}` ## 视图 1. 语法请自行参考lua-resty-template。 2. 渲染调用接口为rsp:html(view, data, is_plain)。 | **参数** | **是否必填** | **说明** | | --- | --- | --- | | view | 是 | HTML文本或html文件路径 | | data | 否 | 生成动态页面需要的参数 | | is_plain | 否 | view参数是否是HTML文本 | ## 全局存储 > 使用`string => string`的key-value存储 > 由于每个HTTP会话使用独立的Lua VM,因此需要存放的全局数据,请使用storage | **方法** | **说明** | | --- | --- | | storage.get(k) | 取一个存放的value。不存在或过期时返回nil。 | | storage.set(k, v, never_expire) | 缓存一个string。 | ## 时间计划 支持全局定时器和每日时间计划。使用方法示例: 1) 在配置文件中声明时间计划脚本 ```ini [main] scheduler_script=scripts/scheduler.lua ``` 2) 编写时间计划 ```lua -- scripts/scheduler.lua文件内容 -- 开启一个每天12点执行的任务 scheduler.daily(12, 0, 0, function() local users = require(config.dirs.model .. 'user'); local find = users:query[[SELECT * FROM `users`]]; ... end); -- 开启一个每隔12秒执行的任务 scheduler.timer(12000, function() print('hehe') end, true); ``` **时间计划的接口** | **函数** | **返回值** | **说明** | | --- | --- | --- | | scheduler.timer(delay, func, is_loop) | integer | 创建一个timer,返回时间计划的ID,delay的单位为毫秒 | | scheduler.daily(hour, minute, second, func) | integer | 创建一个每天执行的任务,返回时间计划的ID | | scheduler.is_valid(id) | bool | 判断一个时间计划是否存在 | | scheduler.remain(id) | number | 判断一个时间计划距离触发还有多少毫秒 | | scheduler.cancel(id) | - | 取消一个时间计划 | ## Lua层的C++接口 扩展os库 | **函数** | **返回值** | **说明** | | --- | --- | --- | | os.exists(filepath) | bool | 文件或目录是否存在 | | os.cp(filepath, to) | bool | 拷贝文件 | | os.rm(filepath) | bool | 删除一个文件 | | os.mkdir(path) | bool | 创建目录 | | os.filesize(path) | integer | 取得文件的大小(Byte) | 全局函数 | **函数** | **返回值** | **说明** | | --- | --- | --- | | uuid() | string | 生成唯一ID | | md5(data) | string | 计算MD5 | | hash(data) | integer | 计算BKDR Hash值 | | crc32(data) | integer | 计算CRC32 | | random([int[, int]]) | double | 生成随机数 | | tick() | double | 毫秒级CPU时间 | | inherit(table) | table | 模拟继承 | JSON | **函数** | **返回值** | **说明** | | --- | --- | --- | | json.encode(v) | string | 将LUA的变量转为JSON字串 | | json.decode(v) | v | 将JSON字串解析为lua的变量 | XML | **函数** | **返回值** | **说明** | | --- | --- | --- | | xml.parse(xml_string) | table | 解析XML,返回table的格式:`{name=xxx, value=xxx, attr={}, children={} }` | BASE64 | **函数** | **返回值** | **说明** | | --- | --- | --- | | b64.encode(s) | string | Base64Encode | | b64.decode(s) | string | Base64Decode | LOGGER | **函数** | **返回值** | **说明** | | --- | --- | --- | | log.verbose(s) | nil | 输出Verbose信息 | | log.info(s) | nil | 输出INFO | | log.warn(s) | nil | 输出警告 | | log.error(s) | nil | 输出错误 |