From 49fb2abd85e1351e4a55f72cbcf0f1c94d674149 Mon Sep 17 00:00:00 2001 From: cloudfreexiao <996442717qqcom@gmail.com> Date: Sun, 25 Jul 2021 13:22:53 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A7=20build:=20=E8=B0=83=E6=95=B4=20we?= =?UTF-8?q?b=20=E5=90=8E=E7=AB=AF=20=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- framework/lualib/3rd/misc/tinyyaml.lua | 808 +++++++++++++ website/backend/.gitignore | 50 - website/backend/README.md | 15 - website/backend/app/config/config.lua | 59 - website/backend/app/config/error_code.lua | 30 - website/backend/app/controller/user/login.lua | 66 - .../backend/app/controller/user/signup.lua | 78 -- .../backend/app/controller/user/user_info.lua | 29 - website/backend/app/cors_header.lua | 11 - website/backend/app/librarys/README.md | 4 - website/backend/app/libs/cors.lua | 95 -- website/backend/app/libs/date.lua | 747 ------------ website/backend/app/libs/db.lua | 135 --- website/backend/app/libs/inspect.lua | 334 ------ website/backend/app/libs/ip_location.lua | 281 ----- website/backend/app/libs/log_api.lua | 49 - website/backend/app/libs/random.lua | 86 -- website/backend/app/libs/resty/http/http.lua | 1064 ----------------- .../app/libs/resty/http/http_headers.lua | 44 - website/backend/app/libs/resty/moongoo.lua | 146 --- .../app/libs/resty/moongoo/auth/cr.lua | 32 - .../app/libs/resty/moongoo/auth/scram.lua | 103 -- .../app/libs/resty/moongoo/collection.lua | 377 ------ .../app/libs/resty/moongoo/connection.lua | 210 ---- .../backend/app/libs/resty/moongoo/cursor.lua | 256 ---- .../app/libs/resty/moongoo/database.lua | 70 -- .../backend/app/libs/resty/moongoo/gridfs.lua | 57 - .../app/libs/resty/moongoo/gridfs/file.lua | 219 ---- .../backend/app/libs/resty/moongoo/utils.lua | 192 --- .../backend/app/libs/resty/redis/redis.lua | 439 ------- website/backend/app/libs/resty/smtp.lua | 321 ----- .../backend/app/libs/resty/smtp/base64.lua | 142 --- website/backend/app/libs/resty/smtp/ltn12.lua | 297 ----- .../backend/app/libs/resty/smtp/mime-core.lua | 271 ----- website/backend/app/libs/resty/smtp/mime.lua | 103 -- website/backend/app/libs/resty/smtp/misc.lua | 37 - website/backend/app/libs/resty/smtp/qp.lua | 222 ---- website/backend/app/libs/resty/smtp/tp.lua | 145 --- website/backend/app/libs/utils.lua | 153 --- website/backend/app/libs/uuid.lua | 205 ---- website/backend/app/main.lua | 6 - website/backend/app/middleware/README.md | 19 - .../backend/app/middleware/check_login.lua | 60 - .../app/middleware/inject_app_info.lua | 11 - website/backend/app/middleware/uploader.lua | 139 --- website/backend/app/model/user.lua | 72 -- website/backend/app/router.lua | 7 - website/backend/app/routes/api.lua | 48 - website/backend/app/server.lua | 90 -- website/backend/app/static/README.md | 11 - website/backend/app/views/.gitkeep | 0 website/backend/conf/README.md | 5 - website/backend/conf/mime.types | 88 -- website/backend/conf/nginx-dev.conf | 98 -- website/backend/lor/.gitignore | 12 - website/backend/lor/.luacheckrc | 4 - website/backend/lor/.sublimelinterrc | 16 - website/backend/lor/.travis.yml | 42 - website/backend/lor/.travis/platform.sh | 15 - website/backend/lor/.travis/setenv_lua.sh | 9 - website/backend/lor/.travis/setup_lua.sh | 109 -- website/backend/lor/.travis/setup_servers.sh | 33 - website/backend/lor/Changes.md | 174 --- website/backend/lor/LICENSE | 21 - website/backend/lor/Makefile | 49 - website/backend/lor/README.md | 143 --- website/backend/lor/README_zh.md | 168 --- website/backend/lor/bin/lord.lua | 47 - .../backend/lor/bin/scaffold/generator.lua | 628 ---------- website/backend/lor/bin/scaffold/launcher.lua | 101 -- .../lor/bin/scaffold/nginx/conf_template.lua | 47 - .../backend/lor/bin/scaffold/nginx/config.lua | 69 -- .../lor/bin/scaffold/nginx/directive.lua | 205 ---- .../backend/lor/bin/scaffold/nginx/handle.lua | 76 -- website/backend/lor/bin/scaffold/utils.lua | 45 - website/backend/lor/dist.ini | 10 - website/backend/lor/lib/lor/index.lua | 27 - .../backend/lor/lib/lor/lib/application.lua | 181 --- website/backend/lor/lib/lor/lib/debug.lua | 25 - website/backend/lor/lib/lor/lib/holder.lua | 48 - website/backend/lor/lib/lor/lib/methods.lua | 15 - .../lor/lib/lor/lib/middleware/cookie.lua | 91 -- .../lor/lib/lor/lib/middleware/init.lua | 9 - .../lor/lib/lor/lib/middleware/session.lua | 184 --- website/backend/lor/lib/lor/lib/node.lua | 265 ---- website/backend/lor/lib/lor/lib/request.lua | 75 -- website/backend/lor/lib/lor/lib/response.lua | 141 --- .../backend/lor/lib/lor/lib/router/group.lua | 141 --- .../backend/lor/lib/lor/lib/router/router.lua | 353 ------ website/backend/lor/lib/lor/lib/trie.lua | 532 --------- website/backend/lor/lib/lor/lib/utils/aes.lua | 54 - .../backend/lor/lib/lor/lib/utils/base64.lua | 27 - .../backend/lor/lib/lor/lib/utils/utils.lua | 152 --- website/backend/lor/lib/lor/lib/view.lua | 54 - website/backend/lor/lib/lor/lib/wrap.lua | 40 - website/backend/lor/lib/lor/version.lua | 1 - website/backend/lor/resty/cookie.lua | 192 --- website/backend/lor/resty/template.lua | 478 -------- website/backend/lor/resty/template/html.lua | 51 - .../lor/resty/template/microbenchmark.lua | 148 --- website/backend/lor/spec/cases/basic_spec.lua | 28 - .../backend/lor/spec/cases/common_spec.lua | 64 - .../lor/spec/cases/error_middleware_spec.lua | 108 -- .../lor/spec/cases/final_handler_spec.lua | 178 --- .../lor/spec/cases/group_index_route_spec.lua | 165 --- .../lor/spec/cases/group_router_spec.lua | 261 ---- .../backend/lor/spec/cases/mock_request.lua | 35 - .../backend/lor/spec/cases/mock_response.lua | 36 - .../lor/spec/cases/multi_route_spec.lua | 254 ---- .../backend/lor/spec/cases/node_id_spec.lua | 38 - .../backend/lor/spec/cases/not_found_spec.lua | 125 -- .../lor/spec/cases/path_params_spec.lua | 181 --- .../lor/spec/cases/path_pattern_1_spec.lua | 113 -- .../lor/spec/cases/path_pattern_2_spec.lua | 70 -- .../lor/spec/cases/path_pattern_3_spec.lua | 53 - .../backend/lor/spec/cases/uri_char_spec.lua | 45 - website/backend/lor/spec/trie/basic_spec.lua | 27 - .../lor/spec/trie/complex_cases_spec.lua | 96 -- website/backend/lor/spec/trie/debug_cases.lua | 49 - .../lor/spec/trie/define_node_spec.lua | 315 ----- .../backend/lor/spec/trie/find_node_spec.lua | 162 --- website/backend/lor/spec/trie/handle_spec.lua | 68 -- .../lor/spec/trie/strict_route_spec.lua | 73 -- website/backend/reload.sh | 21 - website/backend/start.sh | 21 - website/backend/stop.sh | 21 - website/backend/www/.gitkeep | 0 127 files changed, 808 insertions(+), 15742 deletions(-) create mode 100644 framework/lualib/3rd/misc/tinyyaml.lua delete mode 100755 website/backend/.gitignore delete mode 100755 website/backend/README.md delete mode 100755 website/backend/app/config/config.lua delete mode 100755 website/backend/app/config/error_code.lua delete mode 100755 website/backend/app/controller/user/login.lua delete mode 100755 website/backend/app/controller/user/signup.lua delete mode 100755 website/backend/app/controller/user/user_info.lua delete mode 100755 website/backend/app/cors_header.lua delete mode 100755 website/backend/app/librarys/README.md delete mode 100755 website/backend/app/libs/cors.lua delete mode 100755 website/backend/app/libs/date.lua delete mode 100755 website/backend/app/libs/db.lua delete mode 100755 website/backend/app/libs/inspect.lua delete mode 100755 website/backend/app/libs/ip_location.lua delete mode 100755 website/backend/app/libs/log_api.lua delete mode 100755 website/backend/app/libs/random.lua delete mode 100755 website/backend/app/libs/resty/http/http.lua delete mode 100755 website/backend/app/libs/resty/http/http_headers.lua delete mode 100755 website/backend/app/libs/resty/moongoo.lua delete mode 100755 website/backend/app/libs/resty/moongoo/auth/cr.lua delete mode 100755 website/backend/app/libs/resty/moongoo/auth/scram.lua delete mode 100755 website/backend/app/libs/resty/moongoo/collection.lua delete mode 100755 website/backend/app/libs/resty/moongoo/connection.lua delete mode 100755 website/backend/app/libs/resty/moongoo/cursor.lua delete mode 100755 website/backend/app/libs/resty/moongoo/database.lua delete mode 100755 website/backend/app/libs/resty/moongoo/gridfs.lua delete mode 100755 website/backend/app/libs/resty/moongoo/gridfs/file.lua delete mode 100755 website/backend/app/libs/resty/moongoo/utils.lua delete mode 100755 website/backend/app/libs/resty/redis/redis.lua delete mode 100755 website/backend/app/libs/resty/smtp.lua delete mode 100755 website/backend/app/libs/resty/smtp/base64.lua delete mode 100755 website/backend/app/libs/resty/smtp/ltn12.lua delete mode 100755 website/backend/app/libs/resty/smtp/mime-core.lua delete mode 100755 website/backend/app/libs/resty/smtp/mime.lua delete mode 100755 website/backend/app/libs/resty/smtp/misc.lua delete mode 100755 website/backend/app/libs/resty/smtp/qp.lua delete mode 100755 website/backend/app/libs/resty/smtp/tp.lua delete mode 100755 website/backend/app/libs/utils.lua delete mode 100755 website/backend/app/libs/uuid.lua delete mode 100755 website/backend/app/main.lua delete mode 100644 website/backend/app/middleware/README.md delete mode 100755 website/backend/app/middleware/check_login.lua delete mode 100755 website/backend/app/middleware/inject_app_info.lua delete mode 100755 website/backend/app/middleware/uploader.lua delete mode 100755 website/backend/app/model/user.lua delete mode 100755 website/backend/app/router.lua delete mode 100755 website/backend/app/routes/api.lua delete mode 100755 website/backend/app/server.lua delete mode 100755 website/backend/app/static/README.md delete mode 100755 website/backend/app/views/.gitkeep delete mode 100755 website/backend/conf/README.md delete mode 100644 website/backend/conf/mime.types delete mode 100755 website/backend/conf/nginx-dev.conf delete mode 100755 website/backend/lor/.gitignore delete mode 100755 website/backend/lor/.luacheckrc delete mode 100755 website/backend/lor/.sublimelinterrc delete mode 100755 website/backend/lor/.travis.yml delete mode 100755 website/backend/lor/.travis/platform.sh delete mode 100755 website/backend/lor/.travis/setenv_lua.sh delete mode 100755 website/backend/lor/.travis/setup_lua.sh delete mode 100755 website/backend/lor/.travis/setup_servers.sh delete mode 100755 website/backend/lor/Changes.md delete mode 100755 website/backend/lor/LICENSE delete mode 100644 website/backend/lor/Makefile delete mode 100755 website/backend/lor/README.md delete mode 100755 website/backend/lor/README_zh.md delete mode 100755 website/backend/lor/bin/lord.lua delete mode 100755 website/backend/lor/bin/scaffold/generator.lua delete mode 100755 website/backend/lor/bin/scaffold/launcher.lua delete mode 100755 website/backend/lor/bin/scaffold/nginx/conf_template.lua delete mode 100755 website/backend/lor/bin/scaffold/nginx/config.lua delete mode 100755 website/backend/lor/bin/scaffold/nginx/directive.lua delete mode 100755 website/backend/lor/bin/scaffold/nginx/handle.lua delete mode 100755 website/backend/lor/bin/scaffold/utils.lua delete mode 100755 website/backend/lor/dist.ini delete mode 100755 website/backend/lor/lib/lor/index.lua delete mode 100755 website/backend/lor/lib/lor/lib/application.lua delete mode 100755 website/backend/lor/lib/lor/lib/debug.lua delete mode 100644 website/backend/lor/lib/lor/lib/holder.lua delete mode 100755 website/backend/lor/lib/lor/lib/methods.lua delete mode 100755 website/backend/lor/lib/lor/lib/middleware/cookie.lua delete mode 100755 website/backend/lor/lib/lor/lib/middleware/init.lua delete mode 100755 website/backend/lor/lib/lor/lib/middleware/session.lua delete mode 100644 website/backend/lor/lib/lor/lib/node.lua delete mode 100755 website/backend/lor/lib/lor/lib/request.lua delete mode 100755 website/backend/lor/lib/lor/lib/response.lua delete mode 100644 website/backend/lor/lib/lor/lib/router/group.lua delete mode 100755 website/backend/lor/lib/lor/lib/router/router.lua delete mode 100644 website/backend/lor/lib/lor/lib/trie.lua delete mode 100644 website/backend/lor/lib/lor/lib/utils/aes.lua delete mode 100644 website/backend/lor/lib/lor/lib/utils/base64.lua delete mode 100755 website/backend/lor/lib/lor/lib/utils/utils.lua delete mode 100755 website/backend/lor/lib/lor/lib/view.lua delete mode 100755 website/backend/lor/lib/lor/lib/wrap.lua delete mode 100755 website/backend/lor/lib/lor/version.lua delete mode 100755 website/backend/lor/resty/cookie.lua delete mode 100755 website/backend/lor/resty/template.lua delete mode 100755 website/backend/lor/resty/template/html.lua delete mode 100755 website/backend/lor/resty/template/microbenchmark.lua delete mode 100644 website/backend/lor/spec/cases/basic_spec.lua delete mode 100755 website/backend/lor/spec/cases/common_spec.lua delete mode 100755 website/backend/lor/spec/cases/error_middleware_spec.lua delete mode 100755 website/backend/lor/spec/cases/final_handler_spec.lua delete mode 100644 website/backend/lor/spec/cases/group_index_route_spec.lua delete mode 100755 website/backend/lor/spec/cases/group_router_spec.lua delete mode 100755 website/backend/lor/spec/cases/mock_request.lua delete mode 100755 website/backend/lor/spec/cases/mock_response.lua delete mode 100644 website/backend/lor/spec/cases/multi_route_spec.lua delete mode 100644 website/backend/lor/spec/cases/node_id_spec.lua delete mode 100755 website/backend/lor/spec/cases/not_found_spec.lua delete mode 100755 website/backend/lor/spec/cases/path_params_spec.lua delete mode 100755 website/backend/lor/spec/cases/path_pattern_1_spec.lua delete mode 100755 website/backend/lor/spec/cases/path_pattern_2_spec.lua delete mode 100755 website/backend/lor/spec/cases/path_pattern_3_spec.lua delete mode 100644 website/backend/lor/spec/cases/uri_char_spec.lua delete mode 100644 website/backend/lor/spec/trie/basic_spec.lua delete mode 100644 website/backend/lor/spec/trie/complex_cases_spec.lua delete mode 100644 website/backend/lor/spec/trie/debug_cases.lua delete mode 100644 website/backend/lor/spec/trie/define_node_spec.lua delete mode 100644 website/backend/lor/spec/trie/find_node_spec.lua delete mode 100644 website/backend/lor/spec/trie/handle_spec.lua delete mode 100644 website/backend/lor/spec/trie/strict_route_spec.lua delete mode 100755 website/backend/reload.sh delete mode 100755 website/backend/start.sh delete mode 100755 website/backend/stop.sh delete mode 100755 website/backend/www/.gitkeep diff --git a/framework/lualib/3rd/misc/tinyyaml.lua b/framework/lualib/3rd/misc/tinyyaml.lua new file mode 100644 index 0000000..ceda927 --- /dev/null +++ b/framework/lualib/3rd/misc/tinyyaml.lua @@ -0,0 +1,808 @@ +------------------------------------------------------------------------------- +-- tinyyaml - YAML subset parser +-- https://github.com/peposso/lua-tinyyaml +------------------------------------------------------------------------------- +local table = table +local string = string +local schar = string.char +local ssub, gsub = string.sub, string.gsub +local sfind, smatch = string.find, string.match +local tinsert, tremove = table.insert, table.remove +local setmetatable = setmetatable +local pairs = pairs +local type = type +local tonumber = tonumber +local math = math +local getmetatable = getmetatable +local error = error + +local UNESCAPES = { + ['0'] = "\x00", + z = "\x00", + N = "\x85", + a = "\x07", + b = "\x08", + t = "\x09", + n = "\x0a", + v = "\x0b", + f = "\x0c", + r = "\x0d", + e = "\x1b", + ['\\'] = '\\' +}; + +------------------------------------------------------------------------------- +-- utils +local function select(list, pred) + local selected = {} + for i = 0, #list do + local v = list[i] + if v and pred(v, i) then + tinsert(selected, v) + end + end + return selected +end + +local function startswith(haystack, needle) + return ssub(haystack, 1, #needle) == needle +end + +local function ltrim(str) + return smatch(str, "^%s*(.-)$") +end + +local function rtrim(str) + return smatch(str, "^(.-)%s*$") +end + +------------------------------------------------------------------------------- +-- Implementation. +-- +local class = { + __meta = {} +} +function class.__meta.__call(cls, ...) + local self = setmetatable({}, cls) + if cls.__init then + cls.__init(self, ...) + end + return self +end + +function class.def(base, typ, cls) + base = base or class + local mt = { + __metatable = base, + __index = base + } + for k, v in pairs(base.__meta) do + mt[k] = v + end + cls = setmetatable(cls or {}, mt) + cls.__index = cls + cls.__metatable = cls + cls.__type = typ + cls.__meta = mt + return cls +end + +local types = { + null = class:def('null'), + map = class:def('map'), + omap = class:def('omap'), + pairs = class:def('pairs'), + set = class:def('set'), + seq = class:def('seq'), + timestamp = class:def('timestamp') +} + +local Null = types.null +function Null.__tostring() + return 'yaml.null' +end +function Null.isnull(v) + if v == nil then + return true + end + if type(v) == 'table' and getmetatable(v) == Null then + return true + end + return false +end +local null = Null() + +function types.timestamp:__init(y, m, d, h, i, s, f, z) + self.year = tonumber(y) + self.month = tonumber(m) + self.day = tonumber(d) + self.hour = tonumber(h or 0) + self.minute = tonumber(i or 0) + self.second = tonumber(s or 0) + if type(f) == 'string' and sfind(f, '^%d+$') then + self.fraction = tonumber(f) * math.pow(10, 3 - #f) + elseif f then + self.fraction = f + else + self.fraction = 0 + end + self.timezone = z +end + +function types.timestamp:__tostring() + return string.format('%04d-%02d-%02dT%02d:%02d:%02d.%03d%s', self.year, self.month, self.day, self.hour, + self.minute, self.second, self.fraction, self:gettz()) +end + +function types.timestamp:gettz() + if not self.timezone then + return '' + end + if self.timezone == 0 then + return 'Z' + end + local sign = self.timezone > 0 + local z = sign and self.timezone or -self.timezone + local zh = math.floor(z) + local zi = (z - zh) * 60 + return string.format('%s%02d:%02d', sign and '+' or '-', zh, zi) +end + +local function countindent(line) + local _, j = sfind(line, '^%s+') + if not j then + return 0, line + end + return j, ssub(line, j + 1) +end + +local function parsestring(line, stopper) + stopper = stopper or '' + local q = ssub(line, 1, 1) + if q == ' ' or q == '\t' then + return parsestring(ssub(line, 2)) + end + if q == "'" then + local i = sfind(line, "'", 2, true) + if not i then + return nil, line + end + return ssub(line, 2, i - 1), ssub(line, i + 1) + end + if q == '"' then + local i, buf = 2, '' + while i < #line do + local c = ssub(line, i, i) + if c == '\\' then + local n = ssub(line, i + 1, i + 1) + if UNESCAPES[n] ~= nil then + buf = buf .. UNESCAPES[n] + elseif n == 'x' then + local h = ssub(i + 2, i + 3) + if sfind(h, '^[0-9a-fA-F]$') then + buf = buf .. schar(tonumber(h, 16)) + i = i + 2 + else + buf = buf .. 'x' + end + else + buf = buf .. n + end + i = i + 1 + elseif c == q then + break + else + buf = buf .. c + end + i = i + 1 + end + return buf, ssub(line, i + 1) + end + if q == '{' or q == '[' then -- flow style + return nil, line + end + if q == '|' or q == '>' then -- block + return nil, line + end + if q == '-' or q == ':' then + if ssub(line, 2, 2) == ' ' or #line == 1 then + return nil, line + end + end + local buf = '' + while #line > 0 do + local c = ssub(line, 1, 1) + if sfind(stopper, c, 1, true) then + break + elseif c == ':' and (ssub(line, 2, 2) == ' ' or #line == 1) then + break + elseif c == '#' and (ssub(buf, #buf, #buf) == ' ') then + break + else + buf = buf .. c + end + line = ssub(line, 2) + end + return rtrim(buf), line +end + +local function isemptyline(line) + return line == '' or sfind(line, '^%s*$') or sfind(line, '^%s*#') +end + +local function equalsline(line, needle) + return startswith(line, needle) and isemptyline(ssub(line, #needle + 1)) +end + +local function checkdupekey(map, key) + if map[key] ~= nil then + -- print("found a duplicate key '"..key.."' in line: "..line) + local suffix = 1 + while map[key .. '_' .. suffix] do + suffix = suffix + 1 + end + key = key .. '_' .. suffix + end + return key +end + +local function parseflowstyle(line, lines) + local stack = {} + while true do + if #line == 0 then + if #lines == 0 then + break + else + line = tremove(lines, 1) + end + end + local c = ssub(line, 1, 1) + if c == '#' then + line = '' + elseif c == ' ' or c == '\t' or c == '\r' or c == '\n' then + line = ssub(line, 2) + elseif c == '{' or c == '[' then + tinsert(stack, { + v = {}, + t = c + }) + line = ssub(line, 2) + elseif c == ':' then + local s = tremove(stack) + tinsert(stack, { + v = s.v, + t = ':' + }) + line = ssub(line, 2) + elseif c == ',' then + local value = tremove(stack) + if value.t == ':' or value.t == '{' or value.t == '[' then + error() + end + if stack[#stack].t == ':' then + -- map + local key = tremove(stack) + key.v = checkdupekey(stack[#stack].v, key.v) + stack[#stack].v[key.v] = value.v + elseif stack[#stack].t == '{' then + -- set + stack[#stack].v[value.v] = true + elseif stack[#stack].t == '[' then + -- seq + tinsert(stack[#stack].v, value.v) + end + line = ssub(line, 2) + elseif c == '}' then + if stack[#stack].t == '{' then + if #stack == 1 then + break + end + stack[#stack].t = '}' + line = ssub(line, 2) + else + line = ',' .. line + end + elseif c == ']' then + if stack[#stack].t == '[' then + if #stack == 1 then + break + end + stack[#stack].t = ']' + line = ssub(line, 2) + else + line = ',' .. line + end + else + local s, rest = parsestring(line, ',{}[]') + if not s then + error('invalid flowstyle line: ' .. line) + end + tinsert(stack, { + v = s, + t = 's' + }) + line = rest + end + end + return stack[1].v, line +end + +local function parseblockstylestring(line, lines, indent) + if #lines == 0 then + error("failed to find multi-line scalar content") + end + local s = {} + local firstindent = -1 + local endline = -1 + for i = 1, #lines do + local ln = lines[i] + local idt = countindent(ln) + if idt <= indent then + break + end + if ln == '' then + tinsert(s, '') + else + if firstindent == -1 then + firstindent = idt + elseif idt < firstindent then + break + end + tinsert(s, ssub(ln, firstindent + 1)) + end + endline = i + end + + local striptrailing = true + local sep = '\n' + local newlineatend = true + if line == '|' then + striptrailing = true + sep = '\n' + newlineatend = true + elseif line == '|+' then + striptrailing = false + sep = '\n' + newlineatend = true + elseif line == '|-' then + striptrailing = true + sep = '\n' + newlineatend = false + elseif line == '>' then + striptrailing = true + sep = ' ' + newlineatend = true + elseif line == '>+' then + striptrailing = false + sep = ' ' + newlineatend = true + elseif line == '>-' then + striptrailing = true + sep = ' ' + newlineatend = false + else + error('invalid blockstyle string:' .. line) + end + local eonl = 0 + for i = #s, 1, -1 do + if s[i] == '' then + tremove(s, i) + eonl = eonl + 1 + end + end + if striptrailing then + eonl = 0 + end + if newlineatend then + eonl = eonl + 1 + end + for i = endline, 1, -1 do + tremove(lines, i) + end + return table.concat(s, sep) .. string.rep('\n', eonl) +end + +local function parsetimestamp(line) + local _, p1, y, m, d = sfind(line, '^(%d%d%d%d)%-(%d%d)%-(%d%d)') + if not p1 then + return nil, line + end + if p1 == #line then + return types.timestamp(y, m, d), '' + end + local _, p2, h, i, s = sfind(line, '^[Tt ](%d+):(%d+):(%d+)', p1 + 1) + if not p2 then + return types.timestamp(y, m, d), ssub(line, p1 + 1) + end + if p2 == #line then + return types.timestamp(y, m, d, h, i, s), '' + end + local _, p3, f = sfind(line, '^%.(%d+)', p2 + 1) + if not p3 then + p3 = p2 + f = 0 + end + local zc = ssub(line, p3 + 1, p3 + 1) + local _, p4, zs, z = sfind(line, '^ ?([%+%-])(%d+)', p3 + 1) + if p4 then + z = tonumber(z) + local _, p5, zi = sfind(line, '^:(%d+)', p4 + 1) + if p5 then + z = z + tonumber(zi) / 60 + end + z = zs == '-' and -tonumber(z) or tonumber(z) + elseif zc == 'Z' then + p4 = p3 + 1 + z = 0 + else + p4 = p3 + z = false + end + return types.timestamp(y, m, d, h, i, s, f, z), ssub(line, p4 + 1) +end + +local function parsescalar(line, lines, indent) + line = ltrim(line) + line = gsub(line, '^%s*#.*$', '') -- comment only -> '' + line = gsub(line, '^%s*', '') -- trim head spaces + + if line == '' or line == '~' then + return null + end + + local ts, _ = parsetimestamp(line) + if ts then + return ts + end + + local s, _ = parsestring(line) + -- startswith quote ... string + -- not startswith quote ... maybe string + if s and (startswith(line, '"') or startswith(line, "'")) then + return s + end + + if startswith('!', line) then -- unexpected tagchar + error('unsupported line: ' .. line) + end + + if equalsline(line, '{}') then + return {} + end + if equalsline(line, '[]') then + return {} + end + + if startswith(line, '{') or startswith(line, '[') then + return parseflowstyle(line, lines) + end + + if startswith(line, '|') or startswith(line, '>') then + return parseblockstylestring(line, lines, indent) + end + + -- Regular unquoted string + line = gsub(line, '%s*#.*$', '') -- trim tail comment + local v = line + if v == 'null' or v == 'Null' or v == 'NULL' then + return null + elseif v == 'true' or v == 'True' or v == 'TRUE' then + return true + elseif v == 'false' or v == 'False' or v == 'FALSE' then + return false + elseif v == '.inf' or v == '.Inf' or v == '.INF' then + return math.huge + elseif v == '+.inf' or v == '+.Inf' or v == '+.INF' then + return math.huge + elseif v == '-.inf' or v == '-.Inf' or v == '-.INF' then + return -math.huge + elseif v == '.nan' or v == '.NaN' or v == '.NAN' then + return 0 / 0 + elseif sfind(v, '^[%+%-]?[0-9]+$') or sfind(v, '^[%+%-]?[0-9]+%.$') then + return tonumber(v) -- : int + elseif sfind(v, '^[%+%-]?[0-9]+%.[0-9]+$') then + return tonumber(v) + end + return s or v +end + +local parsemap; -- : func + +local function parseseq(line, lines, indent) + local seq = setmetatable({}, types.seq) + if line ~= '' then + error() + end + while #lines > 0 do + -- Check for a new document + line = lines[1] + if startswith(line, '---') then + while #lines > 0 and not startswith(lines, '---') do + tremove(lines, 1) + end + return seq + end + + -- Check the indent level + local level = countindent(line) + if level < indent then + return seq + elseif level > indent then + error("found bad indenting in line: " .. line) + end + + local i, j = sfind(line, '%-%s+') + if not i then + i, j = sfind(line, '%-$') + if not i then + return seq + end + end + local rest = ssub(line, j + 1) + + if sfind(rest, '^[^\'\"%s]*:') then + -- Inline nested hash + local indent2 = j + lines[1] = string.rep(' ', indent2) .. rest + tinsert(seq, parsemap('', lines, indent2)) + elseif sfind(rest, '^%-%s+') then + -- Inline nested seq + local indent2 = j + lines[1] = string.rep(' ', indent2) .. rest + tinsert(seq, parseseq('', lines, indent2)) + elseif isemptyline(rest) then + tremove(lines, 1) + if #lines == 0 then + tinsert(seq, null) + return seq + end + if sfind(lines[1], '^%s*%-') then + local nextline = lines[1] + local indent2 = countindent(nextline) + if indent2 == indent then + -- Null seqay entry + tinsert(seq, null) + else + tinsert(seq, parseseq('', lines, indent2)) + end + else + -- - # comment + -- key: value + local nextline = lines[1] + local indent2 = countindent(nextline) + tinsert(seq, parsemap('', lines, indent2)) + end + elseif rest then + -- Array entry with a value + tremove(lines, 1) + tinsert(seq, parsescalar(rest, lines)) + end + end + return seq +end + +local function parseset(line, lines, indent) + if not isemptyline(line) then + error('not seq line: ' .. line) + end + local set = setmetatable({}, types.set) + while #lines > 0 do + -- Check for a new document + line = lines[1] + if startswith(line, '---') then + while #lines > 0 and not startswith(lines, '---') do + tremove(lines, 1) + end + return set + end + + -- Check the indent level + local level = countindent(line) + if level < indent then + return set + elseif level > indent then + error("found bad indenting in line: " .. line) + end + + local i, j = sfind(line, '%?%s+') + if not i then + i, j = sfind(line, '%?$') + if not i then + return set + end + end + local rest = ssub(line, j + 1) + + if sfind(rest, '^[^\'\"%s]*:') then + -- Inline nested hash + local indent2 = j + lines[1] = string.rep(' ', indent2) .. rest + set[parsemap('', lines, indent2)] = true + elseif sfind(rest, '^%s+$') then + tremove(lines, 1) + if #lines == 0 then + tinsert(set, null) + return set + end + if sfind(lines[1], '^%s*%?') then + local indent2 = countindent(lines[1]) + if indent2 == indent then + -- Null array entry + set[null] = true + else + set[parseseq('', lines, indent2)] = true + end + end + + elseif rest then + tremove(lines, 1) + set[parsescalar(rest, lines)] = true + else + error("failed to classify line: " .. line) + end + end + return set +end + +function parsemap(line, lines, indent) + if not isemptyline(line) then + error('not map line: ' .. line) + end + local map = setmetatable({}, types.map) + while #lines > 0 do + -- Check for a new document + line = lines[1] + if startswith(line, '---') then + while #lines > 0 and not startswith(lines, '---') do + tremove(lines, 1) + end + return map + end + + -- Check the indent level + local level, _ = countindent(line) + if level < indent then + return map + elseif level > indent then + error("found bad indenting in line: " .. line) + end + + -- Find the key + local key + local s, rest = parsestring(line) + + -- Quoted keys + if s and startswith(rest, ':') then + local sc = parsescalar(s, {}, 0) + if sc and type(sc) ~= 'string' then + key = sc + else + key = s + end + line = ssub(rest, 2) + else + error("failed to classify line: " .. line) + end + + key = checkdupekey(map, key) + line = ltrim(line) + + if ssub(line, 1, 1) == '!' then + -- ignore type + local rh = ltrim(ssub(line, 3)) + local typename = smatch(rh, '^!?[^%s]+') + line = ltrim(ssub(rh, #typename + 1)) + end + + if not isemptyline(line) then + tremove(lines, 1) + line = ltrim(line) + map[key] = parsescalar(line, lines, indent) + else + -- An indent + tremove(lines, 1) + if #lines == 0 then + map[key] = null + return map; + end + if sfind(lines[1], '^%s*%-') then + local indent2 = countindent(lines[1]) + map[key] = parseseq('', lines, indent2) + elseif sfind(lines[1], '^%s*%?') then + local indent2 = countindent(lines[1]) + map[key] = parseset('', lines, indent2) + else + local indent2 = countindent(lines[1]) + if indent >= indent2 then + -- Null hash entry + map[key] = null + else + map[key] = parsemap('', lines, indent2) + end + end + end + end + return map +end + +-- : (list)->dict +local function parsedocuments(lines) + lines = select(lines, function(s) + return not isemptyline(s) + end) + + if sfind(lines[1], '^%%YAML') then + tremove(lines, 1) + end + + local root = {} + local in_document = false + while #lines > 0 do + local line = lines[1] + -- Do we have a document header? + local docright; + if sfind(line, '^%-%-%-') then + -- Handle scalar documents + docright = ssub(line, 4) + tremove(lines, 1) + in_document = true + end + if docright then + if (not sfind(docright, '^%s+$') and not sfind(docright, '^%s+#')) then + tinsert(root, parsescalar(docright, lines)) + end + elseif #lines == 0 or startswith(line, '---') then + -- A naked document + tinsert(root, null) + while #lines > 0 and not sfind(lines[1], '---') do + tremove(lines, 1) + end + in_document = false + -- XXX The final '-+$' is to look for -- which ends up being an + -- error later. + elseif not in_document and #root > 0 then + -- only the first document can be explicit + error('parse error: ' .. line) + elseif sfind(line, '^%s*%-') then + -- An array at the root + tinsert(root, parseseq('', lines, 0)) + elseif sfind(line, '^%s*[^%s]') then + -- A hash at the root + local level = countindent(line) + tinsert(root, parsemap('', lines, level)) + else + -- Shouldn't get here. @lines have whitespace-only lines + -- stripped, and previous match is a line with any + -- non-whitespace. So this clause should only be reachable via + -- a perlbug where \s is not symmetric with \S + + -- uncoverable statement + error('parse error: ' .. line) + end + end + if #root > 1 and Null.isnull(root[1]) then + tremove(root, 1) + return root + end + return root +end + +--- Parse yaml string into table. +local function parse(source) + local lines = {} + for line in string.gmatch(source .. '\n', '(.-)\r?\n') do + tinsert(lines, line) + end + + local docs = parsedocuments(lines) + if #docs == 1 then + return docs[1] + end + + return docs +end + +return { + version = 0.1, + parse = parse +} diff --git a/website/backend/.gitignore b/website/backend/.gitignore deleted file mode 100755 index b0ffa7e..0000000 --- a/website/backend/.gitignore +++ /dev/null @@ -1,50 +0,0 @@ -# lor -client_body_temp -fastcgi_temp -logs -proxy_temp -tmp -uwsgi_temp - -# Compiled Lua sources -luac.out - -# luarocks build files -*.src.rock -*.zip -*.tar.gz - -# Object files -*.o -*.os -*.ko -*.obj -*.elf - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo -*.def -*.exp - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex - -www/admin/ \ No newline at end of file diff --git a/website/backend/README.md b/website/backend/README.md deleted file mode 100755 index 1631e12..0000000 --- a/website/backend/README.md +++ /dev/null @@ -1,15 +0,0 @@ - -## Installation - - -1 安装 [openresty](https://openresty.org) - -2 了解 [lor](https://github.com/sumory/lor) - -3 修改 [相关配置](https://github.com/cloudfreexiao/RillAdmin/issues/1) - -4 把 frontend 工程打包好的 资源 copy 到 [www 目录](https://github.com/cloudfreexiao/RillAdmin/tree/master/backend-or/www) - -5 执行 start shell - -6 访问 [http://localhost:9527](http://localhost:9527). diff --git a/website/backend/app/config/config.lua b/website/backend/app/config/config.lua deleted file mode 100755 index fbf59a5..0000000 --- a/website/backend/app/config/config.lua +++ /dev/null @@ -1,59 +0,0 @@ -return { - -- 白名单配置:不需要登录即可访问;除非要二次开发,否则不应更改 - whitelist = { - "^/api/login$", -- login page - "^/api/sign_up$", -- sign up page - -- "^/api/user$", - "^/error/$" -- error page - }, - - -- 静态模板配置,保持默认不修改即可 - view_config = { - engine = "tmpl", - ext = "html", - views = "./app/views" - }, - - - -- 分页时每页条数配置 - page_config = { - index_topic_page_size = 10, -- 首页每页文章数 - }, - - - - -- ########################## 以下配置需要使用者自定义为本地需要的配置 ########################## -- - - -- 生成session的secret,请一定要修改此值为一复杂的字符串,用于加密session - session_secret = "3584827dfed45b40328acb6242bhngod", - - -- 用于存储密码的盐,请一定要修改此值, 一旦使用不能修改,用户也可自行实现其他密码方案 - pwd_secret = "salt_secret_for_password", - jwt_secret = "hjuhdk_jjdkdh763nnjhf", --jwt 私钥,用于加密 - - -- mysql配置 - --ERROR 1045 (28000): Access denied for user 'root'@'192.168.1.25' (using password: YES) - --原因是 非本机不可以root 登录 - mysql = { - timeout = 5000, - connect_config = { - host = "192.168.1.14", - port = 3306, - database = "fishadmin", - user = "fish", - password = "111111", - max_packet_size = 1024 * 1024 - }, - pool_config = { - max_idle_timeout = 20000, -- 20s - pool_size = 50 -- connection pool size - } - }, - - -- 上传文件配置,如上传的头像、文章中的图片等 - upload_config = { - dir = "/opt/fishadmin/static", -- 文件目录,修改此值时须同时修改nginx配置文件中的$static_files_path值 - }, - - cors_whitelist = "http://192.168.1.35:9527", --请修改自己对应的 frontend url -} \ No newline at end of file diff --git a/website/backend/app/config/error_code.lua b/website/backend/app/config/error_code.lua deleted file mode 100755 index 9d7f213..0000000 --- a/website/backend/app/config/error_code.lua +++ /dev/null @@ -1,30 +0,0 @@ -local errors = {} - -function system_error_msg(ec) - if not ec then - return "nil" - end - return errors[ec].desc -end - -local function add(err) - assert(errors[err.code] == nil, string.format("have the same error code[%x], msg[%s]", err.code, err.message)) - errors[err.code] = {code = err.code, desc = err.desc} - return err.code -end - -SYSTEM_ERROR = { - success = add{code = 0x0000, desc = "请求成功"}, - failed = add{code = 0x0001, desc = "操作失败"}, -} - -AUTH_ERROR = { - account_error = add{code = 0x0101, desc = "用户名或密码错误,请检查!"}, - account_nil = add{code = 0x0102, desc = "用户名和密码不得为空!"}, - account_login = add{code = 0x0103, desc = "该操作需要先登录!"}, - -} - - - -return errors \ No newline at end of file diff --git a/website/backend/app/controller/user/login.lua b/website/backend/app/controller/user/login.lua deleted file mode 100755 index 58d8200..0000000 --- a/website/backend/app/controller/user/login.lua +++ /dev/null @@ -1,66 +0,0 @@ -local utils = require("app.libs.utils") --- local jwt = require("app.libs.jwt.jwt") - -local pwd_secret = require("app.config.config").pwd_secret -local jwt_secret = require("app.config.config").jwt_secret - -local user_model = require("app.model.user") - -return function (req, username, password) - if not username or not password or username == "" or password == "" then - return { - code = AUTH_ERROR.account_nil, - message = system_error_msg(AUTH_ERROR.account_nil), - } - end - - local isExist = false - local userid = 0 - - password = utils.encode(password .. "#" .. pwd_secret) - local result, err = user_model:query(username, password) - - local user = {} - if result and not err then - if result and #result == 1 then - isExist = true - user = result[1] - userid = user.id - end - else - isExist = false - end - - -- 生成 token 的有效期 - local now = ngx.now() - local exp = now + 1200 - - if isExist == true then - -- local jwt_token = jwt:sign(jwt_secret, { - -- header = { typ = "JWT", alg = "HS256" }, - -- payload = { foo = "bar", id = 1, name = "mind029", exp = exp } - -- }) - - local token = ngx.md5(username .. password .. os.time() .. "fishadminapi") - req.session.set("user", { - username = username, - userid = userid, - create_time = user.create_time or "", - token = token - }) - - return { - code = SYSTEM_ERROR.success, - message = system_error_msg(SYSTEM_ERROR.success), - data = { - token = token - } - } - else - return { - code = AUTH_ERROR.account_error, - message = system_error_msg(AUTH_ERROR.account_error), - } - end - -end \ No newline at end of file diff --git a/website/backend/app/controller/user/signup.lua b/website/backend/app/controller/user/signup.lua deleted file mode 100755 index 6849b6e..0000000 --- a/website/backend/app/controller/user/signup.lua +++ /dev/null @@ -1,78 +0,0 @@ -local pairs = pairs -local ipairs = ipairs -local smatch = string.match -local slen = string.len -local ssub = string.sub -local slower = string.lower - -local utils = require("app.libs.utils") -local pwd_secret = require("app.config.config").pwd_secret - -local user_model = require("app.model.user") - -local role_lv = 1 --角色等级 用来 鉴权操作 - -return function(username, password) - local pattern = "^[a-zA-Z][0-9a-zA-Z_]+$" - local match, err = smatch(username, pattern) - - if not username or not password or username == "" or password == "" then - return { - code = system_error_msg(AUTH_ERROR.account_nil), - message = system_error_msg(AUTH_ERROR.account_nil), - } - end - - local username_len = slen(username) - local password_len = slen(password) - - if username_len<4 or username_len>50 then - return { - success = false, - msg = "用户名长度应为4~50位." - } - end - if password_len<6 or password_len>50 then - return { - success = false, - msg = "密码长度应为6~50位." - } - end - - if not match then - return { - success = false, - msg = "用户名只能输入字母、下划线、数字,必须以字母开头." - } - end - - local result, err = user_model:query_by_username(username) - local isExist = false - if result and not err then - isExist = true - end - - if isExist == true then - return { - success = false, - msg = "用户名已被占用,请修改." - } - else - password = utils.encode(password .. "#" .. pwd_secret) - local avatar = ssub(username, 1, 1) .. ".png" --取首字母作为默认头像名 - avatar = slower(avatar) - local result, err = user_model:new(username, password, avatar, role_lv) - if result and not err then - return { - success = true, - msg = "注册成功." - } - else - return { - success = false, - msg = "注册失败." - } - end - end - -end \ No newline at end of file diff --git a/website/backend/app/controller/user/user_info.lua b/website/backend/app/controller/user/user_info.lua deleted file mode 100755 index 59959b0..0000000 --- a/website/backend/app/controller/user/user_info.lua +++ /dev/null @@ -1,29 +0,0 @@ - -local function is_login(req) - local user - if req.session then - user = req.session.get("user") - if user and user.username and user.userid then - return true, user - end - end - return false, nil -end - -return function (req, res) - local user = is_login(req) - assert(user) - local msg = { - code = SYSTEM_ERROR.success, - message = system_error_msg(SYSTEM_ERROR.success), - data = { - name = "goodname", - avatar = "333333", - roles = {[1] = "/api/getRoles", - [2] = "/api/role",}, - permissions = {[1]="/api/permissions/"}, - } - - } - return msg -end \ No newline at end of file diff --git a/website/backend/app/cors_header.lua b/website/backend/app/cors_header.lua deleted file mode 100755 index 992fe5d..0000000 --- a/website/backend/app/cors_header.lua +++ /dev/null @@ -1,11 +0,0 @@ -local cors_whitelist = require("app.config.config").cors_whitelist - ---跨域访问 头 设置 -return function (res) - res:set_header("X-Powered-By", "Lor framework") - res:set_header("Access-Control-Allow-Origin", cors_whitelist) - - res:set_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") - res:set_header("Access-Control-Allow-Credentials", "true") - res:set_header("Access-Control-Allow-Headers", "Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since,X-Msys-Subaccount,X-Sparky") -end \ No newline at end of file diff --git a/website/backend/app/librarys/README.md b/website/backend/app/librarys/README.md deleted file mode 100755 index d5c634a..0000000 --- a/website/backend/app/librarys/README.md +++ /dev/null @@ -1,4 +0,0 @@ - -### lua c so 存放目录() - - diff --git a/website/backend/app/libs/cors.lua b/website/backend/app/libs/cors.lua deleted file mode 100755 index 3ad2766..0000000 --- a/website/backend/app/libs/cors.lua +++ /dev/null @@ -1,95 +0,0 @@ --- @Author: detailyang --- @Date: 2016-10-10 15:45:33 --- @Last Modified by: detailyang --- @Last Modified time: 2017-02-19 13:29:41 - --- https://www.w3.org/TR/cors/ - -local re_match = ngx.re.match - -local _M = { _VERSION = '0.1.0'} - -local Origin = 'Origin' -local AccessControlAllowOrigin = 'Access-Control-Allow-Origin' -local AccessControlExposeHeaders = 'Access-Control-Expose-Headers' -local AccessControlMaxAge = 'Access-Control-Max-Age' -local AccessControlAllowCredentials = 'Access-Control-Allow-Credentials' -local AccessControlAllowMethods = 'Access-Control-Allow-Methods' -local AccessControlAllowHeaders = 'Access-Control-Allow-Headers' - -local mt = { __index = _M } - -local allow_hosts = {} -local allow_headers = {} -local allow_methods = {} -local expose_headers = {} -local max_age = 3600 -local allow_credentials = true -local join = table.concat - - -function _M.allow_host(host) - allow_hosts[#allow_hosts + 1] = host -end - -function _M.allow_method(method) - allow_methods[#allow_methods + 1] = method -end - -function _M.allow_header(header) - allow_headers[#allow_headers + 1] = header -end - -function _M.expose_header(header) - expose_headers[#expose_headers + 1] = header -end - -function _M.max_age(age) - max_age = age -end - -function _M.allow_credentials(credentials) - allow_credentials = credentials -end - -function _M.run() - local origin = ngx.req.get_headers()[Origin] - if not origin then - return - end - - local matched = false - for k, v in pairs(allow_hosts) do - local from, to, err = ngx.re.find(origin, v, "jo") - if from then - matched = true - end - end - - if matched == false then - return - end - - ngx.header[AccessControlAllowOrigin] = origin - ngx.header[AccessControlMaxAge] = max_age - - if #expose_headers >= 0 then - ngx.header[AccessControlExposeHeaders] = join(expose_headers, ',') - end - - if #allow_headers >= 0 then - ngx.header[AccessControlAllowHeaders] = join(allow_headers, ',') - end - - if #allow_methods >= 0 then - ngx.header[AccessControlAllowMethods] = join(allow_methods, ',') - end - - if allow_credentials == true then - ngx.header[AccessControlAllowCredentials] = "true" - else - ngx.header[AccessControlAllowCredentials] = "false" - end -end - -return _M diff --git a/website/backend/app/libs/date.lua b/website/backend/app/libs/date.lua deleted file mode 100755 index 6010cda..0000000 --- a/website/backend/app/libs/date.lua +++ /dev/null @@ -1,747 +0,0 @@ --- https://github.com/Tieske/date ---------------------------------------------------------------------------------------- --- Module for date and time calculations --- --- Version 2.1.1 --- Copyright (C) 2006, by Jas Latrix (jastejada@yahoo.com) --- Copyright (C) 2013-2014, by Thijs Schreijer --- Licensed under MIT, http://opensource.org/licenses/MIT - ---[[ CONSTANTS ]]-- - local HOURPERDAY = 24 - local MINPERHOUR = 60 - local MINPERDAY = 1440 -- 24*60 - local SECPERMIN = 60 - local SECPERHOUR = 3600 -- 60*60 - local SECPERDAY = 86400 -- 24*60*60 - local TICKSPERSEC = 1000000 - local TICKSPERDAY = 86400000000 - local TICKSPERHOUR = 3600000000 - local TICKSPERMIN = 60000000 - local DAYNUM_MAX = 365242500 -- Sat Jan 01 1000000 00:00:00 - local DAYNUM_MIN = -365242500 -- Mon Jan 01 1000000 BCE 00:00:00 - local DAYNUM_DEF = 0 -- Mon Jan 01 0001 00:00:00 - local _; ---[[ LOCAL ARE FASTER ]]-- - local type = type - local pairs = pairs - local error = error - local assert = assert - local tonumber = tonumber - local tostring = tostring - local string = string - local math = math - local os = os - local unpack = unpack or table.unpack - local pack = table.pack or function(...) return { n = select('#', ...), ... } end - local setmetatable = setmetatable - local getmetatable = getmetatable ---[[ EXTRA FUNCTIONS ]]-- - local fmt = string.format - local lwr = string.lower - local upr = string.upper - local rep = string.rep - local len = string.len - local sub = string.sub - local gsub = string.gsub - local gmatch = string.gmatch or string.gfind - local find = string.find - local ostime = os.time - local osdate = os.date - local floor = math.floor - local ceil = math.ceil - local abs = math.abs - -- removes the decimal part of a number - local function fix(n) n = tonumber(n) return n and ((n > 0 and floor or ceil)(n)) end - -- returns the modulo n % d; - local function mod(n,d) return n - d*floor(n/d) end - -- rounds a number; - local function round(n, d) d=d^10 return floor((n*d)+.5)/d end - -- rounds a number to whole; - local function whole(n)return floor(n+.5)end - -- is `str` in string list `tbl`, `ml` is the minimun len - local function inlist(str, tbl, ml, tn) - local sl = len(str) - if sl < (ml or 0) then return nil end - str = lwr(str) - for k, v in pairs(tbl) do - if str == lwr(sub(v, 1, sl)) then - if tn then tn[0] = k end - return k - end - end - end - local function fnil() end - local function fret(x)return x;end ---[[ DATE FUNCTIONS ]]-- - local DATE_EPOCH -- to be set later - local sl_weekdays = { - [0]="Sunday",[1]="Monday",[2]="Tuesday",[3]="Wednesday",[4]="Thursday",[5]="Friday",[6]="Saturday", - [7]="Sun",[8]="Mon",[9]="Tue",[10]="Wed",[11]="Thu",[12]="Fri",[13]="Sat", - } - local sl_meridian = {[-1]="AM", [1]="PM"} - local sl_months = { - [00]="January", [01]="February", [02]="March", - [03]="April", [04]="May", [05]="June", - [06]="July", [07]="August", [08]="September", - [09]="October", [10]="November", [11]="December", - [12]="Jan", [13]="Feb", [14]="Mar", - [15]="Apr", [16]="May", [17]="Jun", - [18]="Jul", [19]="Aug", [20]="Sep", - [21]="Oct", [22]="Nov", [23]="Dec", - } - -- added the '.2' to avoid collision, use `fix` to remove - local sl_timezone = { - [000]="utc", [0.2]="gmt", - [300]="est", [240]="edt", - [360]="cst", [300.2]="cdt", - [420]="mst", [360.2]="mdt", - [480]="pst", [420.2]="pdt", - } - -- set the day fraction resolution - local function setticks(t) - TICKSPERSEC = t; - TICKSPERDAY = SECPERDAY*TICKSPERSEC - TICKSPERHOUR= SECPERHOUR*TICKSPERSEC - TICKSPERMIN = SECPERMIN*TICKSPERSEC - end - -- is year y leap year? - local function isleapyear(y) -- y must be int! - return (mod(y, 4) == 0 and (mod(y, 100) ~= 0 or mod(y, 400) == 0)) - end - -- day since year 0 - local function dayfromyear(y) -- y must be int! - return 365*y + floor(y/4) - floor(y/100) + floor(y/400) - end - -- day number from date, month is zero base - local function makedaynum(y, m, d) - local mm = mod(mod(m,12) + 10, 12) - return dayfromyear(y + floor(m/12) - floor(mm/10)) + floor((mm*306 + 5)/10) + d - 307 - --local yy = y + floor(m/12) - floor(mm/10) - --return dayfromyear(yy) + floor((mm*306 + 5)/10) + (d - 1) - end - -- date from day number, month is zero base - local function breakdaynum(g) - local g = g + 306 - local y = floor((10000*g + 14780)/3652425) - local d = g - dayfromyear(y) - if d < 0 then y = y - 1; d = g - dayfromyear(y) end - local mi = floor((100*d + 52)/3060) - return (floor((mi + 2)/12) + y), mod(mi + 2,12), (d - floor((mi*306 + 5)/10) + 1) - end - --[[ for floats or int32 Lua Number data type - local function breakdaynum2(g) - local g, n = g + 306; - local n400 = floor(g/DI400Y);n = mod(g,DI400Y); - local n100 = floor(n/DI100Y);n = mod(n,DI100Y); - local n004 = floor(n/DI4Y); n = mod(n,DI4Y); - local n001 = floor(n/365); n = mod(n,365); - local y = (n400*400) + (n100*100) + (n004*4) + n001 - ((n001 == 4 or n100 == 4) and 1 or 0) - local d = g - dayfromyear(y) - local mi = floor((100*d + 52)/3060) - return (floor((mi + 2)/12) + y), mod(mi + 2,12), (d - floor((mi*306 + 5)/10) + 1) - end - ]] - -- day fraction from time - local function makedayfrc(h,r,s,t) - return ((h*60 + r)*60 + s)*TICKSPERSEC + t - end - -- time from day fraction - local function breakdayfrc(df) - return - mod(floor(df/TICKSPERHOUR),HOURPERDAY), - mod(floor(df/TICKSPERMIN ),MINPERHOUR), - mod(floor(df/TICKSPERSEC ),SECPERMIN), - mod(df,TICKSPERSEC) - end - -- weekday sunday = 0, monday = 1 ... - local function weekday(dn) return mod(dn + 1, 7) end - -- yearday 0 based ... - local function yearday(dn) - return dn - dayfromyear((breakdaynum(dn))-1) - end - -- parse v as a month - local function getmontharg(v) - local m = tonumber(v); - return (m and fix(m - 1)) or inlist(tostring(v) or "", sl_months, 2) - end - -- get daynum of isoweek one of year y - local function isow1(y) - local f = makedaynum(y, 0, 4) -- get the date for the 4-Jan of year `y` - local d = weekday(f) - d = d == 0 and 7 or d -- get the ISO day number, 1 == Monday, 7 == Sunday - return f + (1 - d) - end - local function isowy(dn) - local w1; - local y = (breakdaynum(dn)) - if dn >= makedaynum(y, 11, 29) then - w1 = isow1(y + 1); - if dn < w1 then - w1 = isow1(y); - else - y = y + 1; - end - else - w1 = isow1(y); - if dn < w1 then - w1 = isow1(y-1) - y = y - 1 - end - end - return floor((dn-w1)/7)+1, y - end - local function isoy(dn) - local y = (breakdaynum(dn)) - return y + (((dn >= makedaynum(y, 11, 29)) and (dn >= isow1(y + 1))) and 1 or (dn < isow1(y) and -1 or 0)) - end - local function makedaynum_isoywd(y,w,d) - return isow1(y) + 7*w + d - 8 -- simplified: isow1(y) + ((w-1)*7) + (d-1) - end ---[[ THE DATE MODULE ]]-- - local fmtstr = "%x %X"; ---#if not DATE_OBJECT_AFX then - local date = {} - setmetatable(date, date) --- Version: VMMMRRRR; V-Major, M-Minor, R-Revision; e.g. 5.45.321 == 50450321 - date.version = 20010001 -- 2.1.1 ---#end -- not DATE_OBJECT_AFX ---[[ THE DATE OBJECT ]]-- - local dobj = {} - dobj.__index = dobj - dobj.__metatable = dobj - -- shout invalid arg - local function date_error_arg() return error("invalid argument(s)",0) end - -- create new date object - local function date_new(dn, df) - return setmetatable({daynum=dn, dayfrc=df}, dobj) - end - -- is `v` a date object? - local function date_isdobj(v) - return (type(v) == 'table' and getmetatable(v) == dobj) and v - end - ---#if not NO_LOCAL_TIME_SUPPORT then - -- magic year table - local date_epoch, yt; - local function getequivyear(y) - assert(not yt) - yt = {} - local de, dw, dy = date_epoch:copy() - for i = 0, 3000 do - de:setyear(de:getyear() + 1, 1, 1) - dy = de:getyear() - dw = de:getweekday() * (isleapyear(dy) and -1 or 1) - if not yt[dw] then yt[dw] = dy end --print(de) - if yt[1] and yt[2] and yt[3] and yt[4] and yt[5] and yt[6] and yt[7] and yt[-1] and yt[-2] and yt[-3] and yt[-4] and yt[-5] and yt[-6] and yt[-7] then - getequivyear = function(y) return yt[ (weekday(makedaynum(y, 0, 1)) + 1) * (isleapyear(y) and -1 or 1) ] end - return getequivyear(y) - end - end - end - -- TimeValue from daynum and dayfrc - local function dvtotv(dn, df) - return fix(dn - DATE_EPOCH) * SECPERDAY + (df/1000) - end - -- TimeValue from date and time - local function totv(y,m,d,h,r,s) - return (makedaynum(y, m, d) - DATE_EPOCH) * SECPERDAY + ((h*60 + r)*60 + s) - end - -- TimeValue from TimeTable - local function tmtotv(tm) - return tm and totv(tm.year, tm.month - 1, tm.day, tm.hour, tm.min, tm.sec) - end - -- Returns the bias in seconds of utc time daynum and dayfrc - local function getbiasutc2(self) - local y,m,d = breakdaynum(self.daynum) - local h,r,s = breakdayfrc(self.dayfrc) - local tvu = totv(y,m,d,h,r,s) -- get the utc TimeValue of date and time - local tml = osdate("*t", tvu) -- get the local TimeTable of tvu - if (not tml) or (tml.year > (y+1) or tml.year < (y-1)) then -- failed try the magic - y = getequivyear(y) - tvu = totv(y,m,d,h,r,s) - tml = osdate("*t", tvu) - end - local tvl = tmtotv(tml) - if tvu and tvl then - return tvu - tvl, tvu, tvl - else - return error("failed to get bias from utc time") - end - end - -- Returns the bias in seconds of local time daynum and dayfrc - local function getbiasloc2(daynum, dayfrc) - local tvu - -- extract date and time - local y,m,d = breakdaynum(daynum) - local h,r,s = breakdayfrc(dayfrc) - -- get equivalent TimeTable - local tml = {year=y, month=m+1, day=d, hour=h, min=r, sec=s} - -- get equivalent TimeValue - local tvl = tmtotv(tml) - - local function chkutc() - tml.isdst = nil; local tvug = ostime(tml) if tvug and (tvl == tmtotv(osdate("*t", tvug))) then tvu = tvug return end - tml.isdst = true; local tvud = ostime(tml) if tvud and (tvl == tmtotv(osdate("*t", tvud))) then tvu = tvud return end - tvu = tvud or tvug - end - chkutc() - if not tvu then - tml.year = getequivyear(y) - tvl = tmtotv(tml) - chkutc() - end - return ((tvu and tvl) and (tvu - tvl)) or error("failed to get bias from local time"), tvu, tvl - end ---#end -- not NO_LOCAL_TIME_SUPPORT - ---#if not DATE_OBJECT_AFX then - -- the date parser - local strwalker = {} -- ^Lua regular expression is not as powerful as Perl$ - strwalker.__index = strwalker - local function newstrwalker(s)return setmetatable({s=s, i=1, e=1, c=len(s)}, strwalker) end - function strwalker:aimchr() return "\n" .. self.s .. "\n" .. rep(".",self.e-1) .. "^" end - function strwalker:finish() return self.i > self.c end - function strwalker:back() self.i = self.e return self end - function strwalker:restart() self.i, self.e = 1, 1 return self end - function strwalker:match(s) return (find(self.s, s, self.i)) end - function strwalker:__call(s, f)-- print("strwalker:__call "..s..self:aimchr()) - local is, ie; is, ie, self[1], self[2], self[3], self[4], self[5] = find(self.s, s, self.i) - if is then self.e, self.i = self.i, 1+ie; if f then f(unpack(self)) end return self end - end - local function date_parse(str) - local y,m,d, h,r,s, z, w,u, j, e, k, x,v,c, chkfin, dn,df; - local sw = newstrwalker(gsub(gsub(str, "(%b())", ""),"^(%s*)","")) -- remove comment, trim leading space - --local function error_out() print(y,m,d,h,r,s) end - local function error_dup(q) --[[error_out()]] error("duplicate value: " .. (q or "") .. sw:aimchr()) end - local function error_syn(q) --[[error_out()]] error("syntax error: " .. (q or "") .. sw:aimchr()) end - local function error_inv(q) --[[error_out()]] error("invalid date: " .. (q or "") .. sw:aimchr()) end - local function sety(q) y = y and error_dup() or tonumber(q); end - local function setm(q) m = (m or w or j) and error_dup(m or w or j) or tonumber(q) end - local function setd(q) d = d and error_dup() or tonumber(q) end - local function seth(q) h = h and error_dup() or tonumber(q) end - local function setr(q) r = r and error_dup() or tonumber(q) end - local function sets(q) s = s and error_dup() or tonumber(q) end - local function adds(q) s = s + tonumber(q) end - local function setj(q) j = (m or w or j) and error_dup() or tonumber(q); end - local function setz(q) z = (z ~= 0 and z) and error_dup() or q end - local function setzn(zs,zn) zn = tonumber(zn); setz( ((zn<24) and (zn*60) or (mod(zn,100) + floor(zn/100) * 60))*( zs=='+' and -1 or 1) ) end - local function setzc(zs,zh,zm) setz( ((tonumber(zh)*60) + tonumber(zm))*( zs=='+' and -1 or 1) ) end - - if not (sw("^(%d%d%d%d)",sety) and (sw("^(%-?)(%d%d)%1(%d%d)",function(_,a,b) setm(tonumber(a)); setd(tonumber(b)) end) or sw("^(%-?)[Ww](%d%d)%1(%d?)",function(_,a,b) w, u = tonumber(a), tonumber(b or 1) end) or sw("^%-?(%d%d%d)",setj) or sw("^%-?(%d%d)",function(a) setm(a);setd(1) end)) - and ((sw("^%s*[Tt]?(%d%d):?",seth) and sw("^(%d%d):?",setr) and sw("^(%d%d)",sets) and sw("^(%.%d+)",adds)) - or sw:finish() or (sw"^%s*$" or sw"^%s*[Zz]%s*$" or sw("^%s-([%+%-])(%d%d):?(%d%d)%s*$",setzc) or sw("^%s*([%+%-])(%d%d)%s*$",setzn)) - ) ) - then --print(y,m,d,h,r,s,z,w,u,j) - sw:restart(); y,m,d,h,r,s,z,w,u,j = nil; - repeat -- print(sw:aimchr()) - if sw("^[tT:]?%s*(%d%d?):",seth) then --print("$Time") - _ = sw("^%s*(%d%d?)",setr) and sw("^%s*:%s*(%d%d?)",sets) and sw("^(%.%d+)",adds) - elseif sw("^(%d+)[/\\%s,-]?%s*") then --print("$Digits") - x, c = tonumber(sw[1]), len(sw[1]) - if (x >= 70) or (m and d and (not y)) or (c > 3) then - sety( x + ((x >= 100 or c>3)and 0 or 1900) ) - else - if m then setd(x) else m = x end - end - elseif sw("^(%a+)[/\\%s,-]?%s*") then --print("$Words") - x = sw[1] - if inlist(x, sl_months, 2, sw) then - if m and (not d) and (not y) then d, m = m, false end - setm(mod(sw[0],12)+1) - elseif inlist(x, sl_timezone, 2, sw) then - c = fix(sw[0]) -- ignore gmt and utc - if c ~= 0 then setz(c, x) end - elseif inlist(x, sl_weekdays, 2, sw) then - k = sw[0] - else - sw:back() - -- am pm bce ad ce bc - if sw("^([bB])%s*(%.?)%s*[Cc]%s*(%2)%s*[Ee]%s*(%2)%s*") or sw("^([bB])%s*(%.?)%s*[Cc]%s*(%2)%s*") then - e = e and error_dup() or -1 - elseif sw("^([aA])%s*(%.?)%s*[Dd]%s*(%2)%s*") or sw("^([cC])%s*(%.?)%s*[Ee]%s*(%2)%s*") then - e = e and error_dup() or 1 - elseif sw("^([PApa])%s*(%.?)%s*[Mm]?%s*(%2)%s*") then - x = lwr(sw[1]) -- there should be hour and it must be correct - if (not h) or (h > 12) or (h < 0) then return error_inv() end - if x == 'a' and h == 12 then h = 0 end -- am - if x == 'p' and h ~= 12 then h = h + 12 end -- pm - else error_syn() end - end - elseif not(sw("^([+-])(%d%d?):(%d%d)",setzc) or sw("^([+-])(%d+)",setzn) or sw("^[Zz]%s*$")) then -- sw{"([+-])",{"(%d%d?):(%d%d)","(%d+)"}} - error_syn("?") - end - sw("^%s*") until sw:finish() - --else print("$Iso(Date|Time|Zone)") - end - -- if date is given, it must be complete year, month & day - if (not y and not h) or ((m and not d) or (d and not m)) or ((m and w) or (m and j) or (j and w)) then return error_inv("!") end - -- fix month - if m then m = m - 1 end - -- fix year if we are on BCE - if e and e < 0 and y > 0 then y = 1 - y end - -- create date object - dn = (y and ((w and makedaynum_isoywd(y,w,u)) or (j and makedaynum(y, 0, j)) or makedaynum(y, m, d))) or DAYNUM_DEF - df = makedayfrc(h or 0, r or 0, s or 0, 0) + ((z or 0)*TICKSPERMIN) - --print("Zone",h,r,s,z,m,d,y,df) - return date_new(dn, df) -- no need to :normalize(); - end - local function date_fromtable(v) - local y, m, d = fix(v.year), getmontharg(v.month), fix(v.day) - local h, r, s, t = tonumber(v.hour), tonumber(v.min), tonumber(v.sec), tonumber(v.ticks) - -- atleast there is time or complete date - if (y or m or d) and (not(y and m and d)) then return error("incomplete table") end - return (y or h or r or s or t) and date_new(y and makedaynum(y, m, d) or DAYNUM_DEF, makedayfrc(h or 0, r or 0, s or 0, t or 0)) - end - local tmap = { - ['number'] = function(v) return date_epoch:copy():addseconds(v) end, - ['string'] = function(v) return date_parse(v) end, - ['boolean']= function(v) return date_fromtable(osdate(v and "!*t" or "*t")) end, - ['table'] = function(v) local ref = getmetatable(v) == dobj; return ref and v or date_fromtable(v), ref end - } - local function date_getdobj(v) - local o, r = (tmap[type(v)] or fnil)(v); - return (o and o:normalize() or error"invalid date time value"), r -- if r is true then o is a reference to a date obj - end ---#end -- not DATE_OBJECT_AFX - local function date_from(...) - local arg = pack(...) - local y, m, d = fix(arg[1]), getmontharg(arg[2]), fix(arg[3]) - local h, r, s, t = tonumber(arg[4] or 0), tonumber(arg[5] or 0), tonumber(arg[6] or 0), tonumber(arg[7] or 0) - if y and m and d and h and r and s and t then - return date_new(makedaynum(y, m, d), makedayfrc(h, r, s, t)):normalize() - else - return date_error_arg() - end - end - - --[[ THE DATE OBJECT METHODS ]]-- - function dobj:normalize() - local dn, df = fix(self.daynum), self.dayfrc - self.daynum, self.dayfrc = dn + floor(df/TICKSPERDAY), mod(df, TICKSPERDAY) - return (dn >= DAYNUM_MIN and dn <= DAYNUM_MAX) and self or error("date beyond imposed limits:"..self) - end - - function dobj:getdate() local y, m, d = breakdaynum(self.daynum) return y, m+1, d end - function dobj:gettime() return breakdayfrc(self.dayfrc) end - - function dobj:getclockhour() local h = self:gethours() return h>12 and mod(h,12) or (h==0 and 12 or h) end - - function dobj:getyearday() return yearday(self.daynum) + 1 end - function dobj:getweekday() return weekday(self.daynum) + 1 end -- in lua weekday is sunday = 1, monday = 2 ... - - function dobj:getyear() local r,_,_ = breakdaynum(self.daynum) return r end - function dobj:getmonth() local _,r,_ = breakdaynum(self.daynum) return r+1 end-- in lua month is 1 base - function dobj:getday() local _,_,r = breakdaynum(self.daynum) return r end - function dobj:gethours() return mod(floor(self.dayfrc/TICKSPERHOUR),HOURPERDAY) end - function dobj:getminutes() return mod(floor(self.dayfrc/TICKSPERMIN), MINPERHOUR) end - function dobj:getseconds() return mod(floor(self.dayfrc/TICKSPERSEC ),SECPERMIN) end - function dobj:getfracsec() return mod(floor(self.dayfrc/TICKSPERSEC ),SECPERMIN)+(mod(self.dayfrc,TICKSPERSEC)/TICKSPERSEC) end - function dobj:getticks(u) local x = mod(self.dayfrc,TICKSPERSEC) return u and ((x*u)/TICKSPERSEC) or x end - - function dobj:getweeknumber(wdb) - local wd, yd = weekday(self.daynum), yearday(self.daynum) - if wdb then - wdb = tonumber(wdb) - if wdb then - wd = mod(wd-(wdb-1),7)-- shift the week day base - else - return date_error_arg() - end - end - return (yd < wd and 0) or (floor(yd/7) + ((mod(yd, 7)>=wd) and 1 or 0)) - end - - function dobj:getisoweekday() return mod(weekday(self.daynum)-1,7)+1 end -- sunday = 7, monday = 1 ... - function dobj:getisoweeknumber() return (isowy(self.daynum)) end - function dobj:getisoyear() return isoy(self.daynum) end - function dobj:getisodate() - local w, y = isowy(self.daynum) - return y, w, self:getisoweekday() - end - function dobj:setisoyear(y, w, d) - local cy, cw, cd = self:getisodate() - if y then cy = fix(tonumber(y))end - if w then cw = fix(tonumber(w))end - if d then cd = fix(tonumber(d))end - if cy and cw and cd then - self.daynum = makedaynum_isoywd(cy, cw, cd) - return self:normalize() - else - return date_error_arg() - end - end - - function dobj:setisoweekday(d) return self:setisoyear(nil, nil, d) end - function dobj:setisoweeknumber(w,d) return self:setisoyear(nil, w, d) end - - function dobj:setyear(y, m, d) - local cy, cm, cd = breakdaynum(self.daynum) - if y then cy = fix(tonumber(y))end - if m then cm = getmontharg(m) end - if d then cd = fix(tonumber(d))end - if cy and cm and cd then - self.daynum = makedaynum(cy, cm, cd) - return self:normalize() - else - return date_error_arg() - end - end - - function dobj:setmonth(m, d)return self:setyear(nil, m, d) end - function dobj:setday(d) return self:setyear(nil, nil, d) end - - function dobj:sethours(h, m, s, t) - local ch,cm,cs,ck = breakdayfrc(self.dayfrc) - ch, cm, cs, ck = tonumber(h or ch), tonumber(m or cm), tonumber(s or cs), tonumber(t or ck) - if ch and cm and cs and ck then - self.dayfrc = makedayfrc(ch, cm, cs, ck) - return self:normalize() - else - return date_error_arg() - end - end - - function dobj:setminutes(m,s,t) return self:sethours(nil, m, s, t) end - function dobj:setseconds(s, t) return self:sethours(nil, nil, s, t) end - function dobj:setticks(t) return self:sethours(nil, nil, nil, t) end - - function dobj:spanticks() return (self.daynum*TICKSPERDAY + self.dayfrc) end - function dobj:spanseconds() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERSEC end - function dobj:spanminutes() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERMIN end - function dobj:spanhours() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERHOUR end - function dobj:spandays() return (self.daynum*TICKSPERDAY + self.dayfrc)/TICKSPERDAY end - - function dobj:addyears(y, m, d) - local cy, cm, cd = breakdaynum(self.daynum) - if y then y = fix(tonumber(y))else y = 0 end - if m then m = fix(tonumber(m))else m = 0 end - if d then d = fix(tonumber(d))else d = 0 end - if y and m and d then - self.daynum = makedaynum(cy+y, cm+m, cd+d) - return self:normalize() - else - return date_error_arg() - end - end - - function dobj:addmonths(m, d) - return self:addyears(nil, m, d) - end - - local function dobj_adddayfrc(self,n,pt,pd) - n = tonumber(n) - if n then - local x = floor(n/pd); - self.daynum = self.daynum + x; - self.dayfrc = self.dayfrc + (n-x*pd)*pt; - return self:normalize() - else - return date_error_arg() - end - end - function dobj:adddays(n) return dobj_adddayfrc(self,n,TICKSPERDAY,1) end - function dobj:addhours(n) return dobj_adddayfrc(self,n,TICKSPERHOUR,HOURPERDAY) end - function dobj:addminutes(n) return dobj_adddayfrc(self,n,TICKSPERMIN,MINPERDAY) end - function dobj:addseconds(n) return dobj_adddayfrc(self,n,TICKSPERSEC,SECPERDAY) end - function dobj:addticks(n) return dobj_adddayfrc(self,n,1,TICKSPERDAY) end - local tvspec = { - -- Abbreviated weekday name (Sun) - ['%a']=function(self) return sl_weekdays[weekday(self.daynum) + 7] end, - -- Full weekday name (Sunday) - ['%A']=function(self) return sl_weekdays[weekday(self.daynum)] end, - -- Abbreviated month name (Dec) - ['%b']=function(self) return sl_months[self:getmonth() - 1 + 12] end, - -- Full month name (December) - ['%B']=function(self) return sl_months[self:getmonth() - 1] end, - -- Year/100 (19, 20, 30) - ['%C']=function(self) return fmt("%.2d", fix(self:getyear()/100)) end, - -- The day of the month as a number (range 1 - 31) - ['%d']=function(self) return fmt("%.2d", self:getday()) end, - -- year for ISO 8601 week, from 00 (79) - ['%g']=function(self) return fmt("%.2d", mod(self:getisoyear() ,100)) end, - -- year for ISO 8601 week, from 0000 (1979) - ['%G']=function(self) return fmt("%.4d", self:getisoyear()) end, - -- same as %b - ['%h']=function(self) return self:fmt0("%b") end, - -- hour of the 24-hour day, from 00 (06) - ['%H']=function(self) return fmt("%.2d", self:gethours()) end, - -- The hour as a number using a 12-hour clock (01 - 12) - ['%I']=function(self) return fmt("%.2d", self:getclockhour()) end, - -- The day of the year as a number (001 - 366) - ['%j']=function(self) return fmt("%.3d", self:getyearday()) end, - -- Month of the year, from 01 to 12 - ['%m']=function(self) return fmt("%.2d", self:getmonth()) end, - -- Minutes after the hour 55 - ['%M']=function(self) return fmt("%.2d", self:getminutes())end, - -- AM/PM indicator (AM) - ['%p']=function(self) return sl_meridian[self:gethours() > 11 and 1 or -1] end, --AM/PM indicator (AM) - -- The second as a number (59, 20 , 01) - ['%S']=function(self) return fmt("%.2d", self:getseconds()) end, - -- ISO 8601 day of the week, to 7 for Sunday (7, 1) - ['%u']=function(self) return self:getisoweekday() end, - -- Sunday week of the year, from 00 (48) - ['%U']=function(self) return fmt("%.2d", self:getweeknumber()) end, - -- ISO 8601 week of the year, from 01 (48) - ['%V']=function(self) return fmt("%.2d", self:getisoweeknumber()) end, - -- The day of the week as a decimal, Sunday being 0 - ['%w']=function(self) return self:getweekday() - 1 end, - -- Monday week of the year, from 00 (48) - ['%W']=function(self) return fmt("%.2d", self:getweeknumber(2)) end, - -- The year as a number without a century (range 00 to 99) - ['%y']=function(self) return fmt("%.2d", mod(self:getyear() ,100)) end, - -- Year with century (2000, 1914, 0325, 0001) - ['%Y']=function(self) return fmt("%.4d", self:getyear()) end, - -- Time zone offset, the date object is assumed local time (+1000, -0230) - ['%z']=function(self) local b = -self:getbias(); local x = abs(b); return fmt("%s%.4d", b < 0 and "-" or "+", fix(x/60)*100 + floor(mod(x,60))) end, - -- Time zone name, the date object is assumed local time - ['%Z']=function(self) return self:gettzname() end, - -- Misc -- - -- Year, if year is in BCE, prints the BCE Year representation, otherwise result is similar to "%Y" (1 BCE, 40 BCE) - ['%\b']=function(self) local x = self:getyear() return fmt("%.4d%s", x>0 and x or (-x+1), x>0 and "" or " BCE") end, - -- Seconds including fraction (59.998, 01.123) - ['%\f']=function(self) local x = self:getfracsec() return fmt("%s%.9f",x >= 10 and "" or "0", x) end, - -- percent character % - ['%%']=function(self) return "%" end, - -- Group Spec -- - -- 12-hour time, from 01:00:00 AM (06:55:15 AM); same as "%I:%M:%S %p" - ['%r']=function(self) return self:fmt0("%I:%M:%S %p") end, - -- hour:minute, from 01:00 (06:55); same as "%I:%M" - ['%R']=function(self) return self:fmt0("%I:%M") end, - -- 24-hour time, from 00:00:00 (06:55:15); same as "%H:%M:%S" - ['%T']=function(self) return self:fmt0("%H:%M:%S") end, - -- month/day/year from 01/01/00 (12/02/79); same as "%m/%d/%y" - ['%D']=function(self) return self:fmt0("%m/%d/%y") end, - -- year-month-day (1979-12-02); same as "%Y-%m-%d" - ['%F']=function(self) return self:fmt0("%Y-%m-%d") end, - -- The preferred date and time representation; same as "%x %X" - ['%c']=function(self) return self:fmt0("%x %X") end, - -- The preferred date representation, same as "%a %b %d %\b" - ['%x']=function(self) return self:fmt0("%a %b %d %\b") end, - -- The preferred time representation, same as "%H:%M:%\f" - ['%X']=function(self) return self:fmt0("%H:%M:%\f") end, - -- GroupSpec -- - -- Iso format, same as "%Y-%m-%dT%T" - ['${iso}'] = function(self) return self:fmt0("%Y-%m-%dT%T") end, - -- http format, same as "%a, %d %b %Y %T GMT" - ['${http}'] = function(self) return self:fmt0("%a, %d %b %Y %T GMT") end, - -- ctime format, same as "%a %b %d %T GMT %Y" - ['${ctime}'] = function(self) return self:fmt0("%a %b %d %T GMT %Y") end, - -- RFC850 format, same as "%A, %d-%b-%y %T GMT" - ['${rfc850}'] = function(self) return self:fmt0("%A, %d-%b-%y %T GMT") end, - -- RFC1123 format, same as "%a, %d %b %Y %T GMT" - ['${rfc1123}'] = function(self) return self:fmt0("%a, %d %b %Y %T GMT") end, - -- asctime format, same as "%a %b %d %T %Y" - ['${asctime}'] = function(self) return self:fmt0("%a %b %d %T %Y") end, - } - function dobj:fmt0(str) return (gsub(str, "%%[%a%%\b\f]", function(x) local f = tvspec[x];return (f and f(self)) or x end)) end - function dobj:fmt(str) - str = str or self.fmtstr or fmtstr - return self:fmt0((gmatch(str, "${%w+}")) and (gsub(str, "${%w+}", function(x)local f=tvspec[x];return (f and f(self)) or x end)) or str) - end - - function dobj.__lt(a, b) if (a.daynum == b.daynum) then return (a.dayfrc < b.dayfrc) else return (a.daynum < b.daynum) end end - function dobj.__le(a, b) if (a.daynum == b.daynum) then return (a.dayfrc <= b.dayfrc) else return (a.daynum <= b.daynum) end end - function dobj.__eq(a, b)return (a.daynum == b.daynum) and (a.dayfrc == b.dayfrc) end - function dobj.__sub(a,b) - local d1, d2 = date_getdobj(a), date_getdobj(b) - local d0 = d1 and d2 and date_new(d1.daynum - d2.daynum, d1.dayfrc - d2.dayfrc) - return d0 and d0:normalize() - end - function dobj.__add(a,b) - local d1, d2 = date_getdobj(a), date_getdobj(b) - local d0 = d1 and d2 and date_new(d1.daynum + d2.daynum, d1.dayfrc + d2.dayfrc) - return d0 and d0:normalize() - end - function dobj.__concat(a, b) return tostring(a) .. tostring(b) end - function dobj:__tostring() return self:fmt() end - - function dobj:copy() return date_new(self.daynum, self.dayfrc) end - ---[[ THE LOCAL DATE OBJECT METHODS ]]-- - function dobj:tolocal() - local dn,df = self.daynum, self.dayfrc - local bias = getbiasutc2(self) - if bias then - -- utc = local + bias; local = utc - bias - self.daynum = dn - self.dayfrc = df - bias*TICKSPERSEC - return self:normalize() - else - return nil - end - end - - function dobj:toutc() - local dn,df = self.daynum, self.dayfrc - local bias = getbiasloc2(dn, df) - if bias then - -- utc = local + bias; - self.daynum = dn - self.dayfrc = df + bias*TICKSPERSEC - return self:normalize() - else - return nil - end - end - - function dobj:getbias() return (getbiasloc2(self.daynum, self.dayfrc))/SECPERMIN end - - function dobj:gettzname() - local _, tvu, _ = getbiasloc2(self.daynum, self.dayfrc) - return tvu and osdate("%Z",tvu) or "" - end - ---#if not DATE_OBJECT_AFX then - function date.time(h, r, s, t) - h, r, s, t = tonumber(h or 0), tonumber(r or 0), tonumber(s or 0), tonumber(t or 0) - if h and r and s and t then - return date_new(DAYNUM_DEF, makedayfrc(h, r, s, t)) - else - return date_error_arg() - end - end - - function date:__call(...) - local arg = pack(...) - if arg.n > 1 then return (date_from(...)) - elseif arg.n == 0 then return (date_getdobj(false)) - else local o, r = date_getdobj(arg[1]); return r and o:copy() or o end - end - - date.diff = dobj.__sub - - function date.isleapyear(v) - local y = fix(v); - if not y then - y = date_getdobj(v) - y = y and y:getyear() - end - return isleapyear(y+0) - end - - function date.epoch() return date_epoch:copy() end - - function date.isodate(y,w,d) return date_new(makedaynum_isoywd(y + 0, w and (w+0) or 1, d and (d+0) or 1), 0) end - --- Internal functions - function date.fmt(str) if str then fmtstr = str end; return fmtstr end - function date.daynummin(n) DAYNUM_MIN = (n and n < DAYNUM_MAX) and n or DAYNUM_MIN return n and DAYNUM_MIN or date_new(DAYNUM_MIN, 0):normalize()end - function date.daynummax(n) DAYNUM_MAX = (n and n > DAYNUM_MIN) and n or DAYNUM_MAX return n and DAYNUM_MAX or date_new(DAYNUM_MAX, 0):normalize()end - function date.ticks(t) if t then setticks(t) end return TICKSPERSEC end ---#end -- not DATE_OBJECT_AFX - - local tm = osdate("!*t", 0); - if tm then - date_epoch = date_new(makedaynum(tm.year, tm.month - 1, tm.day), makedayfrc(tm.hour, tm.min, tm.sec, 0)) - -- the distance from our epoch to os epoch in daynum - DATE_EPOCH = date_epoch and date_epoch:spandays() - else -- error will be raise only if called! - date_epoch = setmetatable({},{__index = function() error("failed to get the epoch date") end}) - end - ---#if not DATE_OBJECT_AFX then -return date ---#else ---$return date_from ---#end diff --git a/website/backend/app/libs/db.lua b/website/backend/app/libs/db.lua deleted file mode 100755 index 43d8069..0000000 --- a/website/backend/app/libs/db.lua +++ /dev/null @@ -1,135 +0,0 @@ -local sgsub = string.gsub -local tinsert = table.insert -local type = type -local ipairs = ipairs -local pairs = pairs -local mysql = require("resty.mysql") -local cjson = require("cjson") -local utils = require("app.libs.utils") -local config = require("app.config.config") -local DB = {} - -function DB:new(conf) - conf = conf or config.mysql - local instance = {} - instance.conf = conf - setmetatable(instance, { __index = self}) - return instance -end - -function DB:exec(sql) - if not sql then - ngx.log(ngx.ERR, "sql parse error! please check") - return nil, "sql parse error! please check" - end - - local conf = self.conf - local db, err = mysql:new() - if not db then - ngx.say("failed to instantiate mysql: ", err) - return - end - db:set_timeout(conf.timeout) -- 1 sec - - local ok, err, errno, sqlstate = db:connect(conf.connect_config) - if not ok then - ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate) - return - end - - ngx.log(ngx.ERR, "connected to mysql, reused_times:", db:get_reused_times(), " sql:", sql) - - db:query("SET NAMES utf8") - local res, err, errno, sqlstate = db:query(sql) - if not res then - ngx.log(ngx.ERR, "bad result: ", err, ": ", errno, ": ", sqlstate, ".") - end - - local ok, err = db:set_keepalive(conf.pool_config.max_idle_timeout, conf.pool_config.pool_size) - if not ok then - ngx.say("failed to set keepalive: ", err) - end - - return res, err, errno, sqlstate -end - - - -function DB:query(sql, params) - sql = self:parse_sql(sql, params) - return self:exec(sql) -end - -function DB:select(sql, params) - return self:query(sql, params) -end - -function DB:insert(sql, params) - local res, err, errno, sqlstate = self:query(sql, params) - if res and not err then - return res.insert_id, err - else - return res, err - end -end - -function DB:update(sql, params) - return self:query(sql, params) -end - -function DB:delete(sql, params) - local res, err, errno, sqlstate = self:query(sql, params) - if res and not err then - return res.affected_rows, err - else - return res, err - end -end - -local function split(str, delimiter) - if str==nil or str=='' or delimiter==nil then - return nil - end - - local result = {} - for match in (str..delimiter):gmatch("(.-)"..delimiter) do - tinsert(result, match) - end - return result -end - - -local function compose(t, params) - if t==nil or params==nil or type(t)~="table" or type(params)~="table" or #t~=#params+1 or #t==0 then - return nil - else - local result = t[1] - for i=1, #params do - result = result .. params[i].. t[i+1] - end - return result - end -end - - -function DB:parse_sql(sql, params) - if not params or not utils.table_is_array(params) or #params == 0 then - return sql - end - - local new_params = {} - for i, v in ipairs(params) do - if v and type(v) == "string" then - v = ngx.quote_sql_str(v) - end - - tinsert(new_params, v) - end - - local t = split(sql,"?") - local sql = compose(t, new_params) - - return sql -end - -return DB diff --git a/website/backend/app/libs/inspect.lua b/website/backend/app/libs/inspect.lua deleted file mode 100755 index e2e3806..0000000 --- a/website/backend/app/libs/inspect.lua +++ /dev/null @@ -1,334 +0,0 @@ -local inspect ={ - _VERSION = 'inspect.lua 3.1.0', - _URL = 'http://github.com/kikito/inspect.lua', - _DESCRIPTION = 'human-readable representations of tables', - _LICENSE = [[ - MIT LICENSE - - Copyright (c) 2013 Enrique García Cota - - Permission is hereby granted, free of charge, to any person obtaining a - copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, - distribute, sublicense, and/or sell copies of the Software, and to - permit persons to whom the Software is furnished to do so, subject to - the following conditions: - - The above copyright notice and this permission notice shall be included - in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ]] -} - -local tostring = tostring - -inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end}) -inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end}) - -local function rawpairs(t) - return next, t, nil -end - --- Apostrophizes the string if it has quotes, but not aphostrophes --- Otherwise, it returns a regular quoted string -local function smartQuote(str) - if str:match('"') and not str:match("'") then - return "'" .. str .. "'" - end - return '"' .. str:gsub('"', '\\"') .. '"' -end - --- \a => '\\a', \0 => '\\0', 31 => '\31' -local shortControlCharEscapes = { - ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", - ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v" -} -local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031 -for i=0, 31 do - local ch = string.char(i) - if not shortControlCharEscapes[ch] then - shortControlCharEscapes[ch] = "\\"..i - longControlCharEscapes[ch] = string.format("\\%03d", i) - end -end - -local function escape(str) - return (str:gsub("\\", "\\\\") - :gsub("(%c)%f[0-9]", longControlCharEscapes) - :gsub("%c", shortControlCharEscapes)) -end - -local function isIdentifier(str) - return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) -end - -local function isSequenceKey(k, sequenceLength) - return type(k) == 'number' - and 1 <= k - and k <= sequenceLength - and math.floor(k) == k -end - -local defaultTypeOrders = { - ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, - ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 -} - -local function sortKeys(a, b) - local ta, tb = type(a), type(b) - - -- strings and numbers are sorted numerically/alphabetically - if ta == tb and (ta == 'string' or ta == 'number') then return a < b end - - local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb] - -- Two default types are compared according to the defaultTypeOrders table - if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb] - elseif dta then return true -- default types before custom ones - elseif dtb then return false -- custom types after default ones - end - - -- custom types are sorted out alphabetically - return ta < tb -end - --- For implementation reasons, the behavior of rawlen & # is "undefined" when --- tables aren't pure sequences. So we implement our own # operator. -local function getSequenceLength(t) - local len = 1 - local v = rawget(t,len) - while v ~= nil do - len = len + 1 - v = rawget(t,len) - end - return len - 1 -end - -local function getNonSequentialKeys(t) - local keys, keysLength = {}, 0 - local sequenceLength = getSequenceLength(t) - for k,_ in rawpairs(t) do - if not isSequenceKey(k, sequenceLength) then - keysLength = keysLength + 1 - keys[keysLength] = k - end - end - table.sort(keys, sortKeys) - return keys, keysLength, sequenceLength -end - -local function countTableAppearances(t, tableAppearances) - tableAppearances = tableAppearances or {} - - if type(t) == 'table' then - if not tableAppearances[t] then - tableAppearances[t] = 1 - for k,v in rawpairs(t) do - countTableAppearances(k, tableAppearances) - countTableAppearances(v, tableAppearances) - end - countTableAppearances(getmetatable(t), tableAppearances) - else - tableAppearances[t] = tableAppearances[t] + 1 - end - end - - return tableAppearances -end - -local copySequence = function(s) - local copy, len = {}, #s - for i=1, len do copy[i] = s[i] end - return copy, len -end - -local function makePath(path, ...) - local keys = {...} - local newPath, len = copySequence(path) - for i=1, #keys do - newPath[len + i] = keys[i] - end - return newPath -end - -local function processRecursive(process, item, path, visited) - if item == nil then return nil end - if visited[item] then return visited[item] end - - local processed = process(item, path) - if type(processed) == 'table' then - local processedCopy = {} - visited[item] = processedCopy - local processedKey - - for k,v in rawpairs(processed) do - processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) - if processedKey ~= nil then - processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) - end - end - - local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) - if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field - setmetatable(processedCopy, mt) - processed = processedCopy - end - return processed -end - - - -------------------------------------------------------------------- - -local Inspector = {} -local Inspector_mt = {__index = Inspector} - -function Inspector:puts(...) - local args = {...} - local buffer = self.buffer - local len = #buffer - for i=1, #args do - len = len + 1 - buffer[len] = args[i] - end -end - -function Inspector:down(f) - self.level = self.level + 1 - f() - self.level = self.level - 1 -end - -function Inspector:tabify() - self:puts(self.newline, string.rep(self.indent, self.level)) -end - -function Inspector:alreadyVisited(v) - return self.ids[v] ~= nil -end - -function Inspector:getId(v) - local id = self.ids[v] - if not id then - local tv = type(v) - id = (self.maxIds[tv] or 0) + 1 - self.maxIds[tv] = id - self.ids[v] = id - end - return tostring(id) -end - -function Inspector:putKey(k) - if isIdentifier(k) then return self:puts(k) end - self:puts("[") - self:putValue(k) - self:puts("]") -end - -function Inspector:putTable(t) - if t == inspect.KEY or t == inspect.METATABLE then - self:puts(tostring(t)) - elseif self:alreadyVisited(t) then - self:puts('') - elseif self.level >= self.depth then - self:puts('{...}') - else - if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end - - local nonSequentialKeys, nonSequentialKeysLength, sequenceLength = getNonSequentialKeys(t) - local mt = getmetatable(t) - - self:puts('{') - self:down(function() - local count = 0 - for i=1, sequenceLength do - if count > 0 then self:puts(',') end - self:puts(' ') - self:putValue(t[i]) - count = count + 1 - end - - for i=1, nonSequentialKeysLength do - local k = nonSequentialKeys[i] - if count > 0 then self:puts(',') end - self:tabify() - self:putKey(k) - self:puts(' = ') - self:putValue(t[k]) - count = count + 1 - end - - if type(mt) == 'table' then - if count > 0 then self:puts(',') end - self:tabify() - self:puts(' = ') - self:putValue(mt) - end - end) - - if nonSequentialKeysLength > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing } - self:tabify() - elseif sequenceLength > 0 then -- array tables have one extra space before closing } - self:puts(' ') - end - - self:puts('}') - end -end - -function Inspector:putValue(v) - local tv = type(v) - - if tv == 'string' then - self:puts(smartQuote(escape(v))) - elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or - tv == 'cdata' or tv == 'ctype' then - self:puts(tostring(v)) - elseif tv == 'table' then - self:putTable(v) - else - self:puts('<', tv, ' ', self:getId(v), '>') - end -end - -------------------------------------------------------------------- - -function inspect.inspect(root, options) - options = options or {} - - local depth = options.depth or math.huge - local newline = options.newline or '\n' - local indent = options.indent or ' ' - local process = options.process - - if process then - root = processRecursive(process, root, {}, {}) - end - - local inspector = setmetatable({ - depth = depth, - level = 0, - buffer = {}, - ids = {}, - maxIds = {}, - newline = newline, - indent = indent, - tableAppearances = countTableAppearances(root) - }, Inspector_mt) - - inspector:putValue(root) - - return table.concat(inspector.buffer) -end - -setmetatable(inspect, { __call = function(_, ...) return inspect.inspect(...) end }) - -return inspect - diff --git a/website/backend/app/libs/ip_location.lua b/website/backend/app/libs/ip_location.lua deleted file mode 100755 index 8639691..0000000 --- a/website/backend/app/libs/ip_location.lua +++ /dev/null @@ -1,281 +0,0 @@ -#!/usr/bin/env lua -local ngx = require('ngx') - -local setmetatable = setmetatable -local byte = string.byte -local match = string.match -local rawget = rawget -local cjson = require "cjson" - -local ok, new_tab = pcall(require, "table.new") -if not ok or type(new_tab) ~= "function" then - new_tab = function(narr, nrec) return {} end -end - -local _M = new_tab(0, 54) - -local mt = { __index = _M } - -_M._VERSION = '0.01' - --- 测试TOKEN 及 地址 -local token = "cc87f3c77747bccbaaee35006da1ebb65e0bad57" -local ipIpUrl = "http://freeapi.ipip.net/" - --- 切割字符串 -local function split(s, p) - local rt = {} - string.gsub(s, '[^' .. p .. ']+', function(w) table.insert(rt, w) end) - return rt -end - --- 拓展 -string.split = function(str, pattern) - pattern = pattern or "[^%s]+" - if pattern:len() == 0 then pattern = "[^%s]+" end - local parts = { __index = table.insert } - setmetatable(parts, parts) - str:gsub(pattern, parts) - setmetatable(parts, nil) - parts.__index = nil - return parts -end - - --- 转成整型 -local function bit32lshift(b, disp) - return (b * 2 ^ disp) % 2 ^ 32 -end - --- 转换ip -local function byteToUint32(a, b, c, d) - local _int = 0 - if a then - _int = _int + bit32lshift(a, 24) - end - _int = _int + bit32lshift(b, 16) - _int = _int + bit32lshift(c, 8) - _int = _int + d - if _int >= 0 then - return _int - else - return _int + math.pow(2, 32) - end -end - --- 返回数据模版 -local response_template = { - "country", -- // 国家 - "city", -- // 省会或直辖市(国内) - "region", -- // 地区或城市 (国内) - "place", -- // 学校或单位 (国内) - "operator", -- // 运营商字段(只有购买了带有运营商版本的数据库才会有) - "latitude", -- // 纬度 (每日版本提供) - "longitude", -- // 经度 (每日版本提供) - "timeZone", -- // 时区一, 可能不存在 (每日版本提供) - "timeZoneCode", -- // 时区二, 可能不存在 (每日版本提供) - "administrativeAreaCode", -- // 中国行政区划代码 (每日版本提供) - "internationalPhoneCode", -- // 国际电话代码 (每日版本提供) - "countryTwoDigitCode", -- // 国家二位代码 (每日版本提供) - "worldContinentCode" -- // 世界大洲代码 (每日版本提供) -} - --- 转成 table类型 -local function toTable(location) - local response = {} - for k, v in ipairs(location) do - response[response_template[k]] = v - end - - return response -end - --- 发送请求 -local function sendRequest(url, method, body, headers) - local http = require "resty.http" - local httpc = http.new() - local res, err = httpc:request_uri(url, { - method = method, - body = body, - headers = headers - }) - - if not res then - ngx.log(ngx.ERR, "failed to request: " .. err .. url) - return nil, err - end - - if 200 ~= res.status then - ngx.log(ngx.ERR, res.status) - return nil, res.status - end - - return res.body -end - --- 初始化 -function _M.new(self, address, token) - return setmetatable({ _ipAddress = address, _token = token, _ipBinaryFilePath = require("config.app").ip_binary_file_path }, mt) -end - - --- 从文件获取地区信息 -function _M.ipLocation(self, ipstr) - local ipBinaryFilePath = rawget(self, "_ipBinaryFilePath") - if not ipBinaryFilePath then - ngx.log(ngx.ERR, ipBinaryFilePath) - return nil, " file ptah not initialized" - end - - local ip1, ip2, ip3, ip4 = match(ipstr, "(%d+).(%d+).(%d+).(%d+)") - local ip_uint32 = byteToUint32(ip1, ip2, ip3, ip4) - local file = io.open(ipBinaryFilePath) - if file == nil then - return nil - end - - local str = file:read(4) - local offset_len = byteToUint32(byte(str, 1), byte(str, 2), byte(str, 3), byte(str, 4)) - - local indexBuffer = file:read(offset_len - 4) - - local tmp_offset = ip1 * 4 - local start_len = byteToUint32(byte(indexBuffer, tmp_offset + 4), byte(indexBuffer, tmp_offset + 3), byte(indexBuffer, tmp_offset + 2), byte(indexBuffer, tmp_offset + 1)) - - local max_comp_len = offset_len - 1028 - local start = start_len * 8 + 1024 + 1 - local index_offset = -1 - local index_length = -1 - while start < max_comp_len do - local find_uint32 = byteToUint32(byte(indexBuffer, start), byte(indexBuffer, start + 1), byte(indexBuffer, start + 2), byte(indexBuffer, start + 3)) - if ip_uint32 <= find_uint32 then - index_offset = byteToUint32(0, byte(indexBuffer, start + 6), byte(indexBuffer, start + 5), byte(indexBuffer, start + 4)) - index_length = byte(indexBuffer, start + 7) - break - end - start = start + 8 - end - - if index_offset == -1 or index_length == -1 then - return nil - end - - local offset = offset_len + index_offset - 1024 - - file:seek("set", offset) - - return file:read(index_length) -end - --- 获取所有信息 -function _M.location(self) - local ipAddress = rawget(self, "_ipAddress") - if not ipAddress then - return nil, "not initialized" - end - - local address = self:ipLocation(ipAddress) - if not address then - ngx.log(ngx.ERR, { "ip address data nil" }) - return nil, "ip address data nil" - end - - if type(address) == "string" then - return toTable(split(address, "%s+")) - end - - return address -end - --- 通过api获取 -function _M.locationApi(self, sid, uid) - local ipAddress = rawget(self, "_ipAddress") - if not ipAddress then - return nil, "not initialized" - end - - local _token = rawget(self, "_token") - - local myToken = (_token and _token) or token - - local sign, err = ngx.md5("addr=" .. ipAddress .. "&token=" .. myToken) - - if not sign then - return nil, err - end - - local url = ipIpUrl .. "find" - - local headers = { - ["Token"] = myToken - } - - local params = "addr=" .. ipAddress .. "&sid=" .. sid .. "&uid=" .. uid .. "&sig=" .. sign - - local body, err = sendRequest(url, "GET", params, headers) - - if not body or #body < 1 then - return nil, err - end - - -- local body = [[{"ret":"ok","data":["中国","天津","天津","","鹏博士","39.128399","117.185112","Asia/Shanghai","UTC+8","120000","86","CN","AP"]}]] - local response = cjson.decode(body) - - if not response.data then - return response - end - - return toTable(response.data) -end - --- 通过免费的api获取 -function _M.locationApiFree(self) - local ipAddress = rawget(self, "_ipAddress") - if not ipAddress then - return nil, "not initialized" - end - - local url = ipIpUrl .. ipAddress - - local headers = { - ["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", - ["Cache-Control"] = "no-cache", - ["Connection"] = "keep-alive", - ["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36", - ["Content-Type"] = "application/x-www-form-urlencoded", - } - - local body, err = sendRequest(url, "GET", "", headers) - - if not body then - return nil, err - end - - return toTable(cjson.decode(body)) -end - --- 获取当前可访问状态 -function _M.apiStatus(self, token) - if not token then - local token = rawget(self, "_token") - if not token then - return nil, "not initialized" - end - end - - local url = ipIpUrl .. "find_status" - - local headers = { - ["Token"] = token - } - - local body, err = sendRequest(url, "GET", "", headers) - - if not body then - return nil, err - end - - return cjson.decode(body) -end - -return _M \ No newline at end of file diff --git a/website/backend/app/libs/log_api.lua b/website/backend/app/libs/log_api.lua deleted file mode 100755 index 8c562fb..0000000 --- a/website/backend/app/libs/log_api.lua +++ /dev/null @@ -1,49 +0,0 @@ -local table = table - --- 日志级别 -local log_level = { - LOG_DEFAULT = 1, - LOG_TRACE = 1, - LOG_DEBUG = 2, - LOG_INFO = 3, - LOG_WARN = 4, - LOG_ERROR = 5, - LOG_FATAL = 6, -} - -local defaultLevel = log_level.LOG_DEBUG - --- 错误日志 -- -local function logger(str, level, color) - return function (...) - if level >= defaultLevel then - local info = table.pack(...) - info[#info+1] = "\n" - info[#info+1] = "\x1b[0m" - ngx.log(ngx.ERR, string.format("%s%s", color, str), table.unpack(info)) - end - end -end - -local M = { - TRACE = logger("[trace]", log_level.LOG_TRACE, "\x1b[35m"), - DEBUG = logger("[debug]", log_level.LOG_DEBUG, "\x1b[32m"), - INFO = logger("[info]", log_level.LOG_INFO, "\x1b[34m"), - WARN = logger("[warning]", log_level.LOG_WARN, "\x1b[33m"), - ERROR = logger("[error]", log_level.LOG_ERROR, "\x1b[31m"), - FATAL = logger("[fatal]", log_level.LOG_FATAL,"\x1b[31m") -} - --- 错误日志 -- - -setmetatable(M, { - __call = function(t) - for k, v in pairs(t) do - _G[k] = v - end - end, -}) - -M() - -return M diff --git a/website/backend/app/libs/random.lua b/website/backend/app/libs/random.lua deleted file mode 100755 index 96f3961..0000000 --- a/website/backend/app/libs/random.lua +++ /dev/null @@ -1,86 +0,0 @@ -local require = require -local ffi = require "ffi" -local ffi_cdef = ffi.cdef -local ffi_new = ffi.new -local ffi_str = ffi.string -local ffi_typeof = ffi.typeof -local C = ffi.C -local type = type -local random = math.random -local randomseed = math.randomseed -local concat = table.concat -local tostring = tostring -local pcall = pcall - -ffi_cdef[[ -typedef unsigned char u_char; -u_char * ngx_hex_dump(u_char *dst, const u_char *src, size_t len); -int RAND_bytes(u_char *buf, int num); -]] - -local ok, new_tab = pcall(require, "table.new") -if not ok then - new_tab = function () return {} end -end - -local alnum = { - 'A','B','C','D','E','F','G','H','I','J','K','L','M', - 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', - 'a','b','c','d','e','f','g','h','i','j','k','l','m', - 'n','o','p','q','r','s','t','u','v','w','x','y','z', - '0','1','2','3','4','5','6','7','8','9' -} - -local t = ffi_typeof "uint8_t[?]" - -local function bytes(len, format) - local s = ffi_new(t, len) - C.RAND_bytes(s, len) - if not s then return nil end - if format == "hex" then - local b = ffi_new(t, len * 2) - C.ngx_hex_dump(b, s, len) - return ffi_str(b, len * 2), true - else - return ffi_str(s, len), true - end -end - -local function seed() - local a,b,c,d = bytes(4):byte(1, 4) - return randomseed(a * 0x1000000 + b * 0x10000 + c * 0x100 + d) -end - -local function number(min, max, reseed) - if reseed then seed() end - if min and max then return random(min, max) - elseif min then return random(min) - else return random() end -end - -local function token(len, chars, sep) - chars = chars or alnum - local count - local token = new_tab(len, 0) - if type(chars) ~= "table" then - chars = tostring(chars) - count = #chars - local n - for i=1,len do - n = number(1, count) - token[i] = chars:sub(n, n) - end - else - count = #chars - for i=1,len do token[i] = chars[number(1, count)] end - end - return concat(token, sep) -end - -seed() - -return { - bytes = bytes, - number = number, - token = token -} \ No newline at end of file diff --git a/website/backend/app/libs/resty/http/http.lua b/website/backend/app/libs/resty/http/http.lua deleted file mode 100755 index 8655601..0000000 --- a/website/backend/app/libs/resty/http/http.lua +++ /dev/null @@ -1,1064 +0,0 @@ -local http_headers = require "resty.http.http_headers" - -local ngx = ngx -local ngx_socket_tcp = ngx.socket.tcp -local ngx_req = ngx.req -local ngx_req_socket = ngx_req.socket -local ngx_req_get_headers = ngx_req.get_headers -local ngx_req_get_method = ngx_req.get_method -local str_gmatch = string.gmatch -local str_lower = string.lower -local str_upper = string.upper -local str_find = string.find -local str_sub = string.sub -local tbl_concat = table.concat -local tbl_insert = table.insert -local ngx_encode_args = ngx.encode_args -local ngx_re_match = ngx.re.match -local ngx_re_gmatch = ngx.re.gmatch -local ngx_re_sub = ngx.re.sub -local ngx_re_gsub = ngx.re.gsub -local ngx_re_find = ngx.re.find -local ngx_log = ngx.log -local ngx_DEBUG = ngx.DEBUG -local ngx_ERR = ngx.ERR -local ngx_var = ngx.var -local ngx_print = ngx.print -local ngx_header = ngx.header -local co_yield = coroutine.yield -local co_create = coroutine.create -local co_status = coroutine.status -local co_resume = coroutine.resume -local setmetatable = setmetatable -local tonumber = tonumber -local tostring = tostring -local unpack = unpack -local rawget = rawget -local select = select -local ipairs = ipairs -local pairs = pairs -local pcall = pcall -local type = type - - --- http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.5.1 -local HOP_BY_HOP_HEADERS = { - ["connection"] = true, - ["keep-alive"] = true, - ["proxy-authenticate"] = true, - ["proxy-authorization"] = true, - ["te"] = true, - ["trailers"] = true, - ["transfer-encoding"] = true, - ["upgrade"] = true, - ["content-length"] = true, -- Not strictly hop-by-hop, but Nginx will deal - -- with this (may send chunked for example). -} - - --- Reimplemented coroutine.wrap, returning "nil, err" if the coroutine cannot --- be resumed. This protects user code from inifite loops when doing things like --- repeat --- local chunk, err = res.body_reader() --- if chunk then -- <-- This could be a string msg in the core wrap function. --- ... --- end --- until not chunk -local co_wrap = function(func) - local co = co_create(func) - if not co then - return nil, "could not create coroutine" - else - return function(...) - if co_status(co) == "suspended" then - return select(2, co_resume(co, ...)) - else - return nil, "can't resume a " .. co_status(co) .. " coroutine" - end - end - end -end - - --- Returns a new table, recursively copied from the one given. --- --- @param table table to be copied --- @return table -local function tbl_copy(orig) - local orig_type = type(orig) - local copy - if orig_type == "table" then - copy = {} - for orig_key, orig_value in next, orig, nil do - copy[tbl_copy(orig_key)] = tbl_copy(orig_value) - end - else -- number, string, boolean, etc - copy = orig - end - return copy -end - - -local _M = { - _VERSION = '0.12', -} -_M._USER_AGENT = "lua-resty-http/" .. _M._VERSION .. " (Lua) ngx_lua/" .. ngx.config.ngx_lua_version - -local mt = { __index = _M } - - -local HTTP = { - [1.0] = " HTTP/1.0\r\n", - [1.1] = " HTTP/1.1\r\n", -} - -local DEFAULT_PARAMS = { - method = "GET", - path = "/", - version = 1.1, -} - - -function _M.new(self) - local sock, err = ngx_socket_tcp() - if not sock then - return nil, err - end - return setmetatable({ sock = sock, keepalive = true }, mt) -end - - -function _M.set_timeout(self, timeout) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - return sock:settimeout(timeout) -end - - -function _M.set_timeouts(self, connect_timeout, send_timeout, read_timeout) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - return sock:settimeouts(connect_timeout, send_timeout, read_timeout) -end - - -function _M.ssl_handshake(self, ...) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - self.ssl = true - - return sock:sslhandshake(...) -end - - -function _M.connect(self, ...) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - self.host = select(1, ...) - self.port = select(2, ...) - - -- If port is not a number, this is likely a unix domain socket connection. - if type(self.port) ~= "number" then - self.port = nil - end - - self.keepalive = true - - return sock:connect(...) -end - - -function _M.set_keepalive(self, ...) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - if self.keepalive == true then - return sock:setkeepalive(...) - else - -- The server said we must close the connection, so we cannot setkeepalive. - -- If close() succeeds we return 2 instead of 1, to differentiate between - -- a normal setkeepalive() failure and an intentional close(). - local res, err = sock:close() - if res then - return 2, "connection must be closed" - else - return res, err - end - end -end - - -function _M.get_reused_times(self) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - return sock:getreusedtimes() -end - - -function _M.close(self) - local sock = self.sock - if not sock then - return nil, "not initialized" - end - - return sock:close() -end - - -local function _should_receive_body(method, code) - if method == "HEAD" then return nil end - if code == 204 or code == 304 then return nil end - if code >= 100 and code < 200 then return nil end - return true -end - - -function _M.parse_uri(self, uri, query_in_path) - if query_in_path == nil then query_in_path = true end - - local m, err = ngx_re_match(uri, [[^(?:(http[s]?):)?//([^:/\?]+)(?::(\d+))?([^\?]*)\??(.*)]], "jo") - - if not m then - if err then - return nil, "failed to match the uri: " .. uri .. ", " .. err - end - - return nil, "bad uri: " .. uri - else - -- If the URI is schemaless (i.e. //example.com) try to use our current - -- request scheme. - if not m[1] then - local scheme = ngx_var.scheme - if scheme == "http" or scheme == "https" then - m[1] = scheme - else - return nil, "schemaless URIs require a request context: " .. uri - end - end - - if m[3] then - m[3] = tonumber(m[3]) - else - if m[1] == "https" then - m[3] = 443 - else - m[3] = 80 - end - end - if not m[4] or "" == m[4] then m[4] = "/" end - - if query_in_path and m[5] and m[5] ~= "" then - m[4] = m[4] .. "?" .. m[5] - m[5] = nil - end - - return m, nil - end -end - - -local function _format_request(params) - local version = params.version - local headers = params.headers or {} - - local query = params.query or "" - if type(query) == "table" then - query = "?" .. ngx_encode_args(query) - elseif query ~= "" and str_sub(query, 1, 1) ~= "?" then - query = "?" .. query - end - - -- Initialize request - local req = { - str_upper(params.method), - " ", - params.path, - query, - HTTP[version], - -- Pre-allocate slots for minimum headers and carriage return. - true, - true, - true, - } - local c = 6 -- req table index it's faster to do this inline vs table.insert - - -- Append headers - for key, values in pairs(headers) do - if type(values) ~= "table" then - values = {values} - end - - key = tostring(key) - for _, value in pairs(values) do - req[c] = key .. ": " .. tostring(value) .. "\r\n" - c = c + 1 - end - end - - -- Close headers - req[c] = "\r\n" - - return tbl_concat(req) -end - - -local function _receive_status(sock) - local line, err = sock:receive("*l") - if not line then - return nil, nil, nil, err - end - - return tonumber(str_sub(line, 10, 12)), tonumber(str_sub(line, 6, 8)), str_sub(line, 14) -end - - -local function _receive_headers(sock) - local headers = http_headers.new() - - repeat - local line, err = sock:receive("*l") - if not line then - return nil, err - end - - local m, err = ngx_re_match(line, "([^:\\s]+):\\s*(.+)", "jo") - if not m then - break - end - - local key = m[1] - local val = m[2] - if headers[key] then - if type(headers[key]) ~= "table" then - headers[key] = { headers[key] } - end - tbl_insert(headers[key], tostring(val)) - else - headers[key] = tostring(val) - end - until ngx_re_find(line, "^\\s*$", "jo") - - return headers, nil -end - - -local function _chunked_body_reader(sock, default_chunk_size) - return co_wrap(function(max_chunk_size) - local remaining = 0 - local length - max_chunk_size = max_chunk_size or default_chunk_size - - repeat - -- If we still have data on this chunk - if max_chunk_size and remaining > 0 then - - if remaining > max_chunk_size then - -- Consume up to max_chunk_size - length = max_chunk_size - remaining = remaining - max_chunk_size - else - -- Consume all remaining - length = remaining - remaining = 0 - end - else -- This is a fresh chunk - - -- Receive the chunk size - local str, err = sock:receive("*l") - if not str then - co_yield(nil, err) - end - - length = tonumber(str, 16) - - if not length then - co_yield(nil, "unable to read chunksize") - end - - if max_chunk_size and length > max_chunk_size then - -- Consume up to max_chunk_size - remaining = length - max_chunk_size - length = max_chunk_size - end - end - - if length > 0 then - local str, err = sock:receive(length) - if not str then - co_yield(nil, err) - end - - max_chunk_size = co_yield(str) or default_chunk_size - - -- If we're finished with this chunk, read the carriage return. - if remaining == 0 then - sock:receive(2) -- read \r\n - end - else - -- Read the last (zero length) chunk's carriage return - sock:receive(2) -- read \r\n - end - - until length == 0 - end) -end - - -local function _body_reader(sock, content_length, default_chunk_size) - return co_wrap(function(max_chunk_size) - max_chunk_size = max_chunk_size or default_chunk_size - - if not content_length and max_chunk_size then - -- We have no length, but wish to stream. - -- HTTP 1.0 with no length will close connection, so read chunks to the end. - repeat - local str, err, partial = sock:receive(max_chunk_size) - if not str and err == "closed" then - co_yield(partial, err) - end - - max_chunk_size = tonumber(co_yield(str) or default_chunk_size) - if max_chunk_size and max_chunk_size < 0 then max_chunk_size = nil end - - if not max_chunk_size then - ngx_log(ngx_ERR, "Buffer size not specified, bailing") - break - end - until not str - - elseif not content_length then - -- We have no length but don't wish to stream. - -- HTTP 1.0 with no length will close connection, so read to the end. - co_yield(sock:receive("*a")) - - elseif not max_chunk_size then - -- We have a length and potentially keep-alive, but want everything. - co_yield(sock:receive(content_length)) - - else - -- We have a length and potentially a keep-alive, and wish to stream - -- the response. - local received = 0 - repeat - local length = max_chunk_size - if received + length > content_length then - length = content_length - received - end - - if length > 0 then - local str, err = sock:receive(length) - if not str then - co_yield(nil, err) - end - received = received + length - - max_chunk_size = tonumber(co_yield(str) or default_chunk_size) - if max_chunk_size and max_chunk_size < 0 then max_chunk_size = nil end - - if not max_chunk_size then - ngx_log(ngx_ERR, "Buffer size not specified, bailing") - break - end - end - - until length == 0 - end - end) -end - - -local function _no_body_reader() - return nil -end - - -local function _read_body(res) - local reader = res.body_reader - - if not reader then - -- Most likely HEAD or 304 etc. - return nil, "no body to be read" - end - - local chunks = {} - local c = 1 - - local chunk, err - repeat - chunk, err = reader() - - if err then - return nil, err, tbl_concat(chunks) -- Return any data so far. - end - if chunk then - chunks[c] = chunk - c = c + 1 - end - until not chunk - - return tbl_concat(chunks) -end - - -local function _trailer_reader(sock) - return co_wrap(function() - co_yield(_receive_headers(sock)) - end) -end - - -local function _read_trailers(res) - local reader = res.trailer_reader - if not reader then - return nil, "no trailers" - end - - local trailers = reader() - setmetatable(res.headers, { __index = trailers }) -end - - -local function _send_body(sock, body) - if type(body) == 'function' then - repeat - local chunk, err, partial = body() - - if chunk then - local ok, err = sock:send(chunk) - - if not ok then - return nil, err - end - elseif err ~= nil then - return nil, err, partial - end - - until chunk == nil - elseif body ~= nil then - local bytes, err = sock:send(body) - - if not bytes then - return nil, err - end - end - return true, nil -end - - -local function _handle_continue(sock, body) - local status, version, reason, err = _receive_status(sock) - if not status then - return nil, nil, err - end - - -- Only send body if we receive a 100 Continue - if status == 100 then - local ok, err = sock:receive("*l") -- Read carriage return - if not ok then - return nil, nil, err - end - _send_body(sock, body) - end - return status, version, err -end - - -function _M.send_request(self, params) - -- Apply defaults - setmetatable(params, { __index = DEFAULT_PARAMS }) - - local sock = self.sock - local body = params.body - local headers = http_headers.new() - - local params_headers = params.headers - if params_headers then - -- We assign one by one so that the metatable can handle case insensitivity - -- for us. You can blame the spec for this inefficiency. - for k,v in pairs(params_headers) do - headers[k] = v - end - end - - -- Ensure minimal headers are set - if type(body) == 'string' and not headers["Content-Length"] then - headers["Content-Length"] = #body - end - if not headers["Host"] then - if (str_sub(self.host, 1, 5) == "unix:") then - return nil, "Unable to generate a useful Host header for a unix domain socket. Please provide one." - end - -- If we have a port (i.e. not connected to a unix domain socket), and this - -- port is non-standard, append it to the Host heaer. - if self.port then - if self.ssl and self.port ~= 443 then - headers["Host"] = self.host .. ":" .. self.port - elseif not self.ssl and self.port ~= 80 then - headers["Host"] = self.host .. ":" .. self.port - else - headers["Host"] = self.host - end - else - headers["Host"] = self.host - end - end - if not headers["User-Agent"] then - headers["User-Agent"] = _M._USER_AGENT - end - if params.version == 1.0 and not headers["Connection"] then - headers["Connection"] = "Keep-Alive" - end - - params.headers = headers - - -- Format and send request - local req = _format_request(params) - ngx_log(ngx_DEBUG, "\n", req) - local bytes, err = sock:send(req) - - if not bytes then - return nil, err - end - - -- Send the request body, unless we expect: continue, in which case - -- we handle this as part of reading the response. - if headers["Expect"] ~= "100-continue" then - local ok, err, partial = _send_body(sock, body) - if not ok then - return nil, err, partial - end - end - - return true -end - - -function _M.read_response(self, params) - local sock = self.sock - - local status, version, reason, err - - -- If we expect: continue, we need to handle this, sending the body if allowed. - -- If we don't get 100 back, then status is the actual status. - if params.headers["Expect"] == "100-continue" then - local _status, _version, _err = _handle_continue(sock, params.body) - if not _status then - return nil, _err - elseif _status ~= 100 then - status, version, err = _status, _version, _err - end - end - - -- Just read the status as normal. - if not status then - status, version, reason, err = _receive_status(sock) - if not status then - return nil, err - end - end - - - local res_headers, err = _receive_headers(sock) - if not res_headers then - return nil, err - end - - -- keepalive is true by default. Determine if this is correct or not. - local ok, connection = pcall(str_lower, res_headers["Connection"]) - if ok then - if (version == 1.1 and connection == "close") or - (version == 1.0 and connection ~= "keep-alive") then - self.keepalive = false - end - else - -- no connection header - if version == 1.0 then - self.keepalive = false - end - end - - local body_reader = _no_body_reader - local trailer_reader, err - local has_body = false - - -- Receive the body_reader - if _should_receive_body(params.method, status) then - local ok, encoding = pcall(str_lower, res_headers["Transfer-Encoding"]) - if ok and version == 1.1 and encoding == "chunked" then - body_reader, err = _chunked_body_reader(sock) - has_body = true - else - - local ok, length = pcall(tonumber, res_headers["Content-Length"]) - if ok then - body_reader, err = _body_reader(sock, length) - has_body = true - end - end - end - - if res_headers["Trailer"] then - trailer_reader, err = _trailer_reader(sock) - end - - if err then - return nil, err - else - return { - status = status, - reason = reason, - headers = res_headers, - has_body = has_body, - body_reader = body_reader, - read_body = _read_body, - trailer_reader = trailer_reader, - read_trailers = _read_trailers, - } - end -end - - -function _M.request(self, params) - params = tbl_copy(params) -- Take by value - local res, err = self:send_request(params) - if not res then - return res, err - else - return self:read_response(params) - end -end - - -function _M.request_pipeline(self, requests) - requests = tbl_copy(requests) -- Take by value - - for _, params in ipairs(requests) do - if params.headers and params.headers["Expect"] == "100-continue" then - return nil, "Cannot pipeline request specifying Expect: 100-continue" - end - - local res, err = self:send_request(params) - if not res then - return res, err - end - end - - local responses = {} - for i, params in ipairs(requests) do - responses[i] = setmetatable({ - params = params, - response_read = false, - }, { - -- Read each actual response lazily, at the point the user tries - -- to access any of the fields. - __index = function(t, k) - local res, err - if t.response_read == false then - res, err = _M.read_response(self, t.params) - t.response_read = true - - if not res then - ngx_log(ngx_ERR, err) - else - for rk, rv in pairs(res) do - t[rk] = rv - end - end - end - return rawget(t, k) - end, - }) - end - return responses -end - -function _M.request_uri(self, uri, params) - params = tbl_copy(params or {}) -- Take by value - - local parsed_uri, err = self:parse_uri(uri, false) - if not parsed_uri then - return nil, err - end - - local scheme, host, port, path, query = unpack(parsed_uri) - if not params.path then params.path = path end - if not params.query then params.query = query end - - -- See if we should use a proxy to make this request - local proxy_uri = self:get_proxy_uri(scheme, host) - - -- Make the connection either through the proxy or directly - -- to the remote host - local c, err - - if proxy_uri then - c, err = self:connect_proxy(proxy_uri, scheme, host, port) - else - c, err = self:connect(host, port) - end - - if not c then - return nil, err - end - - if proxy_uri then - if scheme == "http" then - -- When a proxy is used, the target URI must be in absolute-form - -- (RFC 7230, Section 5.3.2.). That is, it must be an absolute URI - -- to the remote resource with the scheme, host and an optional port - -- in place. - -- - -- Since _format_request() constructs the request line by concatenating - -- params.path and params.query together, we need to modify the path - -- to also include the scheme, host and port so that the final form - -- in conformant to RFC 7230. - if port == 80 then - params.path = scheme .. "://" .. host .. path - else - params.path = scheme .. "://" .. host .. ":" .. port .. path - end - end - - if scheme == "https" then - -- don't keep this connection alive as the next request could target - -- any host and re-using the proxy tunnel for that is not possible - self.keepalive = false - end - - -- self:connect_uri() set the host and port to point to the proxy server. As - -- the connection to the proxy has been established, set the host and port - -- to point to the actual remote endpoint at the other end of the tunnel to - -- ensure the correct Host header added to the requests. - self.host = host - self.port = port - end - - if scheme == "https" then - local verify = true - if params.ssl_verify == false then - verify = false - end - local ok, err = self:ssl_handshake(nil, host, verify) - if not ok then - return nil, err - end - end - - local res, err = self:request(params) - if not res then - return nil, err - end - - local body, err = res:read_body() - if not body then - return nil, err - end - - res.body = body - - local ok, err = self:set_keepalive() - if not ok then - ngx_log(ngx_ERR, err) - end - - return res, nil -end - - -function _M.get_client_body_reader(self, chunksize, sock) - chunksize = chunksize or 65536 - - if not sock then - local ok, err - ok, sock, err = pcall(ngx_req_socket) - - if not ok then - return nil, sock -- pcall err - end - - if not sock then - if err == "no body" then - return nil - else - return nil, err - end - end - end - - local headers = ngx_req_get_headers() - local length = headers.content_length - local encoding = headers.transfer_encoding - if length then - return _body_reader(sock, tonumber(length), chunksize) - elseif encoding and str_lower(encoding) == 'chunked' then - -- Not yet supported by ngx_lua but should just work... - return _chunked_body_reader(sock, chunksize) - else - return nil - end -end - - -function _M.proxy_request(self, chunksize) - return self:request{ - method = ngx_req_get_method(), - path = ngx_re_gsub(ngx_var.uri, "\\s", "%20", "jo") .. ngx_var.is_args .. (ngx_var.query_string or ""), - body = self:get_client_body_reader(chunksize), - headers = ngx_req_get_headers(), - } -end - - -function _M.proxy_response(self, response, chunksize) - if not response then - ngx_log(ngx_ERR, "no response provided") - return - end - - ngx.status = response.status - - -- Filter out hop-by-hop headeres - for k,v in pairs(response.headers) do - if not HOP_BY_HOP_HEADERS[str_lower(k)] then - ngx_header[k] = v - end - end - - local reader = response.body_reader - repeat - local chunk, err = reader(chunksize) - if err then - ngx_log(ngx_ERR, err) - break - end - - if chunk then - local res, err = ngx_print(chunk) - if not res then - ngx_log(ngx_ERR, err) - break - end - end - until not chunk -end - -function _M.set_proxy_options(self, opts) - self.proxy_opts = tbl_copy(opts) -- Take by value -end - -function _M.get_proxy_uri(self, scheme, host) - if not self.proxy_opts then - return nil - end - - -- Check if the no_proxy option matches this host. Implementation adapted - -- from lua-http library (https://github.com/daurnimator/lua-http) - if self.proxy_opts.no_proxy then - if self.proxy_opts.no_proxy == "*" then - -- all hosts are excluded - return nil - end - - local no_proxy_set = {} - -- wget allows domains in no_proxy list to be prefixed by "." - -- e.g. no_proxy=.mit.edu - for host_suffix in ngx_re_gmatch(self.proxy_opts.no_proxy, "\\.?([^,]+)") do - no_proxy_set[host_suffix[1]] = true - end - - -- From curl docs: - -- matched as either a domain which contains the hostname, or the - -- hostname itself. For example local.com would match local.com, - -- local.com:80, and www.local.com, but not www.notlocal.com. - -- - -- Therefore, we keep stripping subdomains from the host, compare - -- them to the ones in the no_proxy list and continue until we find - -- a match or until there's only the TLD left - repeat - if no_proxy_set[host] then - return nil - end - - -- Strip the next level from the domain and check if that one - -- is on the list - host = ngx_re_sub(host, "^[^.]+\\.", "") - until not ngx_re_find(host, "\\.") - end - - if scheme == "http" and self.proxy_opts.http_proxy then - return self.proxy_opts.http_proxy - end - - if scheme == "https" and self.proxy_opts.https_proxy then - return self.proxy_opts.https_proxy - end - - return nil -end - - -function _M.connect_proxy(self, proxy_uri, scheme, host, port) - -- Parse the provided proxy URI - local parsed_proxy_uri, err = self:parse_uri(proxy_uri, false) - if not parsed_proxy_uri then - return nil, err - end - - -- Check that the scheme is http (https is not supported for - -- connections between the client and the proxy) - local proxy_scheme = parsed_proxy_uri[1] - if proxy_scheme ~= "http" then - return nil, "protocol " .. proxy_scheme .. " not supported for proxy connections" - end - - -- Make the connection to the given proxy - local proxy_host, proxy_port = parsed_proxy_uri[2], parsed_proxy_uri[3] - local c, err = self:connect(proxy_host, proxy_port) - if not c then - return nil, err - end - - if scheme == "https" then - -- Make a CONNECT request to create a tunnel to the destination through - -- the proxy. The request-target and the Host header must be in the - -- authority-form of RFC 7230 Section 5.3.3. See also RFC 7231 Section - -- 4.3.6 for more details about the CONNECT request - local destination = host .. ":" .. port - local res, err = self:request({ - method = "CONNECT", - path = destination, - headers = { - ["Host"] = destination - } - }) - - if not res then - return nil, err - end - - if res.status < 200 or res.status > 299 then - return nil, "failed to establish a tunnel through a proxy: " .. res.status - end - end - - return c, nil -end - -return _M diff --git a/website/backend/app/libs/resty/http/http_headers.lua b/website/backend/app/libs/resty/http/http_headers.lua deleted file mode 100755 index 56069ec..0000000 --- a/website/backend/app/libs/resty/http/http_headers.lua +++ /dev/null @@ -1,44 +0,0 @@ -local rawget, rawset, setmetatable = - rawget, rawset, setmetatable - -local str_lower = string.lower - -local _M = { - _VERSION = '0.12', -} - - --- Returns an empty headers table with internalised case normalisation. -function _M.new() - local mt = { - normalised = {}, - } - - mt.__index = function(t, k) - return rawget(t, mt.normalised[str_lower(k)]) - end - - mt.__newindex = function(t, k, v) - local k_normalised = str_lower(k) - - -- First time seeing this header field? - if not mt.normalised[k_normalised] then - -- Create a lowercased entry in the metatable proxy, with the value - -- of the given field case - mt.normalised[k_normalised] = k - - -- Set the header using the given field case - rawset(t, k, v) - else - -- We're being updated just with a different field case. Use the - -- normalised metatable proxy to give us the original key case, and - -- perorm a rawset() to update the value. - rawset(t, mt.normalised[k_normalised], v) - end - end - - return setmetatable({}, mt) -end - - -return _M diff --git a/website/backend/app/libs/resty/moongoo.lua b/website/backend/app/libs/resty/moongoo.lua deleted file mode 100755 index ad412eb..0000000 --- a/website/backend/app/libs/resty/moongoo.lua +++ /dev/null @@ -1,146 +0,0 @@ -local cbson = require("cbson") -local connection = require("resty.moongoo.connection") -local database = require("resty.moongoo.database") -local parse_uri = require("resty.moongoo.utils").parse_uri -local auth_scram = require("resty.moongoo.auth.scram") -local auth_cr = require("resty.moongoo.auth.cr") - - -local _M = {} - -_M._VERSION = '0.1' -_M.NAME = 'Moongoo' - - -local mt = { __index = _M } - -function _M.new(uri) - local conninfo = parse_uri(uri) - - if not conninfo.scheme or conninfo.scheme ~= "mongodb" then - return nil, "Wrong scheme in connection uri" - end - - local auth_algo = conninfo.query and conninfo.query.authMechanism or "SCRAM-SHA-1" - local w = conninfo.query and conninfo.query.w or 1 - local wtimeout = conninfo.query and conninfo.query.wtimeoutMS or 1000 - local journal = conninfo.query and conninfo.query.journal or false - local ssl = conninfo.query and conninfo.query.ssl or false - - local stimeout = conninfo.query.socketTimeoutMS and conninfo.query.socketTimeoutMS or nil - - return setmetatable({ - connection = nil; - w = w; - wtimeout = wtimeout; - journal = journal; - stimeout = stimeout; - hosts = conninfo.hosts; - default_db = conninfo.database; - user = conninfo.user or nil; - password = conninfo.password or ""; - auth_algo = auth_algo, - ssl = ssl, - version = nil - }, mt) -end - -function _M._auth(self, protocol) - if not self.user then return 1 end - - if not protocol or protocol < cbson.int(3) or self.auth_algo == "MONGODB-CR" then - return auth_cr(self:db(self.default_db), self.user, self.password) - else - return auth_scram(self:db(self.default_db), self.user, self.password) - end - -end - -function _M.connect(self) - if self.connection then return self end - - -- foreach host - for k, v in ipairs(self.hosts) do - -- connect - self.connection, err = connection.new(v.host, v.port, self.stimeout) - if not self.connection then - return nil, err - end - local status, err = self.connection:connect() - if status then - if self.ssl then - self.connection:handshake() - end - if not self.version then - query = self:db(self.default_db):_cmd({ buildInfo = 1 }) - if query then - self.version = query.version - end - end - - local ismaster = self:db("admin"):_cmd("ismaster") - if ismaster and ismaster.ismaster then - -- auth - local r, err = self:_auth(ismaster.maxWireVersion) - if not r then - return nil, err - end - return self - else - -- try to connect to master - if ismaster.primary then - local mhost, mport - string.gsub(ismaster.primary, "([^:]+):([^:]+)", function(host,port) mhost=host; mport=port end) - self.connection:close() - self.connection = nil - self.connection, err = connection.new(mhost, mport, self.stimeout) - if not self.connection then - return nil, err - end - local status, err = self.connection:connect() - if not status then - return nil, err - end - if self.ssl then - self.connection:handshake() - end - if not self.version then - query = self:db(self.default_db):_cmd({ buildInfo = 1 }) - if query then - self.version = query.version - end - end - local ismaster = self:db("admin"):_cmd("ismaster") - if ismaster and ismaster.ismaster then - -- auth - local r, err = self:_auth(ismaster.maxWireVersion) - if not r then - return nil, err - end - return self - else - return nil, "Can't connect to master server" - end - end - end - end - end - return nil, "Can't connect to any of servers" -end - -function _M.close(self) - if self.connection then - self.connection:close() - self.connection = nil - end -end - -function _M.get_reused_times(self) - return self.connection:get_reused_times() -end - -function _M.db(self, dbname) - return database.new(dbname, self) -end - -return _M diff --git a/website/backend/app/libs/resty/moongoo/auth/cr.lua b/website/backend/app/libs/resty/moongoo/auth/cr.lua deleted file mode 100755 index 8907789..0000000 --- a/website/backend/app/libs/resty/moongoo/auth/cr.lua +++ /dev/null @@ -1,32 +0,0 @@ -local pass_digest = require("resty.moongoo.utils").pass_digest - -local b64 = ngx and ngx.encode_base64 or require("mime").b64 -local unb64 = ngx and ngx.decode_base64 or require("mime").unb64 - -local md5 = ngx and ngx.md5 or function(str) return require("crypto").digest("md5", str) end - -local cbson = require("cbson") - - -local function auth(db, username, password) - local r, err = db:_cmd("getnonce", {}) - if not r then - return nil, err - end - - local digest = md5( r.nonce .. username .. pass_digest ( username , password ) ) - - r, err = db:_cmd("authenticate", { - user = username ; - nonce = r.nonce ; - key = digest ; - }) - - if not r then - return nil, err - end - - return 1 -end - -return auth \ No newline at end of file diff --git a/website/backend/app/libs/resty/moongoo/auth/scram.lua b/website/backend/app/libs/resty/moongoo/auth/scram.lua deleted file mode 100755 index d8d1037..0000000 --- a/website/backend/app/libs/resty/moongoo/auth/scram.lua +++ /dev/null @@ -1,103 +0,0 @@ -local Hi = require("resty.moongoo.utils").pbkdf2_hmac_sha1 -local saslprep = require("resty.moongoo.utils").saslprep -local pass_digest = require("resty.moongoo.utils").pass_digest -local xor_bytestr = require("resty.moongoo.utils").xor_bytestr - -local b64 = ngx and ngx.encode_base64 or require("mime").b64 -local unb64 = ngx and ngx.decode_base64 or require("mime").unb64 - -local hmac_sha1 = ngx and ngx.hmac_sha1 or function(str, key) return require("crypto").hmac.digest("sha1", key, str, true) end -local sha1_bin = ngx and ngx.sha1_bin or function(str) return require("crypto").digest("sha1", str, true) end - -local cbson = require("cbson") - - -local function auth(db, username, password) - local username = saslprep(username) - local c_nonce = b64(string.sub(tostring(math.random()), 3 , 14)) - - local first_bare = "n=" .. username .. ",r=" .. c_nonce - - local sasl_start_payload = b64("n,," .. first_bare) - - r, err = db:_cmd("saslStart", { - mechanism = "SCRAM-SHA-1" ; - autoAuthorize = 1 ; - payload = cbson.binary(sasl_start_payload); - }) - - if not r then - return nil, err - end - - - local conversationId = r['conversationId'] - local server_first = r['payload']:raw() - - local parsed_t = {} - for k, v in string.gmatch(server_first, "(%w+)=([^,]*)") do - parsed_t[k] = v - end - - local iterations = tonumber(parsed_t['i']) - local salt = parsed_t['s'] - local s_nonce = parsed_t['r'] - - if not string.sub(s_nonce, 1, 12) == c_nonce then - return nil, 'Server returned an invalid nonce.' - end - - local without_proof = "c=biws,r=" .. s_nonce - - local pbkdf2_key = pass_digest ( username , password ) - local salted_pass = Hi(pbkdf2_key, iterations, unb64(salt), 20) - - local client_key = hmac_sha1(salted_pass, "Client Key") - local stored_key = sha1_bin(client_key) - local auth_msg = first_bare .. ',' .. server_first .. ',' .. without_proof - local client_sig = hmac_sha1(stored_key, auth_msg) - local client_key_xor_sig = xor_bytestr(client_key, client_sig) - local client_proof = "p=" .. b64(client_key_xor_sig) - local client_final = b64(without_proof .. ',' .. client_proof) - local server_key = hmac_sha1(salted_pass, "Server Key") - local server_sig = b64(hmac_sha1(server_key, auth_msg)) - - r, err = db:_cmd("saslContinue",{ - conversationId = conversationId ; - payload = cbson.binary(client_final); - }) - - if not r then - return nil, err - end - - local parsed_s = r['payload']:raw() - parsed_t = {} - for k, v in string.gmatch(parsed_s, "(%w+)=([^,]*)") do - parsed_t[k] = v - end - if parsed_t['v'] ~= server_sig then - return nil, "Server returned an invalid signature." - end - - if not r['done'] then - r, err = db:_cmd("saslContinue", { - conversationId = conversationId ; - payload = cbson.binary("") ; - }) - - if not r then - return nil, err - end - - if not r['done'] then - return nil, 'SASL conversation failed to complete.' - end - - return 1 - end - - return 1 -end - -return auth diff --git a/website/backend/app/libs/resty/moongoo/collection.lua b/website/backend/app/libs/resty/moongoo/collection.lua deleted file mode 100755 index ee5ed18..0000000 --- a/website/backend/app/libs/resty/moongoo/collection.lua +++ /dev/null @@ -1,377 +0,0 @@ -local cbson = require("cbson") -local generate_oid = require("resty.moongoo.utils").generate_oid -local cursor = require("resty.moongoo.cursor") - -local _M = {} - -local mt = { __index = _M } - -function _M.new(name, db) - return setmetatable({_db = db, name = name}, mt) -end - -function _M._build_write_concern(self) - return { - j = self._db._moongoo.journal; - w = tonumber(self._db._moongoo.w) and cbson.int(self._db._moongoo.w) or self._db._moongoo.w; - wtimeout = cbson.int(self._db._moongoo.wtimeout); - } -end - -local function check_write_concern(doc, ...) - -- even if write concern failed we may still have successful operation - -- so we check for number of affected docs, and only warn if its > 0 - -- otherwise, we just return nil and error - - if doc.writeConcernError then - if not doc.n then - return nil, doc.writeConcernError.errmsg - else - print(doc.writeConcernError.errmsg) - end - end - return ... -end - -function _M._get_last_error(self) - local write_concern = self:_build_write_concern() - local cmd = { getLastError = cbson.int(1), j = write_concern.j, w = write_concern.w, wtimeout = write_concern.wtimeout } - - local doc, err = self._db:cmd(cmd) - if not doc then - return nil, err - end - - return doc -end - -function _M._check_last_error(self, ...) - local cmd, err = self:_get_last_error() - - if not cmd then - return nil, err - end - - if tostring(cmd.err) == "null" then - return ... - end - - return nil, tostring(cmd.err) -end - -local function ensure_oids(docs) - local docs = docs - local ids = {} - for k,v in ipairs(docs) do - if not docs[k]._id then - docs[k]._id = cbson.oid(generate_oid()) - end - table.insert(ids, docs[k]._id) - end - return docs, ids -end - -local function build_index_names(docs) - local docs = docs - for k,v in ipairs(docs) do - if not v.name then - local name = {} - for n, d in pairs(v.key) do - table.insert(name, n) - end - name = table.concat(name, '_') - docs[k].name = name - end - end - return docs -end - -function _M.insert(self, docs) - -- ensure we have oids - if #docs == 0 then - local newdocs = {} - newdocs[1] = docs - docs = newdocs - end - local docs, ids = ensure_oids(docs) - - self._db._moongoo:connect() - - local server_version = tonumber(string.sub(string.gsub(self._db._moongoo.version, "(%D)", ""), 1, 3)) - - if server_version < 254 then - self._db:insert(self:full_name(), docs) - return self:_check_last_error(ids) - else - local doc, err = self._db:cmd( - { insert = self.name }, - { - documents = docs, - ordered = true, - writeConcern = self:_build_write_concern() - } - ) - - if not doc then - return nil, err - end - - return check_write_concern(doc, ids, doc.n) - end -end - -function _M.create(self, params) - local params = params or {} - local doc, err = self._db:cmd( - { create = self.name }, - params - ) - if not doc then - return nil, err - end - return true -end - -function _M.drop(self) - local doc, err = self._db:cmd( - { drop = self.name }, - {} - ) - if not doc then - return nil, err - end - return true -end - -function _M.drop_index(self, name) - local doc, err = self._db:cmd( - { dropIndexes = self.name }, - { index = name } - ) - if not doc then - return nil, err - end - return true -end - -function _M.ensure_index(self, docs) - docs = build_index_names(docs) - - local doc, err = self._db:cmd( - { createIndexes = self.name }, - { indexes = docs } - ) - if not doc then - return nil, err - end - return true -end - -function _M.full_name(self) - return self._db.name .. "." .. self.name -end - -function _M.options(self) - local doc, err = self._db:cmd( - "listCollections", - { - filter = { name = self.name } - } - ) - if not doc then - return nil, err - end - return doc.cursor.firstBatch[1] -end - -function _M.remove(self, query, single) - local query = query or {} - - if getmetatable(cbson.oid("000000000000000000000000")) == getmetatable(query) then - query = { _id = query } - end - - local doc, err = self._db:cmd( - { delete = self.name }, - { - deletes = {{q=query, limit = single and 1 or 0}}, - ordered = true, - writeConcern = self:_build_write_concern() - } - ) - if not doc then - return nil, err - end - - return check_write_concern(doc, doc.n) -end - -function _M.stats(self) - local doc, err = self._db:cmd( - {collstats = self.name}, - {} - ) - if not doc then - return nil, err - end - return doc -end - -function _M.index_information(self) - local doc, err = self._db:cmd( - { listIndexes = self.name }, - { } - ) - if not doc then - return nil, err - end - return doc.cursor.firstBatch -end - -function _M.rename(self, to_name, drop) - local drop = drop or false - -- rename - local doc, err = self._db._moongoo:db("admin"):cmd( - { renameCollection = self:full_name() }, - { - to = to_name, - dropTarget = drop - } - ) - if not doc then - return nil, err - end - - return self.new(to_name, self._db) -end - -function _M.update(self, query, update, flags) - local flags = flags or {} - local query = query or {} - - if getmetatable(cbson.oid("000000000000000000000000")) == getmetatable(query) then - query = { _id = query } - end - - local update = { - q = query, - u = update, - upsert = flags.upsert or false, - multi = flags.multi or false - } - - local doc, err = self._db:cmd( - { update = self.name }, - { - updates = { update }, - ordered = true, - writeConcern = self:_build_write_concern() - } - ) - if not doc then - return nil, err - end - - return doc.nModified -end - -function _M.save(self, doc) - if not doc._id then - doc._id = cbson.oid(generate_oid()) - end - local r, err = self:update(doc._id, doc, {upsert = true}); - if not r then - return nil, err - end - - return doc._id -end - -function _M.map_reduce(self, map, reduce, flags) - local flags = flags or {} - flags.map = cbson.code(map) - flags.reduce = cbson.code(reduce) - flags.out = flags.out or { inline = true } - - local doc, err = self._db:cmd( - { mapReduce = self.name }, - flags - ) - if not doc then - return nil, err - end - - if doc.results then - return doc.results - end - - return self.new(doc.result, self._db) -end - -function _M.find(self, query, fields) - local query = query or {} - if getmetatable(cbson.oid("000000000000000000000000")) == getmetatable(query) then - query = { _id = query } - end - return cursor.new(self, query, fields) -end - -function _M.find_one(self, query, fields) - local query = query or {} - if getmetatable(cbson.oid("000000000000000000000000")) == getmetatable(query) then - query = { _id = query } - end - - return self:find(query, fields):limit(-1):next() -end - -function _M.find_and_modify(self, query, opts) - local query = query or {} - if getmetatable(cbson.oid("000000000000000000000000")) == getmetatable(query) then - query = { _id = query } - end - - local opts = opts or {} - opts.query = query - - local doc, err = self._db:cmd( - { findAndModify = self.name }, - opts - ) - if not doc then - return nil, err - end - return doc.value -end - -function _M.aggregate(self, pipeline, opts) - local opts = opts or {} - opts.pipeline = pipeline - if not opts.explain then - opts.cursor = {} - end - - local doc, err = self._db:cmd( - { aggregate = self.name }, - opts - ) - if not doc then - return nil, err - end - - if opts.explain then - return doc - end - - -- collection - if opts.pipeline[#opts.pipeline]['$out'] then - return self.new(opts.pipeline[#opts.pipeline]['$out'], self._db) - end - - -- cursor - return cursor.new(self, {}, {}, false, doc.cursor.id):add_batch(doc.cursor.firstBatch) -end - - - -return _M \ No newline at end of file diff --git a/website/backend/app/libs/resty/moongoo/connection.lua b/website/backend/app/libs/resty/moongoo/connection.lua deleted file mode 100755 index fac53f9..0000000 --- a/website/backend/app/libs/resty/moongoo/connection.lua +++ /dev/null @@ -1,210 +0,0 @@ -local socket = ngx and ngx.socket.tcp or require("socket").tcp -local cbson = require("cbson") - -local opcodes = { - OP_REPLY = 1; - OP_MSG = 1000; - OP_UPDATE = 2001; - OP_INSERT = 2002; - RESERVED = 2003; - OP_QUERY = 2004; - OP_GET_MORE = 2005; - OP_DELETE = 2006; - OP_KILL_CURSORS = 2007; -} - -local _M = {} - -local mt = { __index = _M } - -function _M.new(host, port, timeout) - local sock = socket() - if timeout then - sock:settimeout(timeout) - end - - return setmetatable({ - sock = sock; - host = host; - port = port; - _id = 0; - }, mt) -end - -function _M.connect(self, host, port) - self.host = host or self.host - self.port = port or self.port - return self.sock:connect(self.host, self.port) -end - -function _M.handshake(self) - if ngx then - self.sock:sslhandshake() - else - local ssl = require("ssl") - self.sock = ssl.wrap(self.sock, {mode = "client", protocol = "tlsv1_2"}) - assert(self.sock) - self.sock:dohandshake() - end -end - -function _M.close(self) - if ngx then - self.sock:setkeepalive() - else - self.sock:close() - end -end - -function _M.get_reused_times(self) - if not self.sock then - return nil, "not initialized" - end - - return self.sock:getreusedtimes() -end - -function _M.settimeout(self, ms) - self.sock:settimeout(ms) -end - -function _M.send(self, data) - return self.sock:send(data) -end - -function _M.receive(self, pat) - return self.sock:receive(pat) -end - -function _M._handle_reply(self) - local header = assert ( self.sock:receive ( 16 ) ) - - local length = cbson.raw_to_uint( string.sub(header , 1 , 4 )) - local r_id = cbson.raw_to_uint( string.sub(header , 5 , 8 )) - local r_to = cbson.raw_to_uint( string.sub(header , 9 , 12 )) - local opcode = cbson.raw_to_uint( string.sub(header , 13 , 16 )) - - assert ( opcode == cbson.uint(opcodes.OP_REPLY ) ) - assert ( r_to == cbson.uint(self._id) ) - - local data = assert ( self.sock:receive ( tostring(length-16 ) ) ) - - local flags = cbson.raw_to_uint( string.sub(data , 1 , 4 )) - local cursor_id = cbson.raw_to_uint( string.sub(data , 5 , 12 )) - local from = cbson.raw_to_uint( string.sub(data , 13 , 16 )) - local number = tonumber(tostring(cbson.raw_to_uint( string.sub(data , 17 , 20 )))) - - local docs = string.sub(data , 21) - - local pos = 1 - local index = 0 - local r_docs = {} - while index < number do - local bson_size = tonumber(tostring(cbson.raw_to_uint(docs:sub(pos, pos+3)))) - - local dt = docs:sub(pos,pos+bson_size-1) -- get bson data according to size - - table.insert(r_docs, cbson.decode(dt)) - - pos = pos + bson_size - index = index + 1 - end - - return flags, cursor_id, from, number, r_docs -end - -function _M._build_header(self, op, payload_size) - local size = cbson.uint_to_raw(cbson.uint(payload_size+16), 4) - local op = cbson.uint_to_raw(cbson.uint(op), 4) - self._id = self._id+1 - local id = cbson.uint_to_raw(cbson.uint(self._id), 4) - local reply_to = "\0\0\0\0" - return size .. id .. reply_to .. op -end - -function _M._query(self, collection, query, to_skip, to_return, selector, flags) - local flags = { - tailable = flags and flags.tailable and 1 or 0, - slaveok = flags and flags.slaveok and 1 or 0, - notimeout = flags and flags.notimeout and 1 or 0, - await = flags and flags.await and 1 or 0, - exhaust = flags and flags.exhaust and 1 or 0, - partial = flags and flags.partial and 1 or 0 - } - - local flagset = cbson.int_to_raw( - cbson.int( - 2 * flags["tailable"] + - 2^2 * flags["slaveok"] + - 2^4 * flags["notimeout"] + - 2^5 * flags["await"] + - 2^6 * flags["exhaust"] + - 2^7 * flags["partial"] - ), - 4) - - local selector = selector and #selector and cbson.encode(selector) or "" - - local to_skip = cbson.int_to_raw(cbson.int(to_skip), 4) - local to_return = cbson.int_to_raw(cbson.int(to_return), 4) - - local size = 4 + #collection + 1 + 4 + 4 + #query + #selector - - local header = self:_build_header(opcodes["OP_QUERY"], size) - - local data = header .. flagset .. collection .. "\0" .. to_skip .. to_return .. query .. selector - - assert(self:send(data)) - return self:_handle_reply() -end - -function _M._insert(self, collection, docs, flags) - local encoded_docs = {} - for k, doc in ipairs(docs) do - encoded_docs[k] = cbson.encode(doc) - end - string_docs = table.concat(encoded_docs) - - local flags = { - continue_on_error = flags and flags.continue_on_error and 1 or 0 - } - - local flagset = cbson.int_to_raw( - cbson.int( - 2 * flags["continue_on_error"] - ), - 4) - - local size = 4 + 1 + #collection + #string_docs - local header = self:_build_header(opcodes["OP_INSERT"], size) - - local data = header .. flagset .. collection .. "\0" .. string_docs - - assert(self:send(data)) - - return true -- Mongo doesn't send a reply -end - -function _M._kill_cursors(self, id) - local id = cbson.uint_to_raw(id, 8) - local num = cbson.int_to_raw(cbson.int(1), 4) - local zero = cbson.int_to_raw(cbson.int(0), 4) - local size = 8+4+4 - local header = self:_build_header(opcodes["OP_KILL_CURSORS"], size) - local data = header .. zero .. num .. id - assert(self:send(data)) - return true -- Mongo doesn't send a reply -end - -function _M._get_more(self, collection, number, cursor) - local num = cbson.int_to_raw(cbson.int(number), 4) - local zero = cbson.int_to_raw(cbson.int(0), 4) - local cursor = cbson.uint_to_raw(cursor, 8) - local size = 4+#collection+1+4+8 - local header = self:_build_header(opcodes["OP_GET_MORE"], size) - local data = header .. zero .. collection .. '\0' .. num .. cursor - assert(self:send(data)) - return self:_handle_reply() -end - -return _M \ No newline at end of file diff --git a/website/backend/app/libs/resty/moongoo/cursor.lua b/website/backend/app/libs/resty/moongoo/cursor.lua deleted file mode 100755 index 13bc8f5..0000000 --- a/website/backend/app/libs/resty/moongoo/cursor.lua +++ /dev/null @@ -1,256 +0,0 @@ -local cbson = require("cbson") -local bit = require("bit") - - -local function check_bit(num, bitnum) - return bit.band(num,math.pow(2,bitnum)) ~= 0 -- and true or false -end - -local _M = {} - -local mt = { __index = _M } - -function _M.new(collection, query, fields, explain, id) - return setmetatable( - { - _collection = collection, - _query = query, - _fields = fields, - _id = id or cbson.uint(0), - _skip = 0, - _limit = 0, - _docs = {}, - _started = false, - _cnt = 0, - _comment = nil, - _hint = nil, - _max_scan = nil , - _max_time_ms = nil, - _read_preference = nil, - _snapshot = nil, - _sort = nil, - _await = false, - _tailable = false, - _explain = explain or false - }, - mt) -end - -function _M.tailable(self, tailable) - self._tailable = tailable - return self -end - -function _M.await(self, await) - self._await = await - return self -end - - -function _M.comment(self, comment) - self._comment = comment - return self -end - -function _M.hint(self, hint) - self._hint = hint - return self -end - -function _M.max_scan(self, max_scan) - self._max_scan = max_scan - return self -end - -function _M.max_time_ms(self, max_time_ms) - self._max_time_ms = max_time_ms - return self -end - -function _M.read_preference(self, read_preference) - self._read_preference = read_preference - return self -end - -function _M.snapshot(self, snapshot) - self._snapshot = snapshot - return self -end - -function _M.sort(self, sort) - self._sort = sort - return self -end - - -function _M.clone(self, explain) - local clone = self.new(self._collection, self._query, self._fields, explain) - clone:limit(self._limit) - clone:skip(self._skip) - - clone:comment(self._comment) - clone:hint(self._hint) - clone:max_scan(self._max_scan) - clone:max_time_ms(self._max_time_ms) - clone:read_preference(self._read_preference) - clone:snapshot(self._snapshot) - clone:sort(self._sort) - - return clone -end - -function _M.skip(self, skip) - if self._started then - print("Can's set skip after starting cursor") - else - self._skip = skip - end - return self -end - -function _M.limit(self, limit) - if self._started then - print("Can's set limit after starting cursor") - else - self._limit = limit - end - return self -end - -function _M._build_query(self) - local ext = {} - if self._comment then ext['$comment'] = self._comment end - if self._explain then ext['$explain'] = true end - - - if self._hint then ext['$hint'] = self._hint end - if self._max_scan then ext['$maxScan'] = self._max_scan end - if self._max_time_ms then ext['$maxTimeMS'] = self._max_time_ms end - if self._read_preference then ext['$readPreference'] = self._read_preference end - if self._snapshot then ext['$snapshot'] = true end - if self._sort then ext['$orderby'] = self._sort end - - ext['$query'] = self._query - - return cbson.encode(ext) -end - -function _M.next(self) - local moongoo, err = self._collection._db._moongoo:connect() - if not moongoo then - return nil, err - end - - if self:_finished() then - if self._id ~= cbson.uint(0) then - self._collection._db._moongoo.connection:_kill_cursors(self._id) - self._id = cbson.uint(0) - end - return nil, "no more data" - end - - if (not self._started) and (self._id == cbson.uint(0)) then - - -- query and add id and batch - local flags, id, from, number, docs = self._collection._db._moongoo.connection:_query(self._collection:full_name(), self:_build_query(), self._skip, self._limit, self._fields, {tailable = self._tailable, await = self._await}) - - flags = tonumber(tostring(flags)) -- bitop can't work with cbson.int, so... - - if check_bit(flags, 1) then -- QueryFailure - return nil, docs[1]['$err'] -- why is this $err and not errmsg, like others?? - end - self._id = id - self:add_batch(docs) - elseif #self._docs == 0 and self._id ~= cbson.uint(0) then - -- we have something to fetch - get_more and add_batch - local flags, id, from, number, docs = self._collection._db._moongoo.connection:_get_more(self._collection:full_name(), self._limit, self._id) - - flags = tonumber(tostring(flags)) -- bitop can't work with cbson.int, so... - - if check_bit(flags, 0) then -- QueryFailure - return nil, "wrong cursor id" - end - self:add_batch(docs) - self._id = id - - elseif #self._docs == 0 then--or self._id == cbson.uint(0) then - return nil, "no more data" - end - self._cnt = self._cnt+1 - return table.remove(self._docs, 1) or nil, 'No more data' -end - -function _M.all(self) - local docs = {} - while true do - local doc = self:next() - if doc == nil then break end - table.insert(docs, doc) - end - return docs -end - -function _M.rewind(self) - self._started = false - self._docs = {} - self._collection._db._moongoo.connection:_kill_cursors(self._id) - self._id = cbson.uint(0) - return self -end - -function _M.count(self) - local doc, err = self._collection._db:cmd( - { count = self._collection.name }, - { - query = self._query, - skip = self._skip, - limit = self._limit - } - ) - if not doc then - return nil, err - end - - return doc and doc.n or 0 -end - -function _M.distinct(self, key) - local doc, err = self._collection._db:cmd( - { distinct = self._collection.name }, - { - query = self._query, - key = key - } - ) - if not doc then - return nil, err - end - - return doc and doc.values or {} -end - -function _M.explain(self) - return self:clone(true):sort(nil):next() -end - -function _M.add_batch(self, docs) - self._started = true - for k,v in ipairs(docs) do - table.insert(self._docs, v) - end - return self -end - -function _M._finished(self) - if self._limit == 0 then - return false - else - if self._cnt >= math.abs(self._limit) then - return true - else - return false - end - end -end - -return _M diff --git a/website/backend/app/libs/resty/moongoo/database.lua b/website/backend/app/libs/resty/moongoo/database.lua deleted file mode 100755 index 4b056e8..0000000 --- a/website/backend/app/libs/resty/moongoo/database.lua +++ /dev/null @@ -1,70 +0,0 @@ -local cbson = require("cbson") -local collection = require("resty.moongoo.collection") -local gridfs = require("resty.moongoo.gridfs") - -local _M = {} - -local mt = { __index = _M } - -function _M.new(name, moongoo) - return setmetatable({name = name, _moongoo = moongoo}, mt) -end - -function _M.collection(self, name) - return collection.new(name, self) -end - -function _M.gridfs(self, name) - return gridfs.new(self,name) -end - -function _M.cmd(self, cmd, params) - local r, err = self._moongoo:connect() - if not r then - return nil, err - end - return self:_cmd(cmd, params) -end - -function _M._cmd(self, cmd, params) - local params = params or {} - if type(cmd) == "table" then - local tmpcmd = '' - for k,v in pairs(cmd) do - params[k] = v - tmpcmd = k - end - cmd = tmpcmd - else - params[cmd] = true - end - local cmd = cbson.encode_first(cmd, params) - - local _,_,_,_,docs = self._moongoo.connection:_query(self.name..".$cmd", cmd, 0, 1) - - if not docs[1] then - return nil, "Empty reply from mongodb" - end - - if not docs[1].ok or docs[1].ok == 0 then - return nil, docs[1].errmsg - end - - return docs[1] -end - -function _M.insert(self, collection, docs) - local r, err = self._moongoo:connect() - if not r then - return nil, err - end - return self:_insert(collection, docs) -end - -function _M._insert(self, collection, docs) - self._moongoo.connection:_insert(collection, docs) - return -end - - -return _M \ No newline at end of file diff --git a/website/backend/app/libs/resty/moongoo/gridfs.lua b/website/backend/app/libs/resty/moongoo/gridfs.lua deleted file mode 100755 index 34008b0..0000000 --- a/website/backend/app/libs/resty/moongoo/gridfs.lua +++ /dev/null @@ -1,57 +0,0 @@ -local cbson = require("cbson") -local gfsfile = require("resty.moongoo.gridfs.file") - -local _M = {} - -local mt = { __index = _M } - -function _M.new(db, name) - local name = name or 'fs' - return setmetatable( - { - _db = db, - _name = name, - _files = db:collection(name .. '.files'), - _chunks = db:collection(name .. '.chunks') - }, - mt) -end - -function _M.list(self) - return self._files:find({}):distinct('filename') -end - -function _M.remove(self, id) - local r,err = self._files:remove({_id = cbson.oid(id)}) - if not r then - return nil, "Failed to remove file metadata: "..err - end - r,err = self._chunks:remove({files_id = cbson.oid(id)}); - if not r then - return nil, "Failed to remove file chunks: "..err - end - return r -end - -function _M.find_version(self, name, version) - -- Positive numbers are absolute and negative ones relative - local cursor = self._files:find({filename = name}, {_id = 1}):limit(-1) - cursor:sort({uploadDate = (version < 0) and cbson.int(-1) or cbson.int(1)}):skip(version < 0 and (math.abs(version) - 1) or version) - local doc, err = cursor:next() - if not doc then - return nil, "No such file/version" - end - return doc._id -end - -function _M.open(self, id) - return gfsfile.open(self, id) -end - - -function _M.create(self, name, opts, safe) - return gfsfile.new(self, name, opts, safe) -end - -return _M - diff --git a/website/backend/app/libs/resty/moongoo/gridfs/file.lua b/website/backend/app/libs/resty/moongoo/gridfs/file.lua deleted file mode 100755 index 033d5ee..0000000 --- a/website/backend/app/libs/resty/moongoo/gridfs/file.lua +++ /dev/null @@ -1,219 +0,0 @@ -local cbson = require("cbson") -local generate_oid = require("resty.moongoo.utils").generate_oid - - -local _M = {} - -local mt = { __index = _M } - -function _M.new(gridfs, name, opts, safe, read_only) - local read_only = read_only or false - local safe = safe == nil and true or safe - - opts = opts or {} - opts.filename = name - opts.length = opts.length or cbson.uint(0) - opts.chunkSize = opts.chunkSize or cbson.uint(261120) - - local write_only = true - if not safe then - write_only = false - end - - return setmetatable( - { - _gridfs = gridfs, - _meta = opts, - _write_only = write_only, - _read_only = read_only, - _pos = 0, - _chunks = {}, - _closed = false, - _buffer = '', - _n = 0 - }, - mt) -end - -function _M.open(gridfs, id) - -- try to fetch - local doc, err = gridfs._files:find_one({ _id = id}) - if not doc then - return nil, "No such file" - else - return _M.new(gridfs, doc.filename, doc, false, true) - end -end - --- props - -function _M.content_type(self) return self._meta.contentType end -function _M.filename(self) return self._meta.filename end -function _M.md5(self) return self._meta.md5 end -function _M.metadata(self) return self._meta.metadata end -function _M.raw_length(self) return self._meta.length end -function _M.raw_chunk_size(self) return self._meta.chunkSize end -function _M.date(self) return self._meta.uploadDate end - -function _M.length(self) return tonumber(tostring(self._meta.length)) end -function _M.chunk_size(self) return tonumber(tostring(self._meta.chunkSize)) end - --- reading - -function _M.read(self) - if self._write_only then - return nil, "Can't read from write-only file" - end - - if self._pos >= (self:length() or 0) then - return nil, "EOF" - end - - local n = math.modf(self._pos / self:chunk_size()) - local query = {files_id = self._meta._id, n = n} - local fields = {_id = false, data = true} - - local chunk = self._gridfs._chunks:find_one(query, fields) - if not chunk then - return nil, "EOF?" - end - - return self:_slice(n, chunk.data) -end - -function _M.seek(self, pos) - self._pos = pos - return self -end - -function _M.tell(self) - return self._pos -end - -function _M.slurp(self) - local data = {} - local pos = self._pos - self:seek(0) - while true do - local chunk = self:read() - if not chunk then break end - table.insert(data, chunk) - end - self:seek(pos) - return table.concat(data) -end - --- writing - -function _M.write(self, data) - if self._read_only then - return nil, "Can't write to read-only file" - end - - if self._closed then - return nil, "Can't write to closed file" - end - - self._buffer = self._buffer .. data - self._meta.length = self._meta.length + data:len() - - while self._buffer:len() >= self:chunk_size() do - local r, res = self:_chunk() - if not r then - return nil, err - end - end -end - -function _M.close(self) - - if self._closed then - return nil, "File already closed" - end - self._closed = true - - self:_chunk() -- enqueue/write last chunk of data - - if self._write_only then - -- insert all collected chunks - for k, v in ipairs(self._chunks) do - local r, err = self._gridfs._chunks:insert(v) - if not r then - return nil, err - end - end - end - - -- ensure indexes - self._gridfs._files:ensure_index({{ key = {filename = true}}}) - self._gridfs._chunks:ensure_index({ { key = {files_id = 1, n = 1}, unique = true } }); - -- compute md5 - local res, err = self._gridfs._db:cmd({filemd5 = self:_files_id()}, {root = self._gridfs._name}) - if not res then - return nil, err - end - local file_md5 = res.md5 - -- insert metadata - local ids, n = self._gridfs._files:insert(self:_metadata(file_md5)) - - if not ids then - return nil, n - end - -- return metadata - return ids[1] -end - --- private - -function _M._files_id(self) - if not self._meta._id then - self._meta._id = cbson.oid(generate_oid()) - end - return self._meta._id -end - -function _M._metadata(self, file_md5) - local doc = { - _id = self:_files_id(), - length = self:raw_length(), - chunkSize = self:raw_chunk_size(), - uploadDate = cbson.date(os.time(os.date('!*t'))*1000), - md5 = file_md5, - filename = self:filename() or nil, - content_type = self:content_type() or nil, - metadata = self:metadata() or nil - } - - return doc -end - -function _M._slice(self, n, chunk) - local offset = self._pos - (n * self:chunk_size()) - local chunk = chunk:raw() - self._pos = self._pos + chunk:len() - return chunk:sub(offset+1); -end - -function _M._chunk(self) - local chunk = self._buffer:sub(1,self:chunk_size()) - if not chunk then - return - end - self._buffer = self._buffer:sub(self:chunk_size()+1) - local n = self._n - self._n = self._n+1 - local data = cbson.binary("") - data:raw(chunk, chunk:len()) - if self._write_only then - -- collect chunks for insert - table.insert(self._chunks, {files_id = self:_files_id(), n = cbson.uint(n), data = data}) - return true - else - -- insert immidiately, so we can read back (ugh) - return self._gridfs._chunks:insert({{files_id = self:_files_id(), n = cbson.uint(n), data = data}}) - end -end - - - -return _M diff --git a/website/backend/app/libs/resty/moongoo/utils.lua b/website/backend/app/libs/resty/moongoo/utils.lua deleted file mode 100755 index e0dce3f..0000000 --- a/website/backend/app/libs/resty/moongoo/utils.lua +++ /dev/null @@ -1,192 +0,0 @@ -local bit = require("bit") -local cbson = require("cbson") - -local md5 = ngx and ngx.md5 or function(str) return require("crypto").digest("md5", str) end -local hmac_sha1 = ngx and ngx.hmac_sha1 or function(str, key) return require("crypto").hmac.digest("sha1", key, str, true) end -local hasposix , posix = pcall(require, "posix") - -local machineid -if hasposix then - machineid = posix.uname("%n") -else - machineid = assert(io.popen("uname -n")):read("*l") -end -machineid = md5(machineid):sub(1, 6) - -local function uint_to_hex(num, len, be) - local len = len or 4 - local be = be or 0 - local num = cbson.uint(num) - local raw = cbson.uint_to_raw(num, len, be) - local out = '' - for i = 1, #raw do - out = out .. string.format("%02x", raw:byte(i,i)) - end - return out -end - -local counter = 0 - -if not ngx then - math.randomseed(os.time()) - counter = math.random(100) -else - local resty_random = require "resty.random" - local resty_string = require "resty.string" - local strong_random = resty_random.bytes(4,true) - while strong_random == nil do - strong_random = resty_random.bytes(4,true) - end - counter = tonumber(resty_string.to_hex(strong_random), 16) -end - -local function generate_oid() - local pid = ngx and ngx.worker.pid() or nil - if not pid then - if hasposix then - pid = posix.getpid("pid") - else - pid = 1 - end - end - - pid = uint_to_hex(pid,2) - - counter = counter + 1 - local time = os.time() - - return uint_to_hex(time, 4, 1) .. machineid .. pid .. uint_to_hex(counter, 4, 1):sub(3,8) -end - -local function print_r(t, indent) - local indent=indent or '' - if #indent > 5 then return end - if type(t) ~= "table" then - print(t) - return - end - for key,value in pairs(t) do - io.write(indent,'[',tostring(key),']') - if type(value)=="table" then io.write(':\n') print_r(value,indent..'\t') - else io.write(' = ',tostring(value),'\n') end - end -end - -local function parse_uri(url) - -- initialize default parameters - local parsed = {} - -- empty url is parsed to nil - if not url or url == "" then return nil, "invalid url" end - -- remove whitespace - url = string.gsub(url, "%s", "") - -- get fragment - url = string.gsub(url, "#(.*)$", function(f) - parsed.fragment = f - return "" - end) - -- get scheme - url = string.gsub(url, "^([%w][%w%+%-%.]*)%:", - function(s) parsed.scheme = s; return "" end) - - -- get authority - local location - url = string.gsub(url, "^//([^/]*)", function(n) - location = n - return "" - end) - - -- get query stringing - url = string.gsub(url, "%?(.*)", function(q) - parsed.query_string = q - return "" - end) - -- get params - url = string.gsub(url, "%;(.*)", function(p) - parsed.params = p - return "" - end) - -- path is whatever was left - if url ~= "" then parsed.database = string.gsub(url,"^/([^/]*).*","%1") end - if not parsed.database or #parsed.database == 0 then parsed.database = "admin" end - - if not location then return parsed end - - location = string.gsub(location,"^([^@]*)@", - function(u) parsed.userinfo = u; return "" end) - - parsed.hosts = {} - string.gsub(location, "([^,]+)", function(u) - local pr = { host = "localhost", port = 27017 } - u = string.gsub(u, ":([^:]*)$", - function(p) pr.port = p; return "" end) - if u ~= "" then pr.host = u end - table.insert(parsed.hosts, pr) - end) - if #parsed.hosts == 0 then parsed.hosts = {{ host = "localhost", port = 27017 }} end - - parsed.query = {} - if parsed.query_string then - string.gsub(parsed.query_string, "([^&]+)", function(u) - u = string.gsub(u, "([^=]*)=([^=]*)$", - function(k,v) parsed.query[k] = v; return "" end) - end) - end - - local userinfo = parsed.userinfo - if not userinfo then return parsed end - userinfo = string.gsub(userinfo, ":([^:]*)$", - function(p) parsed.password = p; return "" end) - parsed.user = userinfo - return parsed -end - -local function xor_bytestr( a, b ) - local res = "" - for i=1,#a do - res = res .. string.char(bit.bxor(string.byte(a,i,i), string.byte(b, i, i))) - end - return res -end - -local function xor_bytestr( a, b ) - local res = "" - for i=1,#a do - res = res .. string.char(bit.bxor(string.byte(a,i,i), string.byte(b, i, i))) - end - return res -end - --- A simple implementation of PBKDF2_HMAC_SHA1 -local function pbkdf2_hmac_sha1( pbkdf2_key, iterations, salt, len ) - local u1 = hmac_sha1(pbkdf2_key, salt .. "\0\0\0\1") - local ui = u1 - for i=1,iterations-1 do - u1 = hmac_sha1(pbkdf2_key, u1) - ui = xor_bytestr(ui, u1) - end - if #ui < len then - for i=1,len-(#ui) do - ui = string.char(0) .. ui - end - end - return ui -end - --- not full implementation, but oh well -local function saslprep(username) - return string.gsub(string.gsub(username, '=', '=3D'), ',' , '=2C') -end - -local function pass_digest ( username , password ) - return md5(username .. ":mongo:" .. password) -end - -return { - parse_uri = parse_uri; - print_r = print_r; - pbkdf2_hmac_sha1 = pbkdf2_hmac_sha1; - saslprep = saslprep; - pass_digest = pass_digest; - xor_bytestr = xor_bytestr; - generate_oid = generate_oid; -} diff --git a/website/backend/app/libs/resty/redis/redis.lua b/website/backend/app/libs/resty/redis/redis.lua deleted file mode 100755 index 505341d..0000000 --- a/website/backend/app/libs/resty/redis/redis.lua +++ /dev/null @@ -1,439 +0,0 @@ --- Copyright (C) Yichun Zhang (agentzh) - - -local sub = string.sub -local byte = string.byte -local tcp = ngx.socket.tcp -local null = ngx.null -local type = type -local pairs = pairs -local unpack = unpack -local setmetatable = setmetatable -local tonumber = tonumber -local tostring = tostring -local rawget = rawget ---local error = error - - -local ok, new_tab = pcall(require, "table.new") -if not ok or type(new_tab) ~= "function" then - new_tab = function (narr, nrec) return {} end -end - - -local _M = new_tab(0, 54) - -_M._VERSION = '0.26' - - -local common_cmds = { - "get", "set", "mget", "mset", - "del", "incr", "decr", -- Strings - "llen", "lindex", "lpop", "lpush", - "lrange", "linsert", -- Lists - "hexists", "hget", "hset", "hmget", - --[[ "hmset", ]] "hdel", -- Hashes - "smembers", "sismember", "sadd", "srem", - "sdiff", "sinter", "sunion", -- Sets - "zrange", "zrangebyscore", "zrank", "zadd", - "zrem", "zincrby", -- Sorted Sets - "auth", "eval", "expire", "script", - "sort" -- Others -} - - -local sub_commands = { - "subscribe", "psubscribe" -} - - -local unsub_commands = { - "unsubscribe", "punsubscribe" -} - - -local mt = { __index = _M } - - -function _M.new(self) - local sock, err = tcp() - if not sock then - return nil, err - end - return setmetatable({ _sock = sock, _subscribed = false }, mt) -end - - -function _M.set_timeout(self, timeout) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - return sock:settimeout(timeout) -end - - -function _M.connect(self, ...) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - self._subscribed = false - - return sock:connect(...) -end - - -function _M.set_keepalive(self, ...) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - if rawget(self, "_subscribed") then - return nil, "subscribed state" - end - - return sock:setkeepalive(...) -end - - -function _M.get_reused_times(self) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - return sock:getreusedtimes() -end - - -local function close(self) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - return sock:close() -end -_M.close = close - - -local function _read_reply(self, sock) - local line, err = sock:receive() - if not line then - if err == "timeout" and not rawget(self, "_subscribed") then - sock:close() - end - return nil, err - end - - local prefix = byte(line) - - if prefix == 36 then -- char '$' - -- print("bulk reply") - - local size = tonumber(sub(line, 2)) - if size < 0 then - return null - end - - local data, err = sock:receive(size) - if not data then - if err == "timeout" then - sock:close() - end - return nil, err - end - - local dummy, err = sock:receive(2) -- ignore CRLF - if not dummy then - return nil, err - end - - return data - - elseif prefix == 43 then -- char '+' - -- print("status reply") - - return sub(line, 2) - - elseif prefix == 42 then -- char '*' - local n = tonumber(sub(line, 2)) - - -- print("multi-bulk reply: ", n) - if n < 0 then - return null - end - - local vals = new_tab(n, 0) - local nvals = 0 - for i = 1, n do - local res, err = _read_reply(self, sock) - if res then - nvals = nvals + 1 - vals[nvals] = res - - elseif res == nil then - return nil, err - - else - -- be a valid redis error value - nvals = nvals + 1 - vals[nvals] = {false, err} - end - end - - return vals - - elseif prefix == 58 then -- char ':' - -- print("integer reply") - return tonumber(sub(line, 2)) - - elseif prefix == 45 then -- char '-' - -- print("error reply: ", n) - - return false, sub(line, 2) - - else - -- when `line` is an empty string, `prefix` will be equal to nil. - return nil, "unknown prefix: \"" .. tostring(prefix) .. "\"" - end -end - - -local function _gen_req(args) - local nargs = #args - - local req = new_tab(nargs * 5 + 1, 0) - req[1] = "*" .. nargs .. "\r\n" - local nbits = 2 - - for i = 1, nargs do - local arg = args[i] - if type(arg) ~= "string" then - arg = tostring(arg) - end - - req[nbits] = "$" - req[nbits + 1] = #arg - req[nbits + 2] = "\r\n" - req[nbits + 3] = arg - req[nbits + 4] = "\r\n" - - nbits = nbits + 5 - end - - -- it is much faster to do string concatenation on the C land - -- in real world (large number of strings in the Lua VM) - return req -end - - -local function _do_cmd(self, ...) - local args = {...} - - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - local req = _gen_req(args) - - local reqs = rawget(self, "_reqs") - if reqs then - reqs[#reqs + 1] = req - return - end - - -- print("request: ", table.concat(req)) - - local bytes, err = sock:send(req) - if not bytes then - return nil, err - end - - return _read_reply(self, sock) -end - - -local function _check_subscribed(self, res) - if type(res) == "table" - and (res[1] == "unsubscribe" or res[1] == "punsubscribe") - and res[3] == 0 - then - self._subscribed = false - end -end - - -function _M.read_reply(self) - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - if not rawget(self, "_subscribed") then - return nil, "not subscribed" - end - - local res, err = _read_reply(self, sock) - _check_subscribed(self, res) - - return res, err -end - - -for i = 1, #common_cmds do - local cmd = common_cmds[i] - - _M[cmd] = - function (self, ...) - return _do_cmd(self, cmd, ...) - end -end - - -for i = 1, #sub_commands do - local cmd = sub_commands[i] - - _M[cmd] = - function (self, ...) - self._subscribed = true - return _do_cmd(self, cmd, ...) - end -end - - -for i = 1, #unsub_commands do - local cmd = unsub_commands[i] - - _M[cmd] = - function (self, ...) - local res, err = _do_cmd(self, cmd, ...) - _check_subscribed(self, res) - return res, err - end -end - - -function _M.hmset(self, hashname, ...) - if select('#', ...) == 1 then - local t = select(1, ...) - - local n = 0 - for k, v in pairs(t) do - n = n + 2 - end - - local array = new_tab(n, 0) - - local i = 0 - for k, v in pairs(t) do - array[i + 1] = k - array[i + 2] = v - i = i + 2 - end - -- print("key", hashname) - return _do_cmd(self, "hmset", hashname, unpack(array)) - end - - -- backwards compatibility - return _do_cmd(self, "hmset", hashname, ...) -end - - -function _M.init_pipeline(self, n) - self._reqs = new_tab(n or 4, 0) -end - - -function _M.cancel_pipeline(self) - self._reqs = nil -end - - -function _M.commit_pipeline(self) - local reqs = rawget(self, "_reqs") - if not reqs then - return nil, "no pipeline" - end - - self._reqs = nil - - local sock = rawget(self, "_sock") - if not sock then - return nil, "not initialized" - end - - local bytes, err = sock:send(reqs) - if not bytes then - return nil, err - end - - local nvals = 0 - local nreqs = #reqs - local vals = new_tab(nreqs, 0) - for i = 1, nreqs do - local res, err = _read_reply(self, sock) - if res then - nvals = nvals + 1 - vals[nvals] = res - - elseif res == nil then - if err == "timeout" then - close(self) - end - return nil, err - - else - -- be a valid redis error value - nvals = nvals + 1 - vals[nvals] = {false, err} - end - end - - return vals -end - - -function _M.array_to_hash(self, t) - local n = #t - -- print("n = ", n) - local h = new_tab(0, n / 2) - for i = 1, n, 2 do - h[t[i]] = t[i + 1] - end - return h -end - - --- this method is deperate since we already do lazy method generation. -function _M.add_commands(...) - local cmds = {...} - for i = 1, #cmds do - local cmd = cmds[i] - _M[cmd] = - function (self, ...) - return _do_cmd(self, cmd, ...) - end - end -end - - -setmetatable(_M, {__index = function(self, cmd) - local method = - function (self, ...) - return _do_cmd(self, cmd, ...) - end - - -- cache the lazily generated method in our - -- module table - _M[cmd] = method - return method -end}) - - -return _M diff --git a/website/backend/app/libs/resty/smtp.lua b/website/backend/app/libs/resty/smtp.lua deleted file mode 100755 index 034bcf0..0000000 --- a/website/backend/app/libs/resty/smtp.lua +++ /dev/null @@ -1,321 +0,0 @@ ------------------------------------------------------------------------------ --- SMTP client support for the Lua language. --- LuaSocket toolkit. --- Author: Diego Nehab --- RCS ID: $Id: smtp.lua,v 1.46 2007/03/12 04:08:40 diego Exp $ ------------------------------------------------------------------------------ --- Author: Hungpu DU --- ChangeLog: --- * 2014/04/06 03:50:15 - Modified for lua-nginx-module with pure Lua ------------------------------------------------------------------------------ - - -local base = _G -local coroutine = require("coroutine") -local string = require("string") -local math = require("math") -local os = require("os") - -local mime = require("resty.smtp.mime") -local ltn12 = require("resty.smtp.ltn12") -local tp = require("resty.smtp.tp") -local misc = require("resty.smtp.misc") - -module("resty.smtp") - - - -_VERSION = "0.0.3" - --- timeout for connection -TIMEOUT = 6000 --- default server used to send e-mails -SERVER = "localhost" --- default port -PORT = 25 --- domain used in HELO command and default sendmail --- If we are under a CGI, try to get from environment -DOMAIN = "localhost" --- default time zone (means we don"t know) -ZONE = "-0000" - - -local metat = { __index= {} } - -function metat.__index:greet(domain) - self.try(self.tp:expect("2..")) - self.try(self.tp:command("EHLO", domain or DOMAIN)) - - return misc.skip(1, self.try(self.tp:expect("2.."))) -end - - -function metat.__index:mail(from) - self.try(self.tp:command("MAIL", "FROM:" .. from)) - - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:rcpt(to) - self.try(self.tp:command("RCPT", "TO:" .. to)) - - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:data(src, step) - self.try(self.tp:command("DATA")) - self.try(self.tp:expect("3..")) - self.try(self.tp:source(src, step)) - self.try(self.tp:send("\r\n.\r\n")) - - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:quit() - self.try(self.tp:command("QUIT")) - - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:close() - return self.tp:close() -end - - -function metat.__index:login(user, password) - self.try(self.tp:command("AUTH", "LOGIN")) - self.try(self.tp:expect("3..")) - self.try(self.tp:command(mime.b64(user))) - self.try(self.tp:expect("3..")) - self.try(self.tp:command(mime.b64(password))) - - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:plain(user, password) - local auth = "PLAIN " .. mime.b64("\0" .. user .. "\0" .. password) - self.try(self.tp:command("AUTH", auth)) - return self.try(self.tp:expect("2..")) -end - - -function metat.__index:auth(user, password, ext) - if not user or not password then return 1 end - - if string.find(ext, "AUTH[^\n]+LOGIN") then - return self:login(user, password) - - elseif string.find(ext, "AUTH[^\n]+PLAIN") then - return self:plain(user, password) - - else - self.try(nil, "authentication not supported") - end -end - - --- send message or throw an exception -function metat.__index:send(mailt) - self:mail(mailt.from) - - if base.type(mailt.rcpt) == "table" then - for i, v in base.ipairs(mailt.rcpt) do - self:rcpt(v) - end - - else - self:rcpt(mailt.rcpt) - end - - self:data(ltn12.source.chain(mailt.source, mime.stuff()), mailt.step) -end - - --- private methods --- -function open(server, port, timeout, create, ssl) - local tp = misc.try(tp.connect(server, port, timeout, create, ssl)) - local session = base.setmetatable({tp= tp}, metat) - - -- make sure tp is closed if we get an exception - session.try = misc.newtry(function() - session:close() - end) - return session -end - - --- convert headers to lowercase -local function lower_headers(headers) - local lower = {} - - for i,v in base.pairs(headers or lower) do - lower[string.lower(i)] = v - end - - return lower -end - - --- returns a hopefully unique mime boundary -local seqno = 0 -local function newboundary() - seqno = seqno + 1 - - return string.format("%s%05d==%05u", os.date("%d%m%Y%H%M%S"), - math.random(0, 99999), seqno) -end - - --- send_message forward declaration -local send_message - --- yield the headers all at once, it"s faster -local function send_headers(headers) - local h = {} - - for k, v in base.pairs(headers) do - base.table.insert(h, base.table.concat({k, v}, ": ")) - end - base.table.insert(h, "\r\n") - - coroutine.yield(base.table.concat(h, "\r\n")) -end - - --- yield multipart message body from a multipart message table -local function send_multipart(mesgt) - -- make sure we have our boundary and send headers - local bd = newboundary() - local headers = lower_headers(mesgt.headers or {}) - - headers["content-type"] = headers["content-type"] or "multipart/mixed" - headers["content-type"] = headers["content-type"] .. - '; boundary="' .. bd .. '"' - - send_headers(headers) - - -- send preamble - if mesgt.body.preamble then - coroutine.yield(mesgt.body.preamble) - coroutine.yield("\r\n") - end - - -- send each part separated by a boundary - for i, m in base.ipairs(mesgt.body) do - coroutine.yield("\r\n--" .. bd .. "\r\n") - send_message(m) - end - - -- send last boundary - coroutine.yield("\r\n--" .. bd .. "--\r\n\r\n") - - -- send epilogue - if mesgt.body.epilogue then - coroutine.yield(mesgt.body.epilogue) - coroutine.yield("\r\n") - end -end - - --- yield message body from a source -local function send_source(mesgt) - -- make sure we have a content-type - local headers = lower_headers(mesgt.headers or {}) - - headers["content-type"] = headers["content-type"] or - 'text/plain; charset="iso-8859-1"' - - send_headers(headers) - - -- send body from source - while true do - local chunk, err = mesgt.body() - if err then coroutine.yield(nil, err) - elseif chunk then coroutine.yield(chunk) - else break end - end -end - - --- yield message body from a string -local function send_string(mesgt) - -- make sure we have a content-type - local headers = lower_headers(mesgt.headers or {}) - - headers["content-type"] = headers["content-type"] or - 'text/plain; charset="iso-8859-1"' - - send_headers(headers) - - -- send body from string - coroutine.yield(mesgt.body) -end - - --- message source -function send_message(mesgt) - if base.type(mesgt.body) == "table" then - send_multipart(mesgt) - - elseif base.type(mesgt.body) == "function" then - send_source(mesgt) - - else - send_string(mesgt) - end -end - - --- set defaul headers -local function adjust_headers(mesgt) - -- to eliminate duplication for following headers - local lower = lower_headers(mesgt.headers) - - lower["date"] = lower["date"] or - os.date("!%a, %d %b %Y %H:%M:%S ") .. (mesgt.zone or ZONE) - lower["x-mailer"] = lower["x-mailer"] or VERSION - -- this can"t be overriden - lower["mime-version"] = "1.0" - - return lower -end - - -function message(mesgt) - mesgt.headers = adjust_headers(mesgt) - - -- create and return message source - local co = coroutine.create(function() send_message(mesgt) end) - - return function() - local ok, a, b = coroutine.resume(co) - if ok then return a, b - else return nil, a end - end -end - - --- public methods --- -send = misc.except(function(mailt) - local session = open(mailt.server or SERVER, mailt.port or PORT, - mailt.timeout or TIMEOUT, - mailt.create or base.ngx.socket.tcp, - mailt.ssl or {enable= false, verify_cert= false}) - - local ext = session:greet(mailt.domain) - - session:auth(mailt.user, mailt.password, ext) - session:send(mailt) - session:quit() - - return session:close() -end) - - diff --git a/website/backend/app/libs/resty/smtp/base64.lua b/website/backend/app/libs/resty/smtp/base64.lua deleted file mode 100755 index b0ecd95..0000000 --- a/website/backend/app/libs/resty/smtp/base64.lua +++ /dev/null @@ -1,142 +0,0 @@ ------------------------------------------------------------------------------ --- base64 convertion routines for the Lua language --- Author: Diego Nehab --- Date: 26/12/2000 --- Conforms to: RFC 1521 ------------------------------------------------------------------------------ --- Author: Hungpu DU --- Date: 2014/04/06 --- ChangeLog: --- * Taken from LuaSocket 1.1 and modified for Lua 5.1 --- * Modified to be suitable for b64 filter - -local math = require("math") -local string = require("string") - -module("resty.smtp.base64") - - - -local t64 = { - [0] = 'A', [1] = 'B', [2] = 'C', [3] = 'D', [4] = 'E', [5] = 'F', [6] = 'G', - [7] = 'H', [8] = 'I', [9] = 'J', [10] = 'K', [11] = 'L', [12] = 'M', - [13] = 'N', [14] = 'O', [15] = 'P', [16] = 'Q', [17] = 'R', [18] = 'S', - [19] = 'T', [20] = 'U', [21] = 'V', [22] = 'W', [23] = 'X', [24] = 'Y', - [25] = 'Z', [26] = 'a', [27] = 'b', [28] = 'c', [29] = 'd', [30] = 'e', - [31] = 'f', [32] = 'g', [33] = 'h', [34] = 'i', [35] = 'j', [36] = 'k', - [37] = 'l', [38] = 'm', [39] = 'n', [40] = 'o', [41] = 'p', [42] = 'q', - [43] = 'r', [44] = 's', [45] = 't', [46] = 'u', [47] = 'v', [48] = 'w', - [49] = 'x', [50] = 'y', [51] = 'z', [52] = '0', [53] = '1', [54] = '2', - [55] = '3', [56] = '4', [57] = '5', [58] = '6', [59] = '7', [60] = '8', - [61] = '9', [62] = '+', [63] = '/', -} - -local f64 = { - ['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3, ['E'] = 4, ['F'] = 5, ['G'] = 6, - ['H'] = 7, ['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11, ['M'] = 12, - ['N'] = 13, ['O'] = 14, ['P'] = 15, ['Q'] = 16, ['R'] = 17, ['S'] = 18, - ['T'] = 19, ['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23, ['Y'] = 24, - ['Z'] = 25, ['a'] = 26, ['b'] = 27, ['c'] = 28, ['d'] = 29, ['e'] = 30, - ['f'] = 31, ['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35, ['k'] = 36, - ['l'] = 37, ['m'] = 38, ['n'] = 39, ['o'] = 40, ['p'] = 41, ['q'] = 42, - ['r'] = 43, ['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47, ['w'] = 48, - ['x'] = 49, ['y'] = 50, ['z'] = 51, ['0'] = 52, ['1'] = 53, ['2'] = 54, - ['3'] = 55, ['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59, ['8'] = 60, - ['9'] = 61, ['+'] = 62, ['/'] = 63, -} - - -local t2f = function(a, b, c) - local s = a:byte() * 65536 + b:byte() * 256 + c:byte() - local ca, cb, cc, cd - - cd = math.fmod(s, 64) - s = (s - cd) / 64 - cc = math.fmod(s, 64) - s = (s - cc) / 64 - cb = math.fmod(s, 64) - ca = (s - cb) / 64 - - return t64[ca] .. t64[cb] .. t64[cc] .. t64[cd] -end - - -local f2t = function(a, b, c, d) - local s, ca, cb, cc - - if d ~= "=" then - s = f64[a] * 262144 + f64[b] * 4096 + f64[c] * 64 + f64[d] - - cc = math.fmod(s, 256) - s = (s - cc) / 256 - cb = math.fmod(s, 256) - ca = (s - cb) / 256 - - return string.char(ca, cb, cc) - - elseif c ~= "=" then - s = f64[a] * 1024 + f64[b] * 16 + f64[c] / 4 - cb = math.fmod(s, 256) - ca = (s - cb) / 256 - - return string.char(ca, cb) - - else - s = f64[a] * 4 + f64[b] / 16 - ca = math.fmod(s, 256) - return string.char(ca) - end -end - - -function pad(chunk) - local s, a, b, ca, cb, cc - - if #chunk == 0 then return "" end - - _, _, a, b = chunk:find("(.?)(.?)") - if b == "" then - s = a:byte() * 16 - cb = math.fmod(s, 64) - ca = (s - cb)/64 - return t64[ca] .. t64[cb] .. "==" - - else - s = a:byte() * 1024 + b:byte() * 4 - cc = math.fmod(s, 64) - s = (s - cc) / 64 - cb = math.fmod(s, 64) - ca = (s - cb)/64 - return t64[ca] .. t64[cb] .. t64[cc] .. "=" - end -end - - -function encode(chunk) - local l = #chunk - local r = math.fmod(l, 3) - - l = l - r - if l <= 0 then return "", chunk end - - return string.gsub(chunk:sub(1, l), "(.)(.)(.)", t2f), chunk:sub(l + 1) -end - -function decode(chunk) - local l = #chunk - local r = math.fmod(l, 4) - - l = l - r - if l <= 0 then return "", chunk end - - return string.gsub(chunk:sub(1, l), "(.)(.)(.)(.)", f2t), chunk:sub(l + 1) -end - - --- for Encoded Word --- -function qencode(chunk) return encode(chunk) end -function qdecode(chunk) return decode(chunk) end -function qpad(chunk) return pad(chunk) end - - diff --git a/website/backend/app/libs/resty/smtp/ltn12.lua b/website/backend/app/libs/resty/smtp/ltn12.lua deleted file mode 100755 index 9267823..0000000 --- a/website/backend/app/libs/resty/smtp/ltn12.lua +++ /dev/null @@ -1,297 +0,0 @@ ------------------------------------------------------------------------------ --- LTN12 - Filters, sources, sinks and pumps. --- LuaSocket toolkit. --- Author: Diego Nehab --- RCS ID: $Id: ltn12.lua,v 1.31 2006/04/03 04:45:42 diego Exp $ ------------------------------------------------------------------------------ - ------------------------------------------------------------------------------ --- Declare module ------------------------------------------------------------------------------ -local base = _G -local string = require("string") -local table = require("table") - -module("resty.smtp.ltn12") - - - -filter = {} -source = {} -sink = {} -pump = {} - --- 2048 seems to be better in windows... -BLOCKSIZE = 2048 -_VERSION = "LTN12 1.0.1" - ------------------------------------------------------------------------------ --- Filter stuff ------------------------------------------------------------------------------ --- returns a high level filter that cycles a low-level filter -function filter.cycle(low, ctx, extra) - base.assert(low) - return function(chunk) - local ret - ret, ctx = low(ctx, chunk, extra) - return ret - end -end - --- chains a bunch of filters together --- (thanks to Wim Couwenberg) -function filter.chain(...) - local arg = {...} - local n = #arg - local top, index = 1, 1 - local retry = "" - return function(chunk) - retry = chunk and retry - while true do - if index == top then - chunk = arg[index](chunk) - if chunk == "" or top == n then return chunk - elseif chunk then index = index + 1 - else - top = top+1 - index = top - end - else - chunk = arg[index](chunk or "") - if chunk == "" then - index = index - 1 - chunk = retry - elseif chunk then - if index == n then return chunk - else index = index + 1 end - else base.error("filter returned inappropriate nil") end - end - end - end -end - ------------------------------------------------------------------------------ --- Source stuff ------------------------------------------------------------------------------ --- create an empty source -local function empty() - return nil -end - -function source.empty() - return empty -end - --- returns a source that just outputs an error -function source.error(err) - return function() - return nil, err - end -end - --- creates a file source -function source.file(handle, io_err) - if handle then - return function() - local chunk = handle:read(BLOCKSIZE) - if not chunk then handle:close() end - return chunk - end - else return source.error(io_err or "unable to open file") end -end - --- turns a fancy source into a simple source -function source.simplify(src) - base.assert(src) - return function() - local chunk, err_or_new = src() - src = err_or_new or src - if not chunk then return nil, err_or_new - else return chunk end - end -end - --- creates string source -function source.string(s) - if s then - local i = 1 - return function() - local chunk = string.sub(s, i, i+BLOCKSIZE-1) - i = i + BLOCKSIZE - if chunk ~= "" then return chunk - else return nil end - end - else return source.empty() end -end - --- creates rewindable source -function source.rewind(src) - base.assert(src) - local t = {} - return function(chunk) - if not chunk then - chunk = table.remove(t) - if not chunk then return src() - else return chunk end - else - table.insert(t, chunk) - end - end -end - -function source.chain(src, f) - base.assert(src and f) - local last_in, last_out = "", "" - local state = "feeding" - local err - return function() - if not last_out then - base.error('source is empty!', 2) - end - while true do - if state == "feeding" then - last_in, err = src() - if err then return nil, err end - last_out = f(last_in) - if not last_out then - if last_in then - base.error('filter returned inappropriate nil') - else - return nil - end - elseif last_out ~= "" then - state = "eating" - if last_in then last_in = "" end - return last_out - end - else - last_out = f(last_in) - if last_out == "" then - if last_in == "" then - state = "feeding" - else - base.error('filter returned ""') - end - elseif not last_out then - if last_in then - base.error('filter returned inappropriate nil') - else - return nil - end - else - return last_out - end - end - end - end -end - --- creates a source that produces contents of several sources, one after the --- other, as if they were concatenated --- (thanks to Wim Couwenberg) -function source.cat(...) - local arg = {...} - local src = table.remove(arg, 1) - return function() - while src do - local chunk, err = src() - if chunk then return chunk end - if err then return nil, err end - src = table.remove(arg, 1) - end - end -end - ------------------------------------------------------------------------------ --- Sink stuff ------------------------------------------------------------------------------ --- creates a sink that stores into a table -function sink.table(t) - t = t or {} - local f = function(chunk, err) - if chunk then table.insert(t, chunk) end - return 1 - end - return f, t -end - --- turns a fancy sink into a simple sink -function sink.simplify(snk) - base.assert(snk) - return function(chunk, err) - local ret, err_or_new = snk(chunk, err) - if not ret then return nil, err_or_new end - snk = err_or_new or snk - return 1 - end -end - --- creates a file sink -function sink.file(handle, io_err) - if handle then - return function(chunk, err) - if not chunk then - handle:close() - return 1 - else return handle:write(chunk) end - end - else return sink.error(io_err or "unable to open file") end -end - --- creates a sink that discards data -local function null() - return 1 -end - -function sink.null() - return null -end - --- creates a sink that just returns an error -function sink.error(err) - return function() - return nil, err - end -end - --- chains a sink with a filter -function sink.chain(f, snk) - base.assert(f and snk) - return function(chunk, err) - if chunk ~= "" then - local filtered = f(chunk) - local done = chunk and "" - while true do - local ret, snkerr = snk(filtered, err) - if not ret then return nil, snkerr end - if filtered == done then return 1 end - filtered = f(done) - end - else return 1 end - end -end - ------------------------------------------------------------------------------ --- Pump stuff ------------------------------------------------------------------------------ --- pumps one chunk from the source to the sink -function pump.step(src, snk) - local chunk, src_err = src() - local ret, snk_err = snk(chunk, src_err) - if chunk and ret then return 1 - else return nil, src_err or snk_err end -end - --- pumps all data from a source to a sink, using a step function -function pump.all(src, snk, step) - base.assert(src and snk) - step = step or pump.step - while true do - local ret, err = step(src, snk) - if not ret then - if err then return nil, err - else return 1 end - end - end -end - diff --git a/website/backend/app/libs/resty/smtp/mime-core.lua b/website/backend/app/libs/resty/smtp/mime-core.lua deleted file mode 100755 index 0911c27..0000000 --- a/website/backend/app/libs/resty/smtp/mime-core.lua +++ /dev/null @@ -1,271 +0,0 @@ -local base = _G -local string = require("string") -local base64 = require("resty.smtp.base64") -local qpcore = require("resty.smtp.qp") - -module("resty.smtp.mime") - - - --- FIXME following mime-relative string operations are quite inefficient --- compared with original C version, maybe FFI can help? --- --- base64 --- -function b64(ctx, chunk, extra) - local part1, part2 - - if not ctx then return nil, nil end - - -- remaining data from last round - part1, ctx = base64.encode(ctx) - - if not chunk then - part1 = part1 .. base64.pad(ctx) - - if #part1 == 0 then return nil, nil - else return part1, nil end - end - - -- second part - part2, ctx = base64.encode(ctx .. chunk) - - return part1 .. part2, ctx -end - -function unb64(ctx, chunk, extra) - local part1, part2 - - if not ctx then return nil, nil end - - -- remaining data from last round - part1, ctx = base64.decode(ctx) - - if not chunk then - if #part1 == 0 then return nil, nil - else return part1, nil end - end - - -- second part - part2, ctx = base64.decode(ctx .. chunk) - - return part1 .. part2, ctx -end - - --- quoted-printable --- -function qp(ctx, chunk, extra) - local part1, part2, marker - - if not ctx then return nil, nil end - - marker = extra or "\r\n" - part1, ctx = qpcore.encode(ctx, marker) - - if not chunk then - part1 = part1 .. qpcore.pad(ctx) - - if #part1 == 0 then return nil, nil - else return part1, nil end - end - - -- second part - part2, ctx = qpcore.encode(ctx .. chunk, marker) - - return part1 .. part2, ctx -end - -function unqp(ctx, chunk, extra) - local part1, part2 - - if not ctx then return nil, nil end - - -- remaining data from last round - part1, ctx = qpcore.decode(ctx) - - if not chunk then - if #part1 == 0 then return nil, nil - else return part1, nil end - end - - -- second part - part2, ctx = qpcore.decode(ctx .. chunk) - - return part1 .. part2, ctx -end - - --- line-wrap --- -function wrp(ctx, chunk, extra) - -- `ctx` shows how many more bytes current line can still hold - -- before reach the limit `length` - local buffer, length = "", extra or 76 - - if not chunk then - -- last line already has some chars except \r\n - if ctx < length then return buffer .. "\r\n", length - else return nil, length end - end - - for i = 1, #chunk do - local char = chunk:sub(i, i) - - if char == '\r' then - -- take it as part of "\r\n" - elseif char == '\n' then - buffer, ctx = buffer .. "\r\n", length - else - if ctx <= 0 then -- hit the limit - buffer, ctx = buffer .. "\r\n", length - end - - buffer, ctx = buffer .. char, ctx - 1 - end - end - - return buffer, ctx -end - -function qpwrp(ctx, chunk, extra) - -- `ctx` shows how many more bytes current line can still hold - -- before reach the limit `length` - local buffer, length = "", extra or 76 - - if not chunk then - -- last line already has some chars except \r\n - if ctx < length then return buffer .. "=\r\n", length - else return nil, length end - - end - - for i = 1, #chunk do - local char = chunk:sub(i, i) - - if char == '\r' then - -- take it as part of "\r\n" - elseif char == '\n' then - buffer, ctx = buffer .. "\r\n", length - elseif char == '=' then - if ctx <= 3 then - buffer, ctx = buffer .. "=\r\n", length - end - - buffer, ctx = buffer .. char, ctx - 1 - - else - if ctx <= 1 then - buffer, ctx = buffer .. "=\r\n", length - end - - buffer, ctx = buffer .. char, ctx - 1 - end - end - - return buffer, ctx -end - - --- encoded word --- -function ew(ctx, chunk, extra) - local part0, part1, part2 = "", "", "" - local c, e, f - - base.assert(base.type(extra) == "table") - - c = extra.charset or "utf-8" - e = extra.encoding or "B" - m = (e == "Q") and qpcore or base64 - - -- TODO not support Q-encoding yet - base.assert(e == "B") - - if extra.initial == nil or extra.initial then - part0 = string.format("=?%s?%s?", c, e) - extra.initial = false - end - - part1, ctx = m.qencode(ctx, true) - - if not chunk then - part1 = part1 .. m.qpad(ctx, true) - return part0 .. part1 .. "?=", nil - end - - part2, ctx = m.qencode(ctx .. chunk, true) - - return part0 .. part1 .. part2, ctx -end - --- --- extra - the charset to converted to -function unew(ctx, chunk, extra) - -- TODO - -- This one needs a little more work, because we have to decode - -- `chunk` with both specified encoding and charset on the fly. - -- -end - - --- dot --- -function dot(ctx, chunk, extra) - local buffer = "" - - if not chunk then return nil, 2 end - - for i = 1, #chunk do - local char = string.char(string.byte(chunk, i)) - - buffer = buffer .. char - - if char == '\r' then - ctx = 1 - elseif char == '\n' then - ctx = (ctx == 1) and 2 or 0 - elseif char == "." then - if ctx == 2 then buffer = buffer .. "." end - ctx = 0 - else - ctx = 0 - end - end - - return buffer, ctx -end - - --- eol --- -function eol(ctx, chunk, marker) - local buffer = "" - - if not chunk then return nil, 0 end - - local eolcandidate = function(char) - return (char == '\r') or (char == '\n') - end - - for i = 1, #chunk do - local char = string.char(string.byte(chunk, i)) - - if eolcandidate(char) then - if eolcandidate(ctx) then - if char == ctx then buffer = buffer .. marker end - ctx = 0 - else - buffer = buffer .. marker - ctx = char - end - - else - buffer = buffer .. char - ctx = 0 - end - end - - return buffer, ctx -end - diff --git a/website/backend/app/libs/resty/smtp/mime.lua b/website/backend/app/libs/resty/smtp/mime.lua deleted file mode 100755 index a155dca..0000000 --- a/website/backend/app/libs/resty/smtp/mime.lua +++ /dev/null @@ -1,103 +0,0 @@ ------------------------------------------------------------------------------ --- MIME support for the Lua language. --- Author: Diego Nehab --- Conforming to RFCs 2045-2049 --- RCS ID: $Id: mime.lua,v 1.29 2007/06/11 23:44:54 diego Exp $ ------------------------------------------------------------------------------ - ------------------------------------------------------------------------------ --- Declare module and import dependencies ------------------------------------------------------------------------------ -local base = _G -local io = require("io") -local string = require("string") - -require("resty.smtp.mime-core") -local ltn12 = require("resty.smtp.ltn12") - -module("resty.smtp.mime") - - - --- encode, decode and wrap algorithm tables -encodet = {} -decodet = {} -wrapt = {} - --- creates a function that chooses a filter by name from a given table -local function choose(table) - return function(name, opt1, opt2) - if base.type(name) ~= "string" then - name, opt1, opt2 = "default", name, opt1 - end - local f = table[name or "nil"] - if not f then - base.error("unknown key (" .. base.tostring(name) .. ")", 3) - else return f(opt1, opt2) end - end -end - --- define the encoding filters -encodet['base64'] = function() - return ltn12.filter.cycle(b64, "") -end - -encodet['quoted-printable'] = function(mode) - return ltn12.filter.cycle(qp, "", - (mode == "binary") and "=0D=0A" or "\r\n") -end - -encodet['encoded-word'] = function(charset, encoding) - return ltn12.filter.cycle(ew, "", - { charset= charset or "utf-8", encoding= encoding or "B" }) -end - --- define the decoding filters -decodet['base64'] = function() - return ltn12.filter.cycle(unb64, "") -end - -decodet['quoted-printable'] = function() - return ltn12.filter.cycle(unqp, "") -end - -decodet['encoded-word'] = function(encoding) - return ltn12.filter.cycle(unew, "", - { encoding= encoding or "Q" }) -end - -local function format(chunk) - if chunk then - if chunk == "" then return "''" - else return string.len(chunk) end - else return "nil" end -end - --- define the line-wrap filters -wrapt['text'] = function(length) - length = length or 76 - return ltn12.filter.cycle(wrp, length, length) -end -wrapt['base64'] = wrapt['text'] -wrapt['default'] = wrapt['text'] - -wrapt['quoted-printable'] = function() - return ltn12.filter.cycle(qpwrp, 76, 76) -end - --- function that choose the encoding, decoding or wrap algorithm -encode = choose(encodet) -decode = choose(decodet) -wrap = choose(wrapt) - --- define the end-of-line normalization filter -function normalize(marker) - if not marker then marker = '\r\n' end - return ltn12.filter.cycle(eol, 0, marker) -end - --- high level stuffing filter -function stuff() - return ltn12.filter.cycle(dot, 2) -end - diff --git a/website/backend/app/libs/resty/smtp/misc.lua b/website/backend/app/libs/resty/smtp/misc.lua deleted file mode 100755 index ccf06d3..0000000 --- a/website/backend/app/libs/resty/smtp/misc.lua +++ /dev/null @@ -1,37 +0,0 @@ -local base = _G - -module("resty.smtp.misc") - - -function skip(amount, ...) - return base.unpack({ ... }, amount + 1) -end - - -function newtry(atexit) - return function(...) - local ret, err = base.select(1, ...), base.select(2, ...) - - if ret then return ... end - if base.type(atexit) == "function" then atexit() end - - base.error(err, 2) - -- never be here - return ret - end -end - - -function except(func) - return function(...) - local ok, ret = base.pcall(func, ...) - - if not ok then return nil, ret - else return ret end - end -end - - -try = newtry() - - diff --git a/website/backend/app/libs/resty/smtp/qp.lua b/website/backend/app/libs/resty/smtp/qp.lua deleted file mode 100755 index 2d99f12..0000000 --- a/website/backend/app/libs/resty/smtp/qp.lua +++ /dev/null @@ -1,222 +0,0 @@ -local base = _G -local math = require("math") -local table = require("table") -local string = require("string") - -module("resty.smtp.qp") - - - ---[[ - -[Quoted-Printable Rules](http://en.wikipedia.org/wiki/Quoted-printable) - -* "All characters except printable ASCII characters" or "end of line characters" - must be encoded. - -* All printable ASCII characters (decimal 33-126) may be represented by - themselves, except "=" (decimal 61) - -* ASCII tab (decimal 9) and space (decimal 32) may be represented by themselves, - except if these characters would appear at the end of the encoded line. In - that case, they would need to be escaped as "=09" or "=20" (what we use), or - be followed by a "=" (soft line break). - -* If the data being encoded contains meaningful line breaks, they must be - encoded as an ASCII CRLF sequence. Conversely, if byte value 13 and 10 have - meanings other than end of line (in media types, for example), they must - be encoded as "=0D" and "=0A" respectively. - -* Lines of Quoted-Printable encoded data must not be longer than 76 characters. - To satisfy this requirement without altering the encoded text, - _soft line breaks_ consists of an "=" at the end of an encoded line, and does - not appear as a line break in the decoded text. - - -Encoded-Word - A slightly modified version of Quoted-Printable used in message -headers. - - -[RFC 2045](http://tools.ietf.org/html/rfc2045#page-19) - ---]] - -local QP_PLAIN = 0 -local QP_QUOTE = 1 -local QP_IF_LAST = 3 -local QP_BYTE_CR = 13 -- '\r' -local QP_BYTE_LF = 10 -- '\n' - - -qpte = { --- 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 2, 1, 1, -- 0 - 15 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 16 - 31 - 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 32 - 47 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, -- 48 - 63 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 64 - 79 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 80 - 95 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- 96 - 111 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -- 112 - 127 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 128 - 143 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 144 - 159 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 160 - 175 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 176 - 191 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 192 - 207 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 208 - 223 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 224 - 239 - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -- 240 - 255 -} - - - -qptd = { -} - - -local HEX_BASE = "0123456789ABCDEF" - -local quote = function(byte) - local f, s = math.floor(byte/16) + 1, math.fmod(byte, 16) + 1 - return table.concat({ '=', HEX_BASE:sub(f, f), HEX_BASE:sub(s, s) }) -end - - -local HEX_LOOKUP = { - ['0']= 0, ['1']= 1, ['2']= 2, ['3']= 3, - ['4']= 4, ['5']= 5, ['6']= 6, ['7']= 7, - ['8']= 8, ['9']= 9, ['a']= 10, ['b']= 11, - ['c']= 12, ['d']= 13, ['e']= 14, ['f']= 15, - ['A']= 10, ['B']= 11, - ['C']= 12, ['D']= 13, ['E']= 14, ['F']= 15, -} - -local unquote = function(fp, sp) - local hp, lp = HEX_LOOKUP[fp], HEX_LOOKUP[sp] - - if not hp or not lp then return nil - else return string.char(hp * 16 + lp) end -end - -local printable = function(char) - local byte = string.byte(char) - return (byte > 31) and (byte < 127) -end - - -function pad(chunk) - local buffer, byte = "", 0 - - for i = 1, #chunk do - byte = string.byte(chunk, i) - - if qpte[byte + 1] == QP_PLAIN then - buffer = buffer .. string.char(byte) - else - buffer = buffer .. quote(byte) - end - end - - -- soft break - if #buffer > 0 then buffer = buffer .. "=\r\n" end - - return buffer -end - - -function encode(chunk, marker) - local atom, buffer = {}, "" - - for i = 1, #chunk do - table.insert(atom, string.byte(chunk, i)) - - repeat - local shift = 1 - - if atom[1] == QP_BYTE_CR then - if #atom < 2 then -- need more - break - elseif atom[2] == QP_BYTE_LF then - buffer, shift = buffer .. marker, 2 - else - buffer = buffer .. quote(atom[1]) - end - - elseif qpte[atom[1] + 1] == QP_IF_LAST then - if #atom < 3 then -- need more - break - elseif atom[2] == QP_BYTE_CR and atom[3] == QP_BYTE_LF then - buffer, shift = buffer .. quote(atom[1]) .. marker, 3 - else -- space not in the end - buffer = buffer .. string.char(atom[1]) - end - - elseif qpte[atom[1] + 1] == QP_QUOTE then - buffer = buffer .. quote(atom[1]) - - else -- printable char - buffer = buffer .. string.char(atom[1]) - end - - -- shift out used chars - for i = 1, 3 do atom[i] = atom[i + shift] end - - until #atom == 0 - - end - - for i = 1, 3 do - atom[i] = atom[i] and string.char(atom[i]) or "" - end - - return buffer, table.concat(atom, "") -end - - -function decode(chunk) - local atom, buffer = {}, "" - - for i = 1, #chunk do - table.insert(atom, chunk:sub(i, i)) - - repeat - local shift = 3 - - if atom[1] == '=' then - if #atom < 3 then -- need more - break - elseif atom[2] == '\r' and atom[3] == '\n' then - -- eliminate soft line break - else - local char = unquote(atom[2], atom[3]) - if not char then - buffer = buffer .. table.concat(atom, "") - else - buffer = buffer .. char - end - end - - elseif atom[1] == '\r' then - if #atom < 2 then -- need more - break - elseif atom[2] == '\n' then - buffer, shift = buffer .. "\r\n", 2 - else -- neglect this '\r' and following char - shift = 2 - end - - else - if atom[1] == '\t' or printable(atom[1]) then - buffer, shift = buffer .. atom[1], 1 - end - end - - -- shift out used chars - for i = 1, 3 do atom[i] = atom[i + shift] end - - until #atom == 0 - end - - return buffer, table.concat(atom, "") -end - diff --git a/website/backend/app/libs/resty/smtp/tp.lua b/website/backend/app/libs/resty/smtp/tp.lua deleted file mode 100755 index f9b62b5..0000000 --- a/website/backend/app/libs/resty/smtp/tp.lua +++ /dev/null @@ -1,145 +0,0 @@ ------------------------------------------------------------------------------ --- Unified SMTP/FTP subsystem --- LuaSocket toolkit. --- Author: Diego Nehab --- RCS ID: $Id: tp.lua,v 1.22 2006/03/14 09:04:15 diego Exp $ ------------------------------------------------------------------------------ --- Author: duhoobo --- ChangeLog: --- * 2014/04/06 03:47:15 - simplified for lua-module-module ------------------------------------------------------------------------------ - - -local base = _G -local string = require("string") - -local ltn12 = require("resty.smtp.ltn12") -local misc = require("resty.smtp.misc") - -module("resty.smtp.tp") - - --- gets server reply (works for SMTP and FTP) -local function get_reply(c) - local code, current, sep - local line, err = c:receive("*l") - local reply = line - - if err then return nil, err end - - code, sep = misc.skip(2, string.find(line, "^(%d%d%d)(.?)")) - - if not code then return nil, "invalid server reply" end - if sep == "-" then -- reply is multiline - repeat - line, err = c:receive("*l") - - if err then return nil, err end - - current, sep = misc.skip(2, string.find(line, "^(%d%d%d)(.?)")) - reply = reply .. "\n" .. line - -- reply ends with same code - until code == current and sep == " " - end - - return code, reply -end - - --- metatable for sock object -local metat = {__index= {}} - - -function metat.__index:expect(check) - local code, reply = get_reply(self.c) - - if not code then return nil, reply end - - if base.type(check) ~= "function" then - if base.type(check) == "table" then - for i, v in base.ipairs(check) do - if string.find(code, v) then - return base.tonumber(code), reply - end - end - - return nil, reply - - else -- string - if string.find(code, check) then - return base.tonumber(code), reply - else return nil, reply end - end - - else return check(base.tonumber(code), reply) end -end - - -function metat.__index:command(cmd, arg) - local request = cmd .. (arg and (" " .. arg) or "") .. "\r\n" - return self.c:send(request) -end - - -function metat.__index:sink(snk, pat) - local chunk, err = c:receive(pat) - return snk(chunk, err) -end - - -function metat.__index:send(data) - return self.c:send(data) -end - - -function metat.__index:receive(pat) - return self.c:receive(pat) -end - - -function metat.__index:source(source, step) - local sink = function(chunk, err) - if chunk then return self:send(chunk) - else return 1 end - end - - return ltn12.pump.all(source, sink, step or ltn12.pump.step) -end - - --- closes the underlying c -function metat.__index:close() - self.c:close() - return 1 -end - - --- connect with server and return c object -function connect(host, port, timeout, create, ssl) - local c, e = create() - if not c then return nil, e end - - c:settimeout(timeout) - - local r, e = c:connect(host, port) - if not r then - c:close() - return nil, e - end - - if ssl.enable then - if not c.sslhandshake then - c:close() - return nil, "socket does not have ssl support" - end - - local s, e = c:sslhandshake(nil, host, ssl.verify_cert) - if not s then - c:close() - return nil, "ssl handshake: " .. e - end - end - - return base.setmetatable({c= c}, metat) -end - diff --git a/website/backend/app/libs/utils.lua b/website/backend/app/libs/utils.lua deleted file mode 100755 index 120f89d..0000000 --- a/website/backend/app/libs/utils.lua +++ /dev/null @@ -1,153 +0,0 @@ -local type = type -local pairs = pairs -local type = type -local mceil = math.ceil -local mfloor = math.floor -local mrandom = math.random -local mmodf = math.modf -local sgsub = string.gsub -local tinsert = table.insert -local date = require("app.libs.date") -local resty_sha256 = require "resty.sha256" -local str = require "resty.string" -local ngx_quote_sql_str = ngx.quote_sql_str - - - -local _M = {} - -function _M.encode(s) - local sha256 = resty_sha256:new() - sha256:update(s) - local digest = sha256:final() - return str.to_hex(digest) -end - - -function _M.clear_slash(s) - s, _ = sgsub(s, "(/+)", "/") - return s -end - -function _M.is_table_empty(t) - if t == nil or _G.next(t) == nil then - return true - else - return false - end -end - -function _M.table_is_array(t) - if type(t) ~= "table" then return false end - local i = 0 - for _ in pairs(t) do - i = i + 1 - if t[i] == nil then return false end - end - return true -end - -function _M.mixin(a, b) - if a and b then - for k, v in pairs(b) do - a[k] = b[k] - end - end - return a -end - -function _M.random() - return mrandom(0, 1000) -end - - -function _M.total_page(total_count, page_size) - local total_page = 0 - if total_count % page_size == 0 then - total_page = total_count / page_size - else - local tmp, _ = mmodf(total_count/page_size) - total_page = tmp + 1 - end - - return total_page -end - - -function _M.days_after_registry(req) - local diff = 0 - local diff_days = 0 -- default value, days after registry - - if req and req.session then - local user = req.session.get("user") - local create_time = user and user.create_time - if create_time then - local now = date() -- seconds - create_time = date(create_time) - diff = date.diff(now, create_time):spandays() - diff_days = mfloor(diff) - end - end - - return diff_days, diff -end - -function _M.now() - local n = date() - local result = n:fmt("%Y-%m-%d %H:%M:%S") - return result -end - -function _M.secure_str(str) - return ngx_quote_sql_str(str) -end - - -function _M.string_split(str, delimiter) - if str==nil or str=='' or delimiter==nil then - return nil - end - - local result = {} - for match in (str..delimiter):gmatch("(.-)"..delimiter) do - tinsert(result, match) - end - return result -end - -return _M - - - - --- local resty_sha256 = require "resty.sha256" - -- local str = require "resty.string" - -- local sha256 = resty_sha256:new() - -- ngx.say(sha256:update("hello")) - -- local digest = sha256:final() - -- ngx.say("sha256: ", str.to_hex(digest)) - - -- local resty_md5 = require "resty.md5" - -- local md5 = resty_md5:new() - -- if not md5 then - -- ngx.say("failed to create md5 object") - -- return - -- end - - -- local ok = md5:update("hel") - -- if not ok then - -- ngx.say("failed to add data") - -- return - -- end - - -- ok = md5:update("lo") - -- if not ok then - -- ngx.say("failed to add data") - -- return - -- end - - -- local digest = md5:final() - - -- local str = require "resty.string" - -- ngx.say("md5: ", str.to_hex(digest)) - -- -- yield "md5: 5d41402abc4b2a76b9719d911017c592" diff --git a/website/backend/app/libs/uuid.lua b/website/backend/app/libs/uuid.lua deleted file mode 100755 index e65ddb8..0000000 --- a/website/backend/app/libs/uuid.lua +++ /dev/null @@ -1,205 +0,0 @@ ---------------------------------------------------------------------------------------- --- Copyright 2012 Rackspace (original), 2013 Thijs Schreijer (modifications) --- --- Licensed under the Apache License, Version 2.0 (the "License"); --- you may not use this file except in compliance with the License. --- You may obtain a copy of the License at --- --- http://www.apache.org/licenses/LICENSE-2.0 --- --- Unless required by applicable law or agreed to in writing, software --- distributed under the License is distributed on an "AS-IS" BASIS, --- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. --- See the License for the specific language governing permissions and --- limitations under the License. --- --- see http://www.ietf.org/rfc/rfc4122.txt --- --- Note that this is not a true version 4 (random) UUID. Since `os.time()` precision is only 1 second, it would be hard --- to guarantee spacial uniqueness when two hosts generate a uuid after being seeded during the same second. This --- is solved by using the node field from a version 1 UUID. It represents the mac address. --- --- 28-apr-2013 modified by Thijs Schreijer from the original [Rackspace code](https://github.com/kans/zirgo/blob/807250b1af6725bad4776c931c89a784c1e34db2/util/uuid.lua) as a generic Lua module. --- Regarding the above mention on `os.time()`; the modifications use the `socket.gettime()` function from LuaSocket --- if available and hence reduce that problem (provided LuaSocket has been loaded before uuid). --- --- **6-nov-2015 Please take note of this issue**; [https://github.com/Mashape/kong/issues/478](https://github.com/Mashape/kong/issues/478) --- It demonstrates the problem of using time as a random seed. Specifically when used from multiple processes. --- So make sure to seed only once, application wide. And to not have multiple processes do that --- simultaneously (like nginx does for example). - -local M = {} -local math = require('math') -local os = require('os') -local string = require('string') - -local bitsize = 32 -- bitsize assumed for Lua VM. See randomseed function below. -local lua_version = tonumber(_VERSION:match("%d%.*%d*")) -- grab Lua version used - -local MATRIX_AND = {{0,0},{0,1} } -local MATRIX_OR = {{0,1},{1,1}} -local HEXES = '0123456789abcdef' - -local math_floor = math.floor -local math_random = math.random -local math_abs = math.abs -local string_sub = string.sub -local to_number = tonumber -local assert = assert -local type = type - --- performs the bitwise operation specified by truth matrix on two numbers. -local function BITWISE(x, y, matrix) - local z = 0 - local pow = 1 - while x > 0 or y > 0 do - z = z + (matrix[x%2+1][y%2+1] * pow) - pow = pow * 2 - x = math_floor(x/2) - y = math_floor(y/2) - end - return z -end - -local function INT2HEX(x) - local s,base = '',16 - local d - while x > 0 do - d = x % base + 1 - x = math_floor(x/base) - s = string_sub(HEXES, d, d)..s - end - while #s < 2 do s = "0" .. s end - return s -end - ----------------------------------------------------------------------------- --- Creates a new uuid. Either provide a unique hex string, or make sure the --- random seed is properly set. The module table itself is a shortcut to this --- function, so `my_uuid = uuid.new()` equals `my_uuid = uuid()`. --- --- For proper use there are 3 options; --- --- 1. first require `luasocket`, then call `uuid.seed()`, and request a uuid using no --- parameter, eg. `my_uuid = uuid()` --- 2. use `uuid` without `luasocket`, set a random seed using `uuid.randomseed(some_good_seed)`, --- and request a uuid using no parameter, eg. `my_uuid = uuid()` --- 3. use `uuid` without `luasocket`, and request a uuid using an unique hex string, --- eg. `my_uuid = uuid(my_networkcard_macaddress)` --- --- @return a properly formatted uuid string --- @param hwaddr (optional) string containing a unique hex value (e.g.: `00:0c:29:69:41:c6`), to be used to compensate for the lesser `math_random()` function. Use a mac address for solid results. If omitted, a fully randomized uuid will be generated, but then you must ensure that the random seed is set properly! --- @usage --- local uuid = require("uuid") --- print("here's a new uuid: ",uuid()) -function M.new(hwaddr) - -- bytes are treated as 8bit unsigned bytes. - local bytes = { - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255), - math_random(0, 255) - } - - if hwaddr then - assert(type(hwaddr)=="string", "Expected hex string, got "..type(hwaddr)) - -- Cleanup provided string, assume mac address, so start from back and cleanup until we've got 12 characters - local i,str = #hwaddr, hwaddr - hwaddr = "" - while i>0 and #hwaddr<12 do - local c = str:sub(i,i):lower() - if HEXES:find(c, 1, true) then - -- valid HEX character, so append it - hwaddr = c..hwaddr - end - i = i - 1 - end - assert(#hwaddr == 12, "Provided string did not contain at least 12 hex characters, retrieved '"..hwaddr.."' from '"..str.."'") - - -- no split() in lua. :( - bytes[11] = to_number(hwaddr:sub(1, 2), 16) - bytes[12] = to_number(hwaddr:sub(3, 4), 16) - bytes[13] = to_number(hwaddr:sub(5, 6), 16) - bytes[14] = to_number(hwaddr:sub(7, 8), 16) - bytes[15] = to_number(hwaddr:sub(9, 10), 16) - bytes[16] = to_number(hwaddr:sub(11, 12), 16) - end - - -- set the version - bytes[7] = BITWISE(bytes[7], 0x0f, MATRIX_AND) - bytes[7] = BITWISE(bytes[7], 0x40, MATRIX_OR) - -- set the variant - bytes[9] = BITWISE(bytes[7], 0x3f, MATRIX_AND) - bytes[9] = BITWISE(bytes[7], 0x80, MATRIX_OR) - return INT2HEX(bytes[1])..INT2HEX(bytes[2])..INT2HEX(bytes[3])..INT2HEX(bytes[4]).."-".. - INT2HEX(bytes[5])..INT2HEX(bytes[6]).."-".. - INT2HEX(bytes[7])..INT2HEX(bytes[8]).."-".. - INT2HEX(bytes[9])..INT2HEX(bytes[10]).."-".. - INT2HEX(bytes[11])..INT2HEX(bytes[12])..INT2HEX(bytes[13])..INT2HEX(bytes[14])..INT2HEX(bytes[15])..INT2HEX(bytes[16]) -end - ----------------------------------------------------------------------------- --- Improved randomseed function. --- Lua 5.1 and 5.2 both truncate the seed given if it exceeds the integer --- range. If this happens, the seed will be 0 or 1 and all randomness will --- be gone (each application run will generate the same sequence of random --- numbers in that case). This improved version drops the most significant --- bits in those cases to get the seed within the proper range again. --- @param seed the random seed to set (integer from 0 - 2^32, negative values will be made positive) --- @return the (potentially modified) seed used --- @usage --- local socket = require("socket") -- gettime() has higher precision than os.time() --- local uuid = require("uuid") --- -- see also example at uuid.seed() --- uuid.randomseed(socket.gettime()*10000) --- print("here's a new uuid: ",uuid()) -function M.randomseed(seed) - seed = math_floor(math_abs(seed)) - if seed >= (2^bitsize) then - -- integer overflow, so reduce to prevent a bad seed - seed = seed - math_floor(seed / 2^bitsize) * (2^bitsize) - end - if lua_version < 5.2 then - -- 5.1 uses (incorrect) signed int - math.randomseed(seed - 2^(bitsize-1)) - else - -- 5.2 uses (correct) unsigned int - math.randomseed(seed) - end - return seed -end - ----------------------------------------------------------------------------- --- Seeds the random generator. --- It does so in 2 possible ways; --- --- 1. use `os.time()`: this only offers resolution to one second (used when --- LuaSocket hasn't been loaded yet --- 2. use luasocket `gettime()` function, but it only does so when LuaSocket --- has been required already. --- @usage --- local socket = require("socket") -- gettime() has higher precision than os.time() --- -- LuaSocket loaded, so below line does the same as the example from randomseed() --- uuid.seed() --- print("here's a new uuid: ",uuid()) -function M.seed() - if package.loaded["socket"] and package.loaded["socket"].gettime then - return M.randomseed(package.loaded["socket"].gettime()*10000) - else - return M.randomseed(os.time()) - end -end - -return setmetatable( M, { __call = function(self, hwaddr) return self.new(hwaddr) end} ) diff --git a/website/backend/app/main.lua b/website/backend/app/main.lua deleted file mode 100755 index 4285944..0000000 --- a/website/backend/app/main.lua +++ /dev/null @@ -1,6 +0,0 @@ -inspect = require("app.libs.inspect") -require("app.config.error_code") -require "app.libs.log_api" - -local app = require("app.server") -app:run() diff --git a/website/backend/app/middleware/README.md b/website/backend/app/middleware/README.md deleted file mode 100644 index 0dd3f92..0000000 --- a/website/backend/app/middleware/README.md +++ /dev/null @@ -1,19 +0,0 @@ - -### 自定义插件目录(define your own middleware) - - -You are recommended to define your own middlewares and keep them in one place to manage. - -建议用户将自定义插件存放在此目录下统一管理,然后在其他地方引用,插件的格式如下: - -``` -local middleware = function(params) - return function(req, res, next) - -- do something with req/res - next() - end -end - -return middleware -``` - diff --git a/website/backend/app/middleware/check_login.lua b/website/backend/app/middleware/check_login.lua deleted file mode 100755 index 529887b..0000000 --- a/website/backend/app/middleware/check_login.lua +++ /dev/null @@ -1,60 +0,0 @@ -local smatch = string.match -local sfind = string.find - -local function is_login(req) - local user - if req.session then - user = req.session.get("user") - if user and user.username and user.userid then - return true, user - end - end - return false, nil -end - -local function check_login(whitelist) - return function(req, res, next) - local requestPath = req.path - local in_white_list = false - if requestPath == "/" then - in_white_list = true - else - for i, v in ipairs(whitelist) do - local match, err = smatch(requestPath, v) - if match then - in_white_list = true - end - end - end - - local islogin, user= is_login(req) - - if in_white_list then - res.locals.login = islogin - res.locals.username = user and user.username - res.locals.userid = user and user.userid - res.locals.create_time = user and user.create_time - next() - else - if islogin then - res.locals.login = true - res.locals.username = user.username - res.locals.userid = user.userid - res.locals.create_time = user.create_time - next() - else - if sfind(req.headers["Accept"], "application/json") then - res:json({ - code = AUTH_ERROR.account_login, - message = system_error_msg(AUTH_ERROR.account_login), - }) - -- else - -- res:redirect("/api/login") - end - end - end - end -end - -return check_login - diff --git a/website/backend/app/middleware/inject_app_info.lua b/website/backend/app/middleware/inject_app_info.lua deleted file mode 100755 index 74c1457..0000000 --- a/website/backend/app/middleware/inject_app_info.lua +++ /dev/null @@ -1,11 +0,0 @@ ---- 中间件示例: 为每个请求注入一些通用的变量 -local lor = require("lor.index") -return function() - return function(req, res, next) - -- res.locals是一个table, 可以在这里注入一些“全局”变量 - -- 这个示例里注入app的名称和版本号, 在渲染页面时即可使用 - res.locals.app_name = "lor application" - res.locals.app_version = lor.version or "" - next() - end -end diff --git a/website/backend/app/middleware/uploader.lua b/website/backend/app/middleware/uploader.lua deleted file mode 100755 index 09bb0f6..0000000 --- a/website/backend/app/middleware/uploader.lua +++ /dev/null @@ -1,139 +0,0 @@ -local upload = require("resty.upload") -local uuid = require("app.libs.uuid") - -local sfind = string.find -local match = string.match -local ngx_var = ngx.var - - - -local function getextension(filename) - return filename:match(".+%.(%w+)$") -end - - -local function _multipart_formdata(config) - - local form, err = upload:new(config.chunk_size) - if not form then - ngx.log(ngx.ERR, "failed to new upload: ", err) - ngx.exit(500) - end - form:set_timeout(config.recieve_timeout) - - - local unique_name = uuid() - local success, msg = false, "" - local file, origin_filename, filename, path, extname, err - while true do - local typ, res, err = form:read() - - if not typ then - success = false - msg = "failed to read" - ngx.log(ngx.ERR, "failed to read: ", err) - return success, msg - end - - if typ == "header" then - if res[1] == "Content-Disposition" then - key = match(res[2], "name=\"(.-)\"") - origin_filename = match(res[2], "filename=\"(.-)\"") - elseif res[1] == "Content-Type" then - filetype = res[2] - end - - if origin_filename and filetype then - if not extname then - extname = getextension(origin_filename) - end - - if extname ~= "png" and extname ~= "jpg" and extname ~= "jpeg" and extname ~= "bmp" and extname ~= "gif" then - success = false - msg = "not allowed upload file type" - ngx.log(ngx.ERR, "not allowed upload file type:", origin_filename) - return success, msg - end - - filename = unique_name .. "." .. extname - path = config.dir.. "/" .. filename - - - file, err = io.open(path, "w+") - - if err then - success = false - msg = "open file error" - ngx.log(ngx.ERR, "open file error:", err) - return success, msg - end - end - - elseif typ == "body" then - if file then - file:write(res) - success = true - else - success = false - msg = "upload file error" - ngx.log(ngx.ERR, "upload file error, path:", path) - return success, msg - end - elseif typ == "part_end" then - file:close() - file = nil - elseif typ == "eof" then - break - else - -- do nothing - end - end - - return success, msg, origin_filename, extname, path, filename -end - - - -local function uploader(config) - return function(req, res, next) - - if ngx_var.request_method == "POST" then - local get_headers = ngx.req.get_headers() - local header = get_headers['Content-Type'] - if header then - local is_multipart = sfind(header, "multipart") - if is_multipart and is_multipart>0 then - config = config or {} - config.dir = config.dir or "/tmp" - config.chunk_size = config.chunk_size or 4096 - config.recieve_timeout = config.recieve_timeout or 20000 -- 20s - - local success, msg, origin_filename, extname, path, filename = _multipart_formdata(config) - if success then - req.file = req.file or {} - req.file.success = true - req.file.origin_filename = origin_filename - req.file.extname = extname - req.file.path = path - req.file.filename = filename - else - req.file = req.file or {} - req.file.success = false - req.file.msg = msg - end - next() - - else - next() - end - else - next() - end - else - next() - end - end -end - -return uploader - diff --git a/website/backend/app/model/user.lua b/website/backend/app/model/user.lua deleted file mode 100755 index ef40634..0000000 --- a/website/backend/app/model/user.lua +++ /dev/null @@ -1,72 +0,0 @@ -local DB = require("app.libs.db") -local db = DB:new() - -local user_model = {} - - -function user_model:new(username, password, avatar, rolelv) - return db:query("insert into user(username, password, avatar, role_lv) values(?,?,?,?)", - {username, password, avatar, rolelv}) -end - -function user_model:query(username, password) - local res, err = db:query("select * from user where username=? and password=?", {username, password}) - return res, err -end - --- function user_model:query_by_id(id) --- local result, err = db:query("select * from user where id=?", {tonumber(id)}) --- if not result or err or type(result) ~= "table" or #result ~=1 then --- return nil, err --- else --- return result[1], err --- end --- end - --- return user, err -function user_model:query_by_username(username) - local res, err = db:query("select * from user where username=? limit 1", {username}) - if not res or err or type(res) ~= "table" or #res ~=1 then - return nil, err or "error" - end - - return res[1], err -end - -function user_model:update_avatar(userid, avatar) - db:query("update user set avatar=? where id=?", {avatar, userid}) -end - -function user_model:update_pwd(userid, pwd) - local res, err = db:query("update user set password=? where id=?", {pwd, userid}) - if not res or err then - return false - else - return true - end - -end - -function user_model:update(userid, email, email_public, city, company, github, website, sign) - local res, err = db:query("update user set email=?, email_public=?, city=?, company=?, github=?, website=?, sign=? where id=?", - { email, email_public, city, company, github, website, sign, userid}) - - if not res or err then - return false - else - return true - end -end - -function user_model:get_total_count() - local res, err = db:query("select count(id) as c from user") - - if err or not res or #res~=1 or not res[1].c then - return 0 - else - return res[1].c - end -end - - -return user_model diff --git a/website/backend/app/router.lua b/website/backend/app/router.lua deleted file mode 100755 index c5fac6d..0000000 --- a/website/backend/app/router.lua +++ /dev/null @@ -1,7 +0,0 @@ --- 业务路由管理 -local apiRouter = require("app.routes.api") - -return function(app) - app:use("/api", apiRouter) -end - diff --git a/website/backend/app/routes/api.lua b/website/backend/app/routes/api.lua deleted file mode 100755 index 631f717..0000000 --- a/website/backend/app/routes/api.lua +++ /dev/null @@ -1,48 +0,0 @@ -local lor = require("lor.index") -local apiRouter = lor:Router() -- 生成一个group router对象 - - -local user_login = require("app.controller.user.login") -local user_signup = require("app.controller.user.signup") -local user_info = require("app.controller.user.user_info") - ---注册 -apiRouter:post("/signup", function(req, res, next) - local body = req.body - local username = body.username - local password = body.password - - local msg = user_signup(username, password) - return res:json(msg) -end) - ---登录 -apiRouter:post("/login", function(req, res, next) - local body = req.body - local username = body.username - local password = body.password - - local msg = user_login(req, username, password) - return res:json(msg) -end) - -apiRouter:get("/user", function(req, res, next) - local msg = user_info(req, res) - return res:json(msg) -end) - -apiRouter:get("/list", function(req, res, next) - local msg = user_info(req, res) - return res:json(msg) -end) - - -apiRouter:post("/logout", function(req, res, next) - res.locals.login = false - res.locals.username = "" - res.locals.userid = 0 - res.locals.create_time = "" - req.session.destroy() -end) - -return apiRouter \ No newline at end of file diff --git a/website/backend/app/server.lua b/website/backend/app/server.lua deleted file mode 100755 index 1cc565b..0000000 --- a/website/backend/app/server.lua +++ /dev/null @@ -1,90 +0,0 @@ -local string_find = string.find -local string_lower = string.lower - -local lor = require("lor.index") -local router = require("app.router") -local app = lor() - -local cors_header = require "cors_header" - -local config = require("app.config.config") -local whitelist = config.whitelist -local view_config = config.view_config -local upload_config = config.upload_config - --- 模板配置 -app:conf("view enable", true) -app:conf("view engine", view_config.engine) -app:conf("view ext", view_config.ext) -app:conf("views", view_config.views) - - --- session和cookie支持,如果不需要可注释以下配置 -local mw_cookie = require("lor.lib.middleware.cookie") -local mw_session = require("lor.lib.middleware.session") -local mw_check_login = require("app.middleware.check_login") --- local mw_uploader = require("app.middleware.uploader") --- 自定义中间件1: 注入一些全局变量供模板渲染使用 -local mw_inject_version = require("app.middleware.inject_app_info") - -app:use(mw_cookie()) -app:use(mw_session({ - session_key = "__rilladmin_app__", -- the key injected in cookie - session_aes_key = "aes_&%$#@(*&Gjjd563hdngds35781fhxgh", -- should set by yourself - timeout = 3600 -- default session timeout is 3600 seconds -})) - -app:use(mw_inject_version()) - --- intercepter: login or not -app:use(mw_check_login(whitelist)) - --- -- uploader --- app:use(mw_uploader({ --- dir = upload_config.dir --- })) - - ---自定义中间件2: 设置响应头 -app:use(function(req, res, next) - cors_header(res) - next() -end) - -router(app) -- 业务路由处理 - --- 错误处理插件,可根据需要定义多个 -app:erroruse(function(err, req, res, next) - -- ERROR("error: ", err) - - cors_header(res) - - local method = req.method and string_lower(req.method) - if method == "options" then - res:set_header("Access-Control-Max-Age", "1728000") - res:set_header("Content-Length", "0") - return - end - - if req:is_found() ~= true then - if string_find(req.headers["Accept"], "application/json") then - res:status(404):json({ - success = false, - msg = "404! sorry, not found." - }) - else - res:status(404):send("404! sorry, not found. " .. (req.path or "")) - end - else - if string_find(req.headers["Accept"], "application/json") then - res:status(500):json({ - success = false, - msg = "500! internal error, please check the log." - }) - else - res:status(500):send("internal error, please check the log.") - end - end -end) - -return app diff --git a/website/backend/app/static/README.md b/website/backend/app/static/README.md deleted file mode 100755 index 28889bf..0000000 --- a/website/backend/app/static/README.md +++ /dev/null @@ -1,11 +0,0 @@ - -### 静态文件目录(static files directory) - -nginx对应配置为 - -``` -location /static { - alias app/static; -} -``` - diff --git a/website/backend/app/views/.gitkeep b/website/backend/app/views/.gitkeep deleted file mode 100755 index e69de29..0000000 diff --git a/website/backend/conf/README.md b/website/backend/conf/README.md deleted file mode 100755 index e7f122c..0000000 --- a/website/backend/conf/README.md +++ /dev/null @@ -1,5 +0,0 @@ - -### nginx configuration directory -## -/usr/local/openresty/nginx/sbin/nginx -c /usr/local/openresty/nginx/conf/nginx.conf - diff --git a/website/backend/conf/mime.types b/website/backend/conf/mime.types deleted file mode 100644 index cd3d700..0000000 --- a/website/backend/conf/mime.types +++ /dev/null @@ -1,88 +0,0 @@ -types { - text/html html htm shtml; - text/css css; - text/xml xml; - image/gif gif; - image/jpeg jpeg jpg; - application/javascript js; - application/atom+xml atom; - application/rss+xml rss; - - text/mathml mml; - text/plain txt; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/x-component htc; - - image/png png; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/x-icon ico; - image/x-jng jng; - image/x-ms-bmp bmp; - image/svg+xml svg svgz; - image/webp webp; - - application/font-woff woff; - application/java-archive jar war ear; - application/json json; - application/mac-binhex40 hqx; - application/msword doc; - application/pdf pdf; - application/postscript ps eps ai; - application/rtf rtf; - application/vnd.apple.mpegurl m3u8; - application/vnd.ms-excel xls; - application/vnd.ms-fontobject eot; - application/vnd.ms-powerpoint ppt; - application/vnd.wap.wmlc wmlc; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/x-7z-compressed 7z; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xspf+xml xspf; - application/zip zip; - - application/octet-stream bin exe dll; - application/octet-stream deb; - application/octet-stream dmg; - application/octet-stream iso img; - application/octet-stream msi msp msm; - - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; - - audio/midi mid midi kar; - audio/mpeg mp3; - audio/ogg ogg; - audio/x-m4a m4a; - audio/x-realaudio ra; - - video/3gpp 3gpp 3gp; - video/mp2t ts; - video/mp4 mp4; - video/mpeg mpeg mpg; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-m4v m4v; - video/x-mng mng; - video/x-ms-asf asx asf; - video/x-ms-wmv wmv; - video/x-msvideo avi; -} diff --git a/website/backend/conf/nginx-dev.conf b/website/backend/conf/nginx-dev.conf deleted file mode 100755 index 780c25c..0000000 --- a/website/backend/conf/nginx-dev.conf +++ /dev/null @@ -1,98 +0,0 @@ - -pid tmp/nginx.pid; -worker_processes 4; -#nginx权限问题 https://github.com/smallnewer/bugs/issues/64 ps aux|grep nginx|grep -v grep -user root; - -events { - worker_connections 4096; -} - -http { - include ./mime.types; - - client_max_body_size 10m; #允许客户端请求的最大单文件字节数 - client_body_buffer_size 10m; #缓冲区代理缓冲用户端请求的最大字节数 - - sendfile on; - keepalive_timeout 65; - charset utf8; - - lua_package_path "./app/?.lua;./app/libs/?.lua;./?.lua;./lor/?.lua;./lor/lib/?.lua;;;;"; -# lua_package_path "./app/?.lua;./app/library/?.lua;./app/?/init.lua;./?.lua;/usr/local/lor/?.lua;/usr/local/lor/?/init.lua;;"; - lua_package_cpath "./app/librarys/?.so;/usr/local/lor/?.so;;"; - lua_code_cache on; # set on @production - #LUA_SHARED_DICT - - server { - listen 9517; - #server_name localhost; - - # Access log with buffer, or disable it completetely if unneeded - access_log logs/dev-www-access.log combined buffer=16k; - # Error log - error_log logs/dev-www-error.log; - - location /admin { - root ./www/; - - # try_files $uri $uri/ ; - index index.html index.htm; - } - } - - server { - listen 9518; - - # Access log with buffer, or disable it completetely if unneeded - access_log logs/dev-www-access.log combined buffer=16k; - # Error log - error_log logs/dev-www-error.log; - - location /api/profiler { - proxy_pass http://127.0.0.1:9527; - proxy_read_timeout 300s; - proxy_send_timeout 300s; - - proxy_set_header Host $host:$server_port; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; - } - - location /api/ { - proxy_pass http://127.0.0.1:9527; - } - } - - server { - listen 7777; - #server_name localhost; - set $template_root ''; - - # # 项目本身的静态文件 - # location /static/css { - # alias ./app/static/css; - # } - # location /static/img { - # alias ./app/static/img; - # } - # location /static/fonts { - # alias ./app/static/fonts; - # } - # location /static/js { - # alias ./app/static/js; - # } - - - # Access log with buffer, or disable it completetely if unneeded - access_log logs/dev-api-access.log combined buffer=16k; - # Error log - error_log logs/dev-api-error.log; - - # lor runtime - location / { - content_by_lua_file ./app/main.lua; - } - } -} \ No newline at end of file diff --git a/website/backend/lor/.gitignore b/website/backend/lor/.gitignore deleted file mode 100755 index fa3abaf..0000000 --- a/website/backend/lor/.gitignore +++ /dev/null @@ -1,12 +0,0 @@ -###test -local_install.sh -gen_rockspec.sh -test.sh -test.lua -snippets.lua -.idea -*.iml -*.rock -*.rockspec -lor-* -.DS_Store diff --git a/website/backend/lor/.luacheckrc b/website/backend/lor/.luacheckrc deleted file mode 100755 index d8bfebd..0000000 --- a/website/backend/lor/.luacheckrc +++ /dev/null @@ -1,4 +0,0 @@ -std = "ngx_lua" -globals = {"LOR_FRAMEWORK_DEBUG"} - -exclude_files = {"test/*", "resty", "bin"} diff --git a/website/backend/lor/.sublimelinterrc b/website/backend/lor/.sublimelinterrc deleted file mode 100755 index 0a0cc96..0000000 --- a/website/backend/lor/.sublimelinterrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "linters": { - "luacheck": { - "@disable": false, - "args": [], - "std": "ngx_lua", - "excludes": ["test/*", "resty", "bin", "*_spec.lua", "*.test.lua"], - "globals": ["LOR_FRAMEWORK_DEBUG"], - "ignore": [ - "channel" - ], - "limit": null, - "only": [] - } - } -} diff --git a/website/backend/lor/.travis.yml b/website/backend/lor/.travis.yml deleted file mode 100755 index c724fc6..0000000 --- a/website/backend/lor/.travis.yml +++ /dev/null @@ -1,42 +0,0 @@ -language: c - -sudo: false - -env: - global: - - LUAROCKS=2.2.2 - matrix: - # Lua 5.1 - - LUA=lua5.1 - # LuaJIT latest stable version (2.0.4) - - LUA=luajit - # Openresty + LuaJIT + mysql - - LUA=luajit SERVER=openresty - # - LUA=luajit2.0 # current head of 2.0 branch - # - LUA=luajit2.1 # current head of 2.1 branch - # Not supported - # - LUA=lua5.2 - # - LUA=lua5.3 - -branches: - - master - - v0.3.0 - - -before_install: - - source .travis/setenv_lua.sh - -install: - - luarocks install https://luarocks.org/manifests/olivine-labs/busted-2.0.rc12-1.rockspec - - luarocks install lrexlib-pcre 2.7.2-1 - - luarocks install luaposix - - luarocks install lua-cjson - #- luarocks make - -script: - - busted spec/* - -notifications: - email: - on_success: change - on_failure: always diff --git a/website/backend/lor/.travis/platform.sh b/website/backend/lor/.travis/platform.sh deleted file mode 100755 index 7259a7d..0000000 --- a/website/backend/lor/.travis/platform.sh +++ /dev/null @@ -1,15 +0,0 @@ -if [ -z "${PLATFORM:-}" ]; then - PLATFORM=$TRAVIS_OS_NAME; -fi - -if [ "$PLATFORM" == "osx" ]; then - PLATFORM="macosx"; -fi - -if [ -z "$PLATFORM" ]; then - if [ "$(uname)" == "Linux" ]; then - PLATFORM="linux"; - else - PLATFORM="macosx"; - fi; -fi diff --git a/website/backend/lor/.travis/setenv_lua.sh b/website/backend/lor/.travis/setenv_lua.sh deleted file mode 100755 index 942fa14..0000000 --- a/website/backend/lor/.travis/setenv_lua.sh +++ /dev/null @@ -1,9 +0,0 @@ -export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/luarocks/bin -export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/nginx/sbin -export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/bin -bash .travis/setup_lua.sh -if [ "$SERVER" == "openresty" ]; then - bash .travis/setup_servers.sh -fi - -eval `$HOME/.lua/luarocks path` diff --git a/website/backend/lor/.travis/setup_lua.sh b/website/backend/lor/.travis/setup_lua.sh deleted file mode 100755 index e434ddc..0000000 --- a/website/backend/lor/.travis/setup_lua.sh +++ /dev/null @@ -1,109 +0,0 @@ -#! /bin/bash - -# A script for setting up environment for travis-ci testing. -# Sets up Lua and Luarocks. -# LUA must be "lua5.1", "lua5.2" or "luajit". -# luajit2.0 - master v2.0 -# luajit2.1 - master v2.1 - -set -eufo pipefail - -LUAJIT_BASE="LuaJIT-2.0.4" - -source .travis/platform.sh - -LUA_HOME_DIR=$TRAVIS_BUILD_DIR/install/lua - -LR_HOME_DIR=$TRAVIS_BUILD_DIR/install/luarocks - -mkdir $HOME/.lua - -LUAJIT="no" - -if [ "$PLATFORM" == "macosx" ]; then - if [ "$LUA" == "luajit" ]; then - LUAJIT="yes"; - fi - if [ "$LUA" == "luajit2.0" ]; then - LUAJIT="yes"; - fi - if [ "$LUA" == "luajit2.1" ]; then - LUAJIT="yes"; - fi; -elif [ "$(expr substr $LUA 1 6)" == "luajit" ]; then - LUAJIT="yes"; -fi - -mkdir -p "$LUA_HOME_DIR" - -if [ "$LUAJIT" == "yes" ]; then - - git clone https://github.com/LuaJIT/LuaJIT $LUAJIT_BASE; - - cd $LUAJIT_BASE - - if [ "$LUA" == "luajit2.1" ]; then - git checkout v2.1; - # force the INSTALL_TNAME to be luajit - perl -i -pe 's/INSTALL_TNAME=.+/INSTALL_TNAME= luajit/' Makefile - else - git checkout v2.0.4; - fi - - make && make install PREFIX="$LUA_HOME_DIR" - - ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/luajit - ln -s $LUA_HOME_DIR/bin/luajit $HOME/.lua/lua; - -else - - if [ "$LUA" == "lua5.1" ]; then - curl http://www.lua.org/ftp/lua-5.1.5.tar.gz | tar xz - cd lua-5.1.5; - fi - - # Build Lua without backwards compatibility for testing - perl -i -pe 's/-DLUA_COMPAT_(ALL|5_2)//' src/Makefile - make $PLATFORM - make INSTALL_TOP="$LUA_HOME_DIR" install; - - ln -s $LUA_HOME_DIR/bin/lua $HOME/.lua/lua - ln -s $LUA_HOME_DIR/bin/luac $HOME/.lua/luac; - -fi - -cd $TRAVIS_BUILD_DIR - -lua -v - -LUAROCKS_BASE=luarocks-$LUAROCKS - -curl --location http://luarocks.org/releases/$LUAROCKS_BASE.tar.gz | tar xz - -cd $LUAROCKS_BASE - -if [ "$LUA" == "luajit" ]; then - ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; -elif [ "$LUA" == "luajit2.0" ]; then - ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.0" --prefix="$LR_HOME_DIR"; -elif [ "$LUA" == "luajit2.1" ]; then - ./configure --lua-suffix=jit --with-lua-include="$LUA_HOME_DIR/include/luajit-2.1" --prefix="$LR_HOME_DIR"; -else - ./configure --with-lua="$LUA_HOME_DIR" --prefix="$LR_HOME_DIR" -fi - -make build && make install - -ln -s $LR_HOME_DIR/bin/luarocks $HOME/.lua/luarocks - -cd $TRAVIS_BUILD_DIR - -luarocks --version - -rm -rf $LUAROCKS_BASE - -if [ "$LUAJIT" == "yes" ]; then - rm -rf $LUAJIT_BASE; -elif [ "$LUA" == "lua5.1" ]; then - rm -rf lua-5.1.5; -fi diff --git a/website/backend/lor/.travis/setup_servers.sh b/website/backend/lor/.travis/setup_servers.sh deleted file mode 100755 index 3b9612c..0000000 --- a/website/backend/lor/.travis/setup_servers.sh +++ /dev/null @@ -1,33 +0,0 @@ -#! /bin/bash - -# A script for setting up environment for travis-ci testing. -# Sets up openresty. -OPENRESTY_VERSION="1.9.3.1" -OPENRESTY_DIR=$TRAVIS_BUILD_DIR/install/openresty - -#if [ "$LUA" == "lua5.1" ]; then -# luarocks install LuaBitOp -#fi - -wget https://openresty.org/download/ngx_openresty-$OPENRESTY_VERSION.tar.gz -tar xzvf ngx_openresty-$OPENRESTY_VERSION.tar.gz -cd ngx_openresty-$OPENRESTY_VERSION/ - -./configure --prefix="$OPENRESTY_DIR" --with-luajit - -make -make install - -ln -s $OPENRESTY_DIR/bin/resty $HOME/.lua/resty -ln -s $OPENRESTY_DIR/nginx/sbin/nginx $HOME/.lua/nginx - -export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/nginx/sbin -export PATH=${PATH}:$HOME/.lua:$HOME/.local/bin:${TRAVIS_BUILD_DIR}/install/openresty/bin - -nginx -v -resty -V - -cd ../ -rm -rf ngx_openresty-$OPENRESTY_VERSION -cd $TRAVIS_BUILD_DIR - diff --git a/website/backend/lor/Changes.md b/website/backend/lor/Changes.md deleted file mode 100755 index 97fdd6f..0000000 --- a/website/backend/lor/Changes.md +++ /dev/null @@ -1,174 +0,0 @@ -### v0.3.4 2017.08.30 - -- 修复默认session插件的`session_aes_secret`长度问题 - - 此问题存在于OpenResty v1.11.2.5版本及可能之后的版本中 - - lua-resty-string v0.10开始AES salt必须是[8个字符](https://github.com/openresty/lua-resty-string/commit/69df3dcc2230364a54761a0d5a65327c6a4e256a) -- 使用内置的session插件时`session_aes_secret`不再是必须配置 - - 若不填则默认为`12345678` - - 若不足8个字符则以`0`补足 - - 若超过8个字符则只使用前8个 - -### v0.3.3 2017.08.05 - -- 使用严格的路由节点id策略,避免潜在冲突 - - -### v0.3.2 2017.06.10 - -- 关于内置session插件的更改 - - 修复session过期时间bug - - 移除lua-resty-session依赖 - - 内置session插件替换为基于cookie的简单实现 - - 接口仍然保持与之前版本兼容 - - 关于session处理,仍然建议根据具体业务需求和安全考量自行实现 -- 支持URI中含有字符'-' - -### v0.3.1 2017.04.16 - -- 支持路由中包含`~`字符(from [@XadillaX](https://github.com/XadillaX)) -- 支持组路由(group router)的多级路由写法 -- 支持组路由下直接挂载中间件(see [issues#40](https://github.com/sumory/lor/issues/40)) - -### v0.3.0 2017.02.11 - -此版本为性能优化和内部实现重构版本,API使用上保持与之前版本兼容,详细描述如下: - -**特性** - -- 中间件(middlewares)重构,支持任意级别、多种方式挂载中间件,这些中间件包括 - - 预处理中间件(use) - - 错误处理中间件(erroruse) - - 业务处理中间件(get/post/put/delete...) -- 提高路由性能 - - 路由匹配次数不再随路由数增多而正比例增长 - - 全面支持正则路由和通配符路由 -- use、get/put/delete/post等API优化,如支持数组参数、支持单独挂载中间件等改进 -- 路由匹配更加灵活: 优先匹配精确路由,其次再匹配正则路由或通配符路由 - -**Break Changes** - -与之前版本相比,break changes主要有以下几点(基本都是一些比较少用到的特性) - -- 路由执行顺序不再与路由定义顺序相关, 如错误路由不用必须定义在最下方 -- 如果一个请求最终匹配不到已定义的任何路由,则不会执行任何中间件代码(之前的版本会执行,这浪费了一些性能) - - -### v0.2.6 2016.11.26 - -- 升级内部集成的session中间件 - - lua-resty-session升级到2.13版本 - - 添加一个session过期参数timeout,默认为3600秒 - - 添加一个refresh_cookie参数,用于控制否在有新请求时刷新session和cookie过期时间,默认“是” -- 更新`lord new`项目模板 - - 缓存`app`对象,提高性能 - - 调整CRUD示例, 详细请参看脚手架代码中的app/routes/user.lua -- 删除默认响应头X-Powered-By - -### v0.2.4 2016.11.16 - -- 支持"application/json"类型请求 - - -### v0.2.2 2016.10.15 - -- 支持opm, 可通过`opm install sumory/lor`安装 - - 注意opm暂不支持命令安装, 所以这种方式无法安装`lord`命令 -- 若仍想使用`lord`命令,建议使用`sh install.sh`方式安装 - -### v0.1.6 2016.10.14 - -- `lord`工具改为使用resty-cli实现,不再依赖luajit - -### v0.1.5 2016.10.01 - -- Path URI支持"." -- 使用xpcall替换pcall以记录更多出错日志 -- 更新了测试用例 - -### v0.1.4 2016.07.30 - -- 删除一些无用代码和引用 -- 升级测试依赖库 -- 修改文档和注释 -- 修改一些小bug - -### v0.1.0 2016.03.15 - -- 增加一配置项,是否启用模板功能:app:conf("view enable", true), 默认为关闭 -- view.lua中ngx.var.template_root存在性判断 -- 增加docker支持 -- 命令`lord --path`变更为`lord path`,用于查看当前lor的安装路径 -- 官网文档更新[http://lor.sumory.com](http://lor.sumory.com) - -### v0.0.9 2016.03.02 - -- 使用install.sh安装lor时如果有指定安装目录,则在指定的目录后面拼上"lor",避免文件误删的问题 -- TODO: debug时列出整个路由表供参考 - -### v0.0.8 2016.02.26 - -- 支持multipart/form文件上传 -- 修复了一个group router被多次app:use时出现404的bug -- 支持Response:json(data, flag)方法传入第二个bool类型参数flag,指明序列化json时默认的空table是否编码为{} - - true 作为{}处理 - - false 作为[]处理 - - 不传入第二个参数则当作[]处理 - - -### v0.0.7 2016.02.02 - -- 统一代码风格 -- 优化部分代码,比如使用ngx.re代替string对应方法、尽量使用local等 -- Break API: req:isFound() -> req:is_found() -- Fix bug: 修复了在lua_code_cache on时的一些404问题 - - -### v0.0.6 2016.01.30 - -- 修改了lor的默认安装路径到/usr/local/lor -- 命令行工具`lord`生成的项目模板更改 - - 加入了nginx.conf配置,方便之后维护自定义的nginx配置 - - 加入start/stop/restart脚本,方便之后项目的灵活部署 -- 改善了路由pattern,支持path variable含有"-"字符 -- 增加了几个测试用例 -- 修复了上一个请求的path variable会污染之后请求的bug -- 完善了res:redirect API -- 修复了请求体为空时解析的bug -- 给lor对象添加了版本号 -- 添加了静态文件支持(通过在nginx.conf里配置) -- 编写了lor框架示例项目[lor-example](https://github.com/lorlabs/lor-example) - - -### v0.0.5 2016.01.28 - -- 完善了Documents和API文档,详见[lor官网](http://lor.sumory.com) -- `lor new`命令生成的项目模板增加了一个middleware目录,用于存放自定义插件 - - 该目录的命名和位置都是非强制的,用户可按需要将自定义的插件放在任何地方 -- 修改了lor new产生的项目模板,增加了几个基本API的使用方式 - - -### v0.0.4 2016.01.25 - -- 以默认插件的形式添加cookie支持(lua-resty-cookie) -- 以默认插件的形式添加session支持(lua-resty-session) - - -### v0.0.3 2016.01.23 - -- 修复上版本路由bug -- 添加模板支持(lua-resty-template) -- 完善了40余个常规测试用例 -- 完善了命令行工具`lord` -- 常规API使用方法添加到默认项目模板 - - -### v0.0.2 2016.01.21 - -- 完全重构v0.0.1路由 -- Sinatra风格路由 -- 主要API设计完成并实现 - - -### v0.0.1 2016.01.15 - -- 原型设计和实验 diff --git a/website/backend/lor/LICENSE b/website/backend/lor/LICENSE deleted file mode 100755 index 58c556a..0000000 --- a/website/backend/lor/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 - 2017 sumory.wu - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/website/backend/lor/Makefile b/website/backend/lor/Makefile deleted file mode 100644 index 068a826..0000000 --- a/website/backend/lor/Makefile +++ /dev/null @@ -1,49 +0,0 @@ -TO_INSTALL = lib/* resty spec bin -LOR_HOME ?= /usr/local -LORD_BIN ?= /usr/local/bin - -.PHONY: test install - -test: - busted spec/* - -install_lor: - @mkdir -p ${LOR_HOME}/lor - @mkdir -p ${LOR_HOME} - @rm -rf ${LOR_HOME}/lor/* - - @echo "install lor runtime files to "${LOR_HOME}/lor - - @for item in $(TO_INSTALL) ; do \ - cp -a $$item ${LOR_HOME}/lor/; \ - done; - - @echo "lor runtime files installed." - - -install_lord: install_lor - @mkdir -p ${LORD_BIN} - @echo "install lord cli to "${LORD_BIN}"/" - - @echo "#!/usr/bin/env resty" > tmp_lor_bin - @echo "package.path=\""${LOR_HOME}/lor"/?.lua;;\"" >> tmp_lor_bin - @echo "if arg[1] and arg[1] == \"path\" then" >> tmp_lor_bin - @echo " print(\"${LOR_HOME}/lor\")" >> tmp_lor_bin - @echo " return" >> tmp_lor_bin - @echo "end" >> tmp_lor_bin - @echo "require('bin.lord')(arg)" >> tmp_lor_bin - - @mv tmp_lor_bin ${LORD_BIN}/lord - @chmod +x ${LORD_BIN}/lord - - @echo "lord cli installed." - -install: install_lord - @echo "lor framework installed successfully." - -version: - @lord -v - -help: - @lord -h - diff --git a/website/backend/lor/README.md b/website/backend/lor/README.md deleted file mode 100755 index 012f286..0000000 --- a/website/backend/lor/README.md +++ /dev/null @@ -1,143 +0,0 @@ -# Lor - -[![https://travis-ci.org/sumory/lor.svg?branch=master](https://travis-ci.org/sumory/lor.svg?branch=master)](https://travis-ci.org/sumory/lor) [![GitHub release](https://img.shields.io/github/release/sumory/lor.svg)](https://github.com/sumory/lor/releases/latest) [![license](https://img.shields.io/github/license/sumory/lor.svg)](https://github.com/sumory/lor/blob/master/LICENSE) - -中文 English - -A fast and minimalist web framework based on [OpenResty](http://openresty.org). - - - -```lua -local lor = require("lor.index") -local app = lor() - -app:get("/", function(req, res, next) - res:send("hello world!") -end) - -app:run() -``` - -## Examples - -- [lor-example](https://github.com/lorlabs/lor-example) -- [openresty-china](https://github.com/sumory/openresty-china) - - -## Installation - -1) shell - -```shell -git clone https://github.com/sumory/lor -cd lor -make install -``` - -`LOR_HOME` and `LORD_BIN` are supported by `Makefile`, so the following command could be used to customize installation: - -``` -make install LOR_HOME=/path/to/lor LORD_BIN=/path/to/lord -``` - -2) opm - -`opm install` is supported from v0.2.2. - -``` -opm install sumory/lor -``` - -`lord` cli is not supported with this installation. - -3) homebrew - -you can use [homebrew-lor](https://github.com/syhily/homebrew-lor) on Mac OSX. - -``` -$ brew tap syhily/lor -$ brew install lor -``` - - -## Features - -- Routing like [Sinatra](http://www.sinatrarb.com/) which is a famous Ruby framework -- Similar API with [Express](http://expressjs.com), good experience for Node.js or Javascript developers -- Middleware support -- Group router support -- Session/Cookie/Views supported and could be redefined with `Middleware` -- Easy to build HTTP APIs, web site, or single page applications - - -## Docs & Community - -- [Website and Documentation](http://lor.sumory.com). -- [Github Organization](https://github.com/lorlabs) for Official Middleware & Modules. - - -## Quick Start - -A quick way to get started with lor is to utilize the executable cli tool `lord` to generate an scaffold application. - -`lord` is installed with `lor` framework. it looks like: - -```bash -$ lord -h -lor ${version}, a Lua web framework based on OpenResty. - -Usage: lord COMMAND [OPTIONS] - -Commands: - new [name] Create a new application - start Starts the server - stop Stops the server - restart Restart the server - version Show version of lor - help Show help tips -``` - -Create app: - -``` -$ lord new lor_demo -``` - -Start server: - -``` -$ cd lor_demo && lord start -``` - -Visit [http://localhost:8888](http://localhost:8888). - - -## Tests - -Install [busted](http://olivinelabs.com/busted/), then run test - -``` -busted spec/* -``` - -## Homebrew - -[https://github.com/syhily/homebrew-lor](https://github.com/syhily/homebrew-lor) maintained by [@syhily](https://github.com/syhily) - -## Contributors - -- [@ms2008](https://github.com/ms2008) -- [@wanghaisheng](https://github.com/wanghaisheng) -- [@lihuibin](https://github.com/lihuibin) -- [@syhily](https://github.com/syhily) -- [@vinsonzou](https://github.com/vinsonzou) -- [@lhmwzy](https://github.com/lhmwzy) -- [@hanxi](https://github.com/hanxi) -- [@诗兄](https://github.com/269724033) -- [@hetz](https://github.com/hetz) -- [@XadillaX](https://github.com/XadillaX) - -## License - -[MIT](./LICENSE) diff --git a/website/backend/lor/README_zh.md b/website/backend/lor/README_zh.md deleted file mode 100755 index 6b33e07..0000000 --- a/website/backend/lor/README_zh.md +++ /dev/null @@ -1,168 +0,0 @@ -# Lor - -[![https://travis-ci.org/sumory/lor.svg?branch=master](https://travis-ci.org/sumory/lor.svg?branch=master)](https://travis-ci.org/sumory/lor) [![GitHub release](https://img.shields.io/github/release/sumory/lor.svg)](https://github.com/sumory/lor/releases/latest) [![license](https://img.shields.io/github/license/sumory/lor.svg)](https://github.com/sumory/lor/blob/master/LICENSE) - -中文 English - -**Lor**是一个运行在[OpenResty](http://openresty.org)上的基于Lua编写的Web框架. - -- 路由采用[Sinatra](http://www.sinatrarb.com/)风格,结构清晰,易于编码和维护. -- API借鉴了[Express](http://expressjs.com)的思路和设计,Node.js跨界开发者可以很快上手. -- 支持多种路由,路由可分组,路由匹配支持正则模式. -- 支持middleware机制,可在任意路由上挂载中间件. -- 可作为HTTP API Server,也可用于构建传统的Web应用. - - -### 文档 - -[http://lor.sumory.com](http://lor.sumory.com) - -#### 示例项目 - -- 简单示例项目[lor-example](https://github.com/lorlabs/lor-example) -- 全站示例项目[openresty-china](https://github.com/sumory/openresty-china) - - -### 快速开始 - -**特别注意:** 在使用lor之前请首先确保OpenResty已安装,并将`nginx`/`resty`命令配置到环境变量中。即在命令行直接输入`nginx -v`、`resty -v`能正确执行。 - -一个简单示例(更复杂的示例或项目模板请使用`lord`命令生成): - -```lua -local lor = require("lor.index") -local app = lor() - -app:get("/", function(req, res, next) - res:send("hello world!") -end) - --- 路由示例: 匹配/query/123?foo=bar -app:get("/query/:id", function(req, res, next) - local foo = req.query.foo - local path_id = req.params.id - res:json({ - foo = foo, - id = path_id - }) -end) - --- 错误处理插件,可根据需要定义多个 -app:erroruse(function(err, req, res, next) - -- err是错误对象 - ngx.log(ngx.ERR, err) - if req:is_found() ~= true then - return res:status(404):send("sorry, not found.") - end - res:status(500):send("server error") -end) - -app:run() -``` - -### 安装 - - -#### 1)使用脚本安装(推荐) - -使用Makefile安装lor框架: - -```shell -git clone https://github.com/sumory/lor -cd lor -make install -``` - -默认`lor`的运行时lua文件会被安装到`/usr/local/lor`下, 命令行工具`lord`被安装在`/usr/local/bin`下。 - -如果希望自定义安装目录, 可参考如下命令自定义路径: - -```shell -make install LOR_HOME=/path/to/lor LORD_BIN=/path/to/lord -``` - -执行**默认安装**后, lor的命令行工具`lord`就被安装在了`/usr/local/bin`下, 通过`which lord`查看: - -``` -$ which lord -/usr/local/bin/lord -``` - -`lor`的运行时包安装在了指定目录下, 可通过`lord path`命令查看。 - - -#### 2)使用opm安装 - -`opm`是OpenResty即将推出的官方包管理器,从v0.2.2开始lor支持通过opm安装: - -``` -opm install sumory/lor -``` - -注意: 目前opm不支持安装命令行工具,所以此种方式安装后不能使用`lord`命令。 - - -#### 3)使用homebrew安装 - -除使用以上方式安装外, Mac用户还可使用homebrew来安装lor, 该方式由[@syhily](https://github.com/syhily)提供, 更详尽的使用方法请参见[这里](https://github.com/syhily/homebrew-lor)。 - -``` -$ brew tap syhily/lor -$ brew install lor -``` - -至此, `lor`框架已经安装完毕,接下来使用`lord`命令行工具快速开始一个项目骨架. - - -### 使用 - -``` -$ lord -h -lor ${version}, a Lua web framework based on OpenResty. - -Usage: lord COMMAND [OPTIONS] - -Commands: - new [name] Create a new application - start Starts the server - stop Stops the server - restart Restart the server - version Show version of lor - help Show help tips -``` - -执行`lord new lor_demo`,则会生成一个名为lor_demo的示例项目,然后执行: - -``` -cd lor_demo -lord start -``` - -之后访问[http://localhost:8888/](http://localhost:8888/), 即可。 - -更多使用方法,请参考[use cases](./spec/cases)测试用例。 - -### Homebrew - -[https://github.com/syhily/homebrew-lor](https://github.com/syhily/homebrew-lor)由[@syhily](https://github.com/syhily)维护。 - -### 贡献者 - -- [@ms2008](https://github.com/ms2008) -- [@wanghaisheng](https://github.com/wanghaisheng) -- [@lihuibin](https://github.com/lihuibin) -- [@syhily](https://github.com/syhily) -- [@vinsonzou](https://github.com/vinsonzou) -- [@lhmwzy](https://github.com/lhmwzy) -- [@hanxi](https://github.com/hanxi) -- [@诗兄](https://github.com/269724033) -- [@hetz](https://github.com/hetz) -- [@XadillaX](https://github.com/XadillaX) - -### 讨论交流 - -有一个QQ群用于在线讨论: 522410959 - -### License - -[MIT](./LICENSE) diff --git a/website/backend/lor/bin/lord.lua b/website/backend/lor/bin/lord.lua deleted file mode 100755 index 7c7f2e4..0000000 --- a/website/backend/lor/bin/lord.lua +++ /dev/null @@ -1,47 +0,0 @@ -package.path = './?.lua;' .. package.path - -local generator = require("bin.scaffold.generator") -local lor = require("bin.scaffold.launcher") -local version = require("lor.version") - -local usages = [[lor v]] .. version .. [[, a Lua web framework based on OpenResty. - -Usage: lord COMMAND [OPTIONS] - -Commands: - new [name] Create a new application - start Start running app server - stop Stop the server - restart Restart the server - version Show version of lor - help Show help tips - path Show install path -]] - -local function exec(args) - local arg = table.remove(args, 1) - - -- parse commands and options - if arg == 'new' and args[1] then - generator.new(args[1]) -- generate example code - elseif arg == 'start' then - lor.start() -- start application - elseif arg == 'stop' then - lor.stop() -- stop application - elseif arg == 'restart' then - lor.stop() - lor.start() - elseif arg == 'reload' then - lor.reload() - elseif arg == 'help' or arg == '-h' then - print(usages) - elseif arg == 'version' or arg == '-v' then - print(version) -- show lor framework version - elseif arg == nil then - print(usages) - else - print("[lord] unsupported commands or options, `lord -h` to check usages.") - end -end - -return exec diff --git a/website/backend/lor/bin/scaffold/generator.lua b/website/backend/lor/bin/scaffold/generator.lua deleted file mode 100755 index 4e9fe87..0000000 --- a/website/backend/lor/bin/scaffold/generator.lua +++ /dev/null @@ -1,628 +0,0 @@ -local sgmatch = string.gmatch -local utils = require 'bin.scaffold.utils' - -local gitignore = [[ -# lor -client_body_temp -fastcgi_temp -logs -proxy_temp -tmp -uwsgi_temp - -# Compiled Lua sources -luac.out - -# luarocks build files -*.src.rock -*.zip -*.tar.gz - -# Object files -*.o -*.os -*.ko -*.obj -*.elf - -# Precompiled Headers -*.gch -*.pch - -# Libraries -*.lib -*.a -*.la -*.lo -*.def -*.exp - -# Shared objects (inc. Windows DLLs) -*.dll -*.so -*.so.* -*.dylib - -# Executables -*.exe -*.out -*.app -*.i*86 -*.x86_64 -*.hex -]] - -local mime_types = [[ -types { - text/html html htm shtml; - text/css css; - text/xml xml; - image/gif gif; - image/jpeg jpeg jpg; - application/javascript js; - application/atom+xml atom; - application/rss+xml rss; - - text/mathml mml; - text/plain txt; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/x-component htc; - - image/png png; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/x-icon ico; - image/x-jng jng; - image/x-ms-bmp bmp; - image/svg+xml svg svgz; - image/webp webp; - - application/font-woff woff; - application/java-archive jar war ear; - application/json json; - application/mac-binhex40 hqx; - application/msword doc; - application/pdf pdf; - application/postscript ps eps ai; - application/rtf rtf; - application/vnd.apple.mpegurl m3u8; - application/vnd.ms-excel xls; - application/vnd.ms-fontobject eot; - application/vnd.ms-powerpoint ppt; - application/vnd.wap.wmlc wmlc; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/x-7z-compressed 7z; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-perl pl pm; - application/x-pilot prc pdb; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert der pem crt; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xspf+xml xspf; - application/zip zip; - - application/octet-stream bin exe dll; - application/octet-stream deb; - application/octet-stream dmg; - application/octet-stream iso img; - application/octet-stream msi msp msm; - - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; - - audio/midi mid midi kar; - audio/mpeg mp3; - audio/ogg ogg; - audio/x-m4a m4a; - audio/x-realaudio ra; - - video/3gpp 3gpp 3gp; - video/mp2t ts; - video/mp4 mp4; - video/mpeg mpeg mpg; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-m4v m4v; - video/x-mng mng; - video/x-ms-asf asx asf; - video/x-ms-wmv wmv; - video/x-msvideo avi; -} -]] - - -local index_view_tpl = [[ - - - - - - - - -]] - -local user_info_view_tpl = [[ - - - - - -
- {{desc}}
- {{id}} - {{name}} -
- - -]] - -local main_tpl = [[ -local app = require("app.server") -app:run() -]] - -local server_tpl = [[ -local string_find = string.find -local lor = require("lor.index") -local router = require("app.router") -local app = lor() - --- 模板配置 -app:conf("view enable", true) -app:conf("view engine", "tmpl") -app:conf("view ext", "html") -app:conf("view layout", "") -app:conf("views", "./app/views") - --- session和cookie支持,如果不需要可注释以下配置 -local mw_cookie = require("lor.lib.middleware.cookie") -local mw_session = require("lor.lib.middleware.session") -app:use(mw_cookie()) -app:use(mw_session({ - session_key = "__app__", -- the key injected in cookie - session_aes_key = "aes_key_for_session", -- should set by yourself - timeout = 3600 -- default session timeout is 3600 seconds -})) - --- 自定义中间件1: 注入一些全局变量供模板渲染使用 -local mw_inject_version = require("app.middleware.inject_app_info") -app:use(mw_inject_version()) - --- 自定义中间件2: 设置响应头 -app:use(function(req, res, next) - res:set_header("X-Powered-By", "Lor framework") - next() -end) - -router(app) -- 业务路由处理 - --- 错误处理插件,可根据需要定义多个 -app:erroruse(function(err, req, res, next) - ngx.log(ngx.ERR, err) - - if req:is_found() ~= true then - if string_find(req.headers["Accept"], "application/json") then - res:status(404):json({ - success = false, - msg = "404! sorry, not found." - }) - else - res:status(404):send("404! sorry, not found. " .. (req.path or "")) - end - else - if string_find(req.headers["Accept"], "application/json") then - res:status(500):json({ - success = false, - msg = "500! internal error, please check the log." - }) - else - res:status(500):send("internal error, please check the log.") - end - end -end) - -return app -]] - - -local router_tpl = [[ --- 业务路由管理 -local userRouter = require("app.routes.user") - -return function(app) - - -- simple router: hello world! - app:get("/hello", function(req, res, next) - res:send("hi! welcome to lor framework.") - end) - - -- simple router: render html, visit "/" or "/?name=foo&desc=bar - app:get("/", function(req, res, next) - local data = { - name = req.query.name or "lor", - desc = req.query.desc or 'a framework of lua based on OpenResty' - } - res:render("index", data) - end) - - -- group router: 对以`/user`开始的请求做过滤处理 - app:use("/user", userRouter()) -end - -]] - - -local user_router_tpl = [[ -local lor = require("lor.index") -local userRouter = lor:Router() -- 生成一个group router对象 - --- 按id查找用户 --- e.g. /query/123 -userRouter:get("/query/:id", function(req, res, next) - local query_id = tonumber(req.params.id) -- 从req.params取参数 - - if not query_id then - return res:render("user/info", { - desc = "Error to find user, path variable `id` should be a number. e.g. /user/query/123" - }) - end - - -- 渲染页面 - res:render("user/info", { - id = query_id, - name = "user" .. query_id, - desc = "User Information" - }) -end) - --- 删除用户 --- e.g. /delete?id=123 -userRouter:delete("/delete", function(req, res, next) - local id = req.query.id -- 从req.query取参数 - if not id then - return res:html("

Error: query param id is required.

") - end - - -- 返回html - res:html("succeed to delete user
user id is:" .. id .. "") -end) - --- 修改用户 --- e.g. /put/123?name=sumory -userRouter:put("/put/:id", function(req, res, next) - local id = req.params.id -- 从req.params取参数 - local name = req.query.name -- 从req.query取参数 - - if not id or not name then - return res:send("error params: id and name are required.") - end - - -- 返回文本格式的响应结果 - res:send("succeed to modify user[" .. id .. "] with new name:" .. name) -end) - --- 创建用户 -userRouter:post("/post", function(req, res, next) - local content_type = req.headers['Content-Type'] - - -- 如果请求类型为form表单或json请求体 - if string.find(content_type, "application/x-www-form-urlencoded",1, true) or - string.find(content_type, "application/json",1, true) then - local id = req.body.id -- 从请求体取参数 - local name = req.body.name -- 从请求体取参数 - - if not id or not name then - return res:json({ - success = false, - msg = "error params: id and name are required." - }) - end - - res:json({-- 返回json格式的响应体 - success = true, - data = { - id = id, - name = name, - desc = "succeed to create new user" .. id - } - }) - else -- 不支持其他请求体 - res:status(500):send("not supported request Content-Type[" .. content_type .. "]") - end -end) - -return userRouter -]] - - - -local middleware_tpl = [[ - -### 自定义插件目录(define your own middleware) - - -You are recommended to define your own middlewares and keep them in one place to manage. - -建议用户将自定义插件存放在此目录下统一管理,然后在其他地方引用,插件的格式如下: - -``` -local middleware = function(params) - return function(req, res, next) - -- do something with req/res - next() - end -end - -return middleware -``` - -]] - - -local middleware_example_tpl = [[ ---- 中间件示例: 为每个请求注入一些通用的变量 -local lor = require("lor.index") -return function() - return function(req, res, next) - -- res.locals是一个table, 可以在这里注入一些“全局”变量 - -- 这个示例里注入app的名称和版本号, 在渲染页面时即可使用 - res.locals.app_name = "lor application" - res.locals.app_version = lor.version or "" - next() - end -end -]] - - -local static_tpl = [[ - -### 静态文件目录(static files directory) - -nginx对应配置为 - -``` -location /static { - alias app/static; -} -``` - -]] - -local ngx_conf_directory = [[ - -### nginx configuration directory - -]] - - -local ngx_config = require 'bin.scaffold.nginx.config' -local ngx_conf_template = require 'bin.scaffold.nginx.conf_template' -local function nginx_conf_content() - -- read nginx.conf file - local nginx_conf_template = ngx_conf_template.get_ngx_conf_template() - - -- append notice - nginx_conf_template = [[ -#generated by `lor framework` - ]] .. nginx_conf_template - - local match = {} - local tmp = 1 - for v in sgmatch(nginx_conf_template , '{{(.-)}}') do - match[tmp] = v - tmp = tmp + 1 - end - - for _, directive in ipairs(match) do - if ngx_config[directive] ~= nil then - nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', ngx_config[directive]) - else - nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', '#' .. directive) - end - end - - return nginx_conf_template -end -local ngx_conf_tpl = nginx_conf_content() - - -local start_sh = [[ -#!/bin/sh - -##################################################################### -# usage: -# sh start.sh -- start application @dev -# sh start.sh ${env} -- start application @${env} - -# examples: -# sh start.sh prod -- use conf/nginx-prod.conf to start OpenResty -# sh start.sh -- use conf/nginx-dev.conf to start OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "start lor application with profile: "${PROFILE} -nginx -p `pwd`/ -c conf/nginx-${PROFILE}.conf -]] - - -local stop_sh = [[ -#!/bin/sh - -##################################################################### -# usage: -# sh stop.sh -- stop application @dev -# sh stop.sh ${env} -- stop application @${env} - -# examples: -# sh stop.sh prod -- use conf/nginx-prod.conf to stop OpenResty -# sh stop.sh -- use conf/nginx-dev.conf to stop OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "stop lor application with profile: "${PROFILE} -nginx -s stop -p `pwd`/ -c conf/nginx-${PROFILE}.conf -]] - -local reload_sh = [[ -#!/bin/sh - -##################################################################### -# usage: -# sh reload.sh -- reload application @dev -# sh reload.sh ${env} -- reload application @${env} - -# examples: -# sh reload.sh prod -- use conf/nginx-prod.conf to reload OpenResty -# sh reload.sh -- use conf/nginx-dev.conf to reload OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "reload lor application with profile: "${PROFILE} -nginx -s reload -p `pwd`/ -c conf/nginx-${PROFILE}.conf -]] - - - -local Generator = {} - -Generator.files = { - ['.gitignore'] = gitignore, - ['app/main.lua'] = main_tpl, - ['app/server.lua'] = server_tpl, - ['app/router.lua'] = router_tpl, - ['app/routes/user.lua'] = user_router_tpl, - ['app/views/index.html'] = index_view_tpl, - ['app/views/user/info.html'] = user_info_view_tpl, - ['app/middleware/README.md'] = middleware_tpl, - ['app/middleware/inject_app_info.lua'] = middleware_example_tpl, - ['app/static/README.md'] = static_tpl, -- static files directory,e.g. js/css/img - ['conf/README.md'] = ngx_conf_directory, -- nginx config directory - ['conf/nginx-dev.conf'] = ngx_conf_tpl, -- nginx config file - ['conf/mime.types'] = mime_types, -- nginx mime - ['start.sh'] = start_sh, - ['stop.sh'] = stop_sh, - ['reload.sh'] = reload_sh -} - -function Generator.new(name) - print('Creating app: ' .. name .. '...') - Generator.create_files(name) -end - -function Generator.create_files(parent) - for file_path, file_content in pairs(Generator.files) do - - local full_file_path = parent .. '/' .. file_path - local full_file_dirname = utils.dirname(full_file_path) - os.execute('mkdir -p ' .. full_file_dirname .. ' > /dev/null') - - local fw = io.open(full_file_path, 'w') - fw:write(file_content) - fw:close() - print(' created file ' .. full_file_path) - end -end - -return Generator - - - - diff --git a/website/backend/lor/bin/scaffold/launcher.lua b/website/backend/lor/bin/scaffold/launcher.lua deleted file mode 100755 index da227c7..0000000 --- a/website/backend/lor/bin/scaffold/launcher.lua +++ /dev/null @@ -1,101 +0,0 @@ -local sgmatch = string.gmatch -local ogetenv = os.getenv - -local ngx_handle = require 'bin.scaffold.nginx.handle' -local ngx_config = require 'bin.scaffold.nginx.config' -local ngx_conf_template = require 'bin.scaffold.nginx.conf_template' - - -local Lor = {} - -function Lor.nginx_conf_content() - -- read nginx.conf file - local nginx_conf_template = ngx_conf_template.get_ngx_conf_template() - - -- append notice - nginx_conf_template = [[ -#generated by `lor framework` - ]] .. nginx_conf_template - - local match = {} - local tmp = 1 - for v in sgmatch(nginx_conf_template , '{{(.-)}}') do - match[tmp] = v - tmp = tmp + 1 - end - - for _, directive in ipairs(match) do - if ngx_config[directive] ~= nil then - nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', ngx_config[directive]) - else - nginx_conf_template = string.gsub(nginx_conf_template, '{{' .. directive .. '}}', '#' .. directive) - end - end - - return nginx_conf_template -end - -function new_handler() - local necessary_dirs ={ -- runtime nginx conf/pid/logs dir - tmp = 'tmp', - logs = 'logs' - } - local env = ogetenv("LOR_ENV") or 'dev' - return ngx_handle.new( - necessary_dirs, - Lor.nginx_conf_content(), - "conf/nginx-" .. env .. ".conf" - ) -end - -function Lor.start() - local env = ogetenv("LOR_ENV") or 'dev' - - local ok, handler = pcall(function() return new_handler() end) - if ok == false then - print("ERROR:Cannot initialize handler: " .. handler) - return - end - - local result = handler:start(env) - if result == 0 or result == true or result == "true" then - if env ~= 'test' then - print("app in " .. env .. " was succesfully started on port " .. ngx_config.PORT) - end - else - print("ERROR: Could not start app on port " .. ngx_config.PORT) - end -end - - -function Lor.stop() - local env = ogetenv("LOR_ENV") or 'dev' - - local handler = new_handler() - local result = handler:stop(env) - - if env ~= 'test' then - if result == 0 or result == true or result == "true" then - print("app in " .. env .. " was succesfully stopped.") - else - print("ERROR: Could not stop app (are you sure it is running?).") - end - end -end - -function Lor.reload() - local env = ogetenv("LOR_ENV") or 'dev' - - local handler = new_handler() - local result = handler:reload(env) - - if env ~= 'test' then - if result == 0 or result == true or result == "true" then - print("app in " .. env .. " was succesfully reloaded.") - else - print("ERROR: Could not reloaded app.") - end - end -end - -return Lor diff --git a/website/backend/lor/bin/scaffold/nginx/conf_template.lua b/website/backend/lor/bin/scaffold/nginx/conf_template.lua deleted file mode 100755 index eb27ce6..0000000 --- a/website/backend/lor/bin/scaffold/nginx/conf_template.lua +++ /dev/null @@ -1,47 +0,0 @@ -local _M = {} - -function _M:get_ngx_conf_template() - return [[ -# user www www; -pid tmp/{{LOR_ENV}}-nginx.pid; - -# This number should be at maxium the number of CPU on the server -worker_processes 4; - -events { - # Number of connections per worker - worker_connections 4096; -} - -http { - sendfile on; - include ./mime.types; - - {{LUA_PACKAGE_PATH}} - lua_code_cache on; - - server { - # List port - listen {{PORT}}; - - # Access log - access_log logs/{{LOR_ENV}}-access.log; - - # Error log - error_log logs/{{LOR_ENV}}-error.log; - - # this variable is for view render(lua-resty-template) - set $template_root ''; - - location /static { - alias {{STATIC_FILE_DIRECTORY}}; #app/static; - } - - # lor runtime - {{CONTENT_BY_LUA_FILE}} - } -} - ]] -end - -return _M diff --git a/website/backend/lor/bin/scaffold/nginx/config.lua b/website/backend/lor/bin/scaffold/nginx/config.lua deleted file mode 100755 index 187669c..0000000 --- a/website/backend/lor/bin/scaffold/nginx/config.lua +++ /dev/null @@ -1,69 +0,0 @@ -local pairs = pairs -local ogetenv = os.getenv -local utils = require 'bin.scaffold.utils' -local app_run_env = ogetenv("LOR_ENV") or 'dev' - -local lor_ngx_conf = {} -lor_ngx_conf.common = { -- directives - LOR_ENV = app_run_env, - -- INIT_BY_LUA_FILE = './app/nginx/init.lua', - -- LUA_PACKAGE_PATH = '', - -- LUA_PACKAGE_CPATH = '', - CONTENT_BY_LUA_FILE = './app/main.lua', - STATIC_FILE_DIRECTORY = './app/static' -} - -lor_ngx_conf.env = {} -lor_ngx_conf.env.dev = { - LUA_CODE_CACHE = false, - PORT = 8888 -} - -lor_ngx_conf.env.test = { - LUA_CODE_CACHE = true, - PORT = 9999 -} - -lor_ngx_conf.env.prod = { - LUA_CODE_CACHE = true, - PORT = 80 -} - -local function getNgxConf(conf_arr) - if conf_arr['common'] ~= nil then - local common_conf = conf_arr['common'] - local env_conf = conf_arr['env'][app_run_env] - for directive, info in pairs(common_conf) do - env_conf[directive] = info - end - return env_conf - elseif conf_arr['env'] ~= nil then - return conf_arr['env'][app_run_env] - end - return {} -end - -local function buildConf() - local sys_ngx_conf = getNgxConf(lor_ngx_conf) - return sys_ngx_conf -end - - -local ngx_directive_handle = require('bin.scaffold.nginx.directive'):new(app_run_env) -local ngx_directives = ngx_directive_handle:directiveSets() -local ngx_run_conf = buildConf() - -local LorNgxConf = {} -for directive, func in pairs(ngx_directives) do - if type(func) == 'function' then - local func_rs = func(ngx_directive_handle, ngx_run_conf[directive]) - if func_rs ~= false then - LorNgxConf[directive] = func_rs - end - else - LorNgxConf[directive] = ngx_run_conf[directive] - end -end - -return LorNgxConf - diff --git a/website/backend/lor/bin/scaffold/nginx/directive.lua b/website/backend/lor/bin/scaffold/nginx/directive.lua deleted file mode 100755 index 919b01e..0000000 --- a/website/backend/lor/bin/scaffold/nginx/directive.lua +++ /dev/null @@ -1,205 +0,0 @@ --- most code is from https://github.com/idevz/vanilla/blob/master/vanilla/sys/nginx/directive.lua - -package.path = './app/?.lua;' .. package.path -package.cpath = './app/library/?.so;' .. package.cpath - - -local Directive = {} - -function Directive:new(env) - local run_env = 'prod' - if env ~= nil then run_env = env end - local instance = { - run_env = run_env, - directiveSets = self.directiveSets - } - setmetatable(instance, Directive) - return instance -end - -function Directive:luaPackagePath(lua_path) - local path = package.path - if lua_path ~= nil then path = lua_path .. path end - local res = [[lua_package_path "]] .. path .. [[;;";]] - return res -end - -function Directive:luaPackageCpath(lua_cpath) - local path = package.cpath - if lua_cpath ~= nil then path = lua_cpath .. path end - local res = [[lua_package_cpath "]] .. path .. [[;;";]] - return res -end - -function Directive:codeCache(bool_var) - if bool_var == true then bool_var = 'on' else bool_var = 'off' end - local res = [[lua_code_cache ]] .. bool_var.. [[;]] - return res -end - -function Directive:luaSharedDict( lua_lib ) - local ok, sh_dict_conf_or_error = pcall(function() return require(lua_lib) end) - if ok == false then - return false - end - local res = '' - if sh_dict_conf_or_error ~= nil then - for name,size in pairs(sh_dict_conf_or_error) do - res = res .. [[lua_shared_dict ]] .. name .. ' ' .. size .. ';' - end - end - return res -end - -function Directive:initByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[init_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:initByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[init_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:initWorkerByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[init_worker_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:initWorkerByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[init_worker_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:setByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[set_by_lua require(']] .. lua_lib .. [[');]] - return res -end - -function Directive:setByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[set_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:rewriteByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[rewrite_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:rewriteByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[rewrite_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:accessByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[access_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:accessByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[access_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:contentByLua(lua_lib) - if lua_lib == nil then return '' end - -- local res = [[content_by_lua require(']] .. lua_lib .. [['):run();]] - local res = [[location / { - content_by_lua require(']] .. lua_lib .. [['):run(); - }]] - return res -end - -function Directive:contentByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[location / { - content_by_lua_file ]] .. lua_file .. [[; - }]] - return res -end - -function Directive:headerFilterByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[header_filter_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:headerFilterByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[header_filter_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:bodyFilterByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[body_filter_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:bodyFilterByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[body_filter_by_lua_file ]] .. lua_file .. [[;]] - return res -end - -function Directive:logByLua(lua_lib) - if lua_lib == nil then return '' end - local res = [[log_by_lua require(']] .. lua_lib .. [['):run();]] - return res -end - -function Directive:logByLuaFile(lua_file) - if lua_file == nil then return '' end - local res = [[log_by_lua_file ]] .. lua_file .. [[;]] - return res -end - - -function Directive:staticFileDirectory(static_file_directory) - if static_file_directory == nil then return '' end - return static_file_directory -end - - -function Directive:directiveSets() - return { - ['LOR_ENV'] = self.run_env, - ['PORT'] = 80, - ['NGX_PATH'] = '', - ['LUA_PACKAGE_PATH'] = Directive.luaPackagePath, - ['LUA_PACKAGE_CPATH'] = Directive.luaPackageCpath, - ['LUA_CODE_CACHE'] = Directive.codeCache, - ['LUA_SHARED_DICT'] = Directive.luaSharedDict, - ['INIT_BY_LUA'] = Directive.initByLua, - ['INIT_BY_LUA_FILE'] = Directive.initByLuaFile, - ['INIT_WORKER_BY_LUA'] = Directive.initWorkerByLua, - ['INIT_WORKER_BY_LUA_FILE'] = Directive.initWorkerByLuaFile, - ['SET_BY_LUA'] = Directive.setByLua, - ['SET_BY_LUA_FILE'] = Directive.setByLuaFile, - ['REWRITE_BY_LUA'] = Directive.rewriteByLua, - ['REWRITE_BY_LUA_FILE'] = Directive.rewriteByLuaFile, - ['ACCESS_BY_LUA'] = Directive.accessByLua, - ['ACCESS_BY_LUA_FILE'] = Directive.accessByLuaFile, - ['CONTENT_BY_LUA'] = Directive.contentByLua, - ['CONTENT_BY_LUA_FILE'] = Directive.contentByLuaFile, - ['HEADER_FILTER_BY_LUA'] = Directive.headerFilterByLua, - ['HEADER_FILTER_BY_LUA_FILE'] = Directive.headerFilterByLuaFile, - ['BODY_FILTER_BY_LUA'] = Directive.bodyFilterByLua, - ['BODY_FILTER_BY_LUA_FILE'] = Directive.bodyFilterByLuaFile, - ['LOG_BY_LUA'] = Directive.logByLua, - ['LOG_BY_LUA_FILE'] = Directive.logByLuaFile, - ['STATIC_FILE_DIRECTORY'] = Directive.staticFileDirectory - } -end - -return Directive \ No newline at end of file diff --git a/website/backend/lor/bin/scaffold/nginx/handle.lua b/website/backend/lor/bin/scaffold/nginx/handle.lua deleted file mode 100755 index 861f7fa..0000000 --- a/website/backend/lor/bin/scaffold/nginx/handle.lua +++ /dev/null @@ -1,76 +0,0 @@ --- most code is from https://github.com/ostinelli/gin/blob/master/gin/cli/base_launcher.lua -local function create_dirs(necessary_dirs) - for _, dir in pairs(necessary_dirs) do - os.execute("mkdir -p " .. dir .. " > /dev/null") - end -end - -local function create_nginx_conf(nginx_conf_file_path, nginx_conf_content) - local fw = io.open(nginx_conf_file_path, "w") - fw:write(nginx_conf_content) - fw:close() -end - -local function remove_nginx_conf(nginx_conf_file_path) - os.remove(nginx_conf_file_path) -end - -local function nginx_command(env, nginx_conf_file_path, nginx_signal) - local env_cmd = "" - - if env ~= nil then env_cmd = "-g \"env LOR_ENV=" .. env .. ";\"" end - local cmd = "nginx " .. nginx_signal .. " " .. env_cmd .. " -p `pwd`/ -c " .. nginx_conf_file_path - print("execute: " .. cmd) - return os.execute(cmd) -end - -local function start_nginx(env, nginx_conf_file_path) - return nginx_command(env, nginx_conf_file_path, '') -end - -local function stop_nginx(env, nginx_conf_file_path) - return nginx_command(env, nginx_conf_file_path, '-s stop') -end - -local function reload_nginx(env, nginx_conf_file_path) - return nginx_command(env, nginx_conf_file_path, '-s reload') -end - - -local NginxHandle = {} -NginxHandle.__index = NginxHandle - -function NginxHandle.new(necessary_dirs, nginx_conf_content, nginx_conf_file_path) - local instance = { - nginx_conf_content = nginx_conf_content, - nginx_conf_file_path = nginx_conf_file_path, - necessary_dirs = necessary_dirs - } - setmetatable(instance, NginxHandle) - return instance -end - -function NginxHandle:start(env) - create_dirs(self.necessary_dirs) - -- create_nginx_conf(self.nginx_conf_file_path, self.nginx_conf_content) - - return start_nginx(env, self.nginx_conf_file_path) -end - -function NginxHandle:stop(env) - local result = stop_nginx(env, self.nginx_conf_file_path) - -- remove_nginx_conf(self.nginx_conf_file_path) - - return result -end - -function NginxHandle:reload(env) - -- remove_nginx_conf(self.nginx_conf_file_path) - create_dirs(self.necessary_dirs) - -- create_nginx_conf(self.nginx_conf_file_path, self.nginx_conf_content) - - return reload_nginx(env, self.nginx_conf_file_path) -end - - -return NginxHandle diff --git a/website/backend/lor/bin/scaffold/utils.lua b/website/backend/lor/bin/scaffold/utils.lua deleted file mode 100755 index 3752a2d..0000000 --- a/website/backend/lor/bin/scaffold/utils.lua +++ /dev/null @@ -1,45 +0,0 @@ -local pcall = pcall -local require = require -local iopen = io.open -local smatch = string.match - -local Utils = {} - --- read file -function Utils.read_file(file_path) - local f = iopen(file_path, "rb") - local content = f:read("*a") - f:close() - return content -end - - -local function require_module(module_name) - return require(module_name) -end - - --- try to require -function Utils.try_require(module_name, default) - local ok, module_or_err = pcall(require_module, module_name) - - if ok == true then return module_or_err end - - if ok == false and smatch(module_or_err, "'" .. module_name .. "' not found") then - return default - else - error(module_or_err) - end -end - - -function Utils.dirname(str) - if str:match(".-/.-") then - local name = string.gsub(str, "(.*/)(.*)", "%1") - return name - else - return '' - end -end - -return Utils \ No newline at end of file diff --git a/website/backend/lor/dist.ini b/website/backend/lor/dist.ini deleted file mode 100755 index 394003e..0000000 --- a/website/backend/lor/dist.ini +++ /dev/null @@ -1,10 +0,0 @@ -name = lor -abstract = A fast and minimalist web framework based on OpenResty. -version = 0.3.3 -author = Sumory Wu (@sumory) -is_original = yes -license = mit -repo_link = https://github.com/sumory/lor -main_module = lib/lor/index.lua -exclude_files = .travis, docker, docs, .travis.yml -requires = bungle/lua-resty-template >= 1.9, p0pr0ck5/lua-resty-cookie >= 0.01 diff --git a/website/backend/lor/lib/lor/index.lua b/website/backend/lor/lib/lor/index.lua deleted file mode 100755 index 2f13e50..0000000 --- a/website/backend/lor/lib/lor/index.lua +++ /dev/null @@ -1,27 +0,0 @@ -local type = type - -local version = require("lor.version") -local Group = require("lor.lib.router.group") -local Router = require("lor.lib.router.router") -local Request = require("lor.lib.request") -local Response = require("lor.lib.response") -local Application = require("lor.lib.application") -local Wrap = require("lor.lib.wrap") - -LOR_FRAMEWORK_DEBUG = false - -local createApplication = function(options) - if options and options.debug and type(options.debug) == 'boolean' then - LOR_FRAMEWORK_DEBUG = options.debug - end - - local app = Application:new() - app:init(options) - - return app -end - -local lor = Wrap:new(createApplication, Router, Group, Request, Response) -lor.version = version - -return lor diff --git a/website/backend/lor/lib/lor/lib/application.lua b/website/backend/lor/lib/lor/lib/application.lua deleted file mode 100755 index 8611153..0000000 --- a/website/backend/lor/lib/lor/lib/application.lua +++ /dev/null @@ -1,181 +0,0 @@ -local pairs = pairs -local type = type -local xpcall = xpcall -local setmetatable = setmetatable - -local Router = require("lor.lib.router.router") -local Request = require("lor.lib.request") -local Response = require("lor.lib.response") -local View = require("lor.lib.view") -local supported_http_methods = require("lor.lib.methods") - -local router_conf = { - strict_route = true, - ignore_case = true, - max_uri_segments = true, - max_fallback_depth = true -} - -local App = {} - -function App:new() - local instance = {} - instance.cache = {} - instance.settings = {} - instance.router = Router:new() - - setmetatable(instance, { - __index = self, - __call = self.handle - }) - - instance:init_method() - return instance -end - -function App:run(final_handler) - local request = Request:new() - local response = Response:new() - - local enable_view = self:getconf("view enable") - if enable_view then - local view_config = { - view_enable = enable_view, - view_engine = self:getconf("view engine"), -- view engine: resty-template or others... - view_ext = self:getconf("view ext"), -- defautl is "html" - view_layout = self:getconf("view layout"), -- defautl is "" - views = self:getconf("views") -- template files directory - } - - local view = View:new(view_config) - response.view = view - end - - self:handle(request, response, final_handler) -end - -function App:init(options) - self:default_configuration(options) -end - -function App:default_configuration(options) - options = options or {} - - -- view and template configuration - if options["view enable"] ~= nil and options["view enable"] == true then - self:conf("view enable", true) - else - self:conf("view enable", false) - end - self:conf("view engine", options["view engine"] or "tmpl") - self:conf("view ext", options["view ext"] or "html") - self:conf("view layout", options["view layout"] or "") - self:conf("views", options["views"] or "./app/views/") - - self.locals = {} - self.locals.settings = self.setttings -end - --- dispatch `req, res` into the pipeline. -function App:handle(req, res, callback) - local router = self.router - local done = callback or function(err) - if err then - if ngx then ngx.log(ngx.ERR, err) end - res:status(500):send("internal error! please check log.") - end - end - - if not router then - return done() - end - - local err_msg - local ok, e = xpcall(function() - router:handle(req, res, done) - end, function(msg) - err_msg = msg - end) - - if not ok then - done(err_msg) - end -end - -function App:use(path, fn) - self:inner_use(3, path, fn) -end - --- just a mirror for `erroruse` -function App:erruse(path, fn) - self:erroruse(path, fn) -end - -function App:erroruse(path, fn) - self:inner_use(4, path, fn) -end - --- should be private -function App:inner_use(fn_args_length, path, fn) - local router = self.router - - if path and fn and type(path) == "string" then - router:use(path, fn, fn_args_length) - elseif path and not fn then - fn = path - path = nil - router:use(path, fn, fn_args_length) - else - error("error usage for `middleware`") - end - - return self -end - -function App:init_method() - for http_method, _ in pairs(supported_http_methods) do - self[http_method] = function(_self, path, ...) -- funcs... - _self.router:app_route(http_method, path, ...) - return _self - end - end -end - -function App:all(path, ...) - for http_method, _ in pairs(supported_http_methods) do - self.router:app_route(http_method, path, ...) - end - - return self -end - -function App:conf(setting, val) - self.settings[setting] = val - - if router_conf[setting] == true then - self.router:conf(setting, val) - end - - return self -end - -function App:getconf(setting) - return self.settings[setting] -end - -function App:enable(setting) - self.settings[setting] = true - return self -end - -function App:disable(setting) - self.settings[setting] = false - return self -end - ---- only for dev -function App:gen_graph() - return self.router.trie:gen_graph() -end - -return App diff --git a/website/backend/lor/lib/lor/lib/debug.lua b/website/backend/lor/lib/lor/lib/debug.lua deleted file mode 100755 index 77ce51d..0000000 --- a/website/backend/lor/lib/lor/lib/debug.lua +++ /dev/null @@ -1,25 +0,0 @@ -local pcall = pcall -local type = type -local pairs = pairs - - -local function debug(...) - if not LOR_FRAMEWORK_DEBUG then - return - end - - local info = { ... } - if info and type(info[1]) == 'function' then - pcall(function() info[1]() end) - elseif info and type(info[1]) == 'table' then - for i, v in pairs(info[1]) do - print(i, v) - end - elseif ... ~= nil then - print(...) - else - print("debug not works...") - end -end - -return debug diff --git a/website/backend/lor/lib/lor/lib/holder.lua b/website/backend/lor/lib/lor/lib/holder.lua deleted file mode 100644 index 2e6d608..0000000 --- a/website/backend/lor/lib/lor/lib/holder.lua +++ /dev/null @@ -1,48 +0,0 @@ -local utils = require("lor.lib.utils.utils") -local ActionHolder = {} - -function ActionHolder:new(func, node, action_type) - local instance = { - id = "action-" .. utils.random(), - node = node, - action_type = action_type, - func = func, - } - - setmetatable(instance, { - __index = self, - __call = self.func - }) - return instance -end - - -local NodeHolder = {} - -function NodeHolder:new() - local instance = { - key = "", - val = nil, -- Node - } - setmetatable(instance, { __index = self }) - return instance -end - -local Matched = {} - -function Matched:new() - local instance = { - node = nil, - params = {}, - pipeline = {}, - } - setmetatable(instance, { __index = self }) - return instance -end - - -return { - ActionHolder = ActionHolder, - NodeHolder = NodeHolder, - Matched = Matched -} diff --git a/website/backend/lor/lib/lor/lib/methods.lua b/website/backend/lor/lib/lor/lib/methods.lua deleted file mode 100755 index b79c5ae..0000000 --- a/website/backend/lor/lib/lor/lib/methods.lua +++ /dev/null @@ -1,15 +0,0 @@ --- get and post methods is guaranteed, the others is still in process --- but all these methods shoule work at most cases by default -local supported_http_methods = { - get = true, -- work well - post = true, -- work well - head = true, -- no test - options = true, -- no test - put = true, -- work well - patch = true, -- no test - delete = true, -- work well - trace = true, -- no test - all = true -- todo: -} - -return supported_http_methods \ No newline at end of file diff --git a/website/backend/lor/lib/lor/lib/middleware/cookie.lua b/website/backend/lor/lib/lor/lib/middleware/cookie.lua deleted file mode 100755 index 183807e..0000000 --- a/website/backend/lor/lib/lor/lib/middleware/cookie.lua +++ /dev/null @@ -1,91 +0,0 @@ -local ck = require("resty.cookie") - --- Mind: --- base on 'lua-resty-cookie', https://github.com/cloudflare/lua-resty-cookie --- this is the default `cookie` middleware --- you're recommended to define your own `cookie` middleware. - --- usage example: --- app:get("/user", function(req, res, next) --- local ok, err = req.cookie.set({ --- key = "qq", --- value = '4==||==hello zhang==||==123456', --- path = "/", --- domain = "new.cn", --- secure = false, --设置后浏览器只有访问https才会把cookie带过来,否则浏览器请求时不带cookie参数 --- httponly = true, --设置后js 无法读取 --- --expires = ngx.cookie_time(os.time() + 3600), --- max_age = 3600, --用秒来设置cookie的生存期。 --- samesite = "Strict", --或者 Lax 指a域名下收到的cookie 不能通过b域名的表单带过来 --- extension = "a4334aebaece" --- }) --- end) - -local cookie_middleware = function(cookieConfig) - return function(req, res, next) - local COOKIE, err = ck:new() - - if not COOKIE then - req.cookie = {} -- all cookies - res._cookie = nil - else - req.cookie = { - set = function(...) - local _cookie = COOKIE - if not _cookie then - return ngx.log(ngx.ERR, "response#none _cookie found to write") - end - - local p = ... - if type(p) == "table" then - local ok, err = _cookie:set(p) - if not ok then - return ngx.log(ngx.ERR, err) - end - else - local params = { ... } - local ok, err = _cookie:set({ - key = params[1], - value = params[2] or "", - }) - if not ok then - return ngx.log(ngx.ERR, err) - end - end - end, - - get = function (name) - local _cookie = COOKIE - local field, err = _cookie:get(name) - - if not field then - return nil - else - return field - end - end, - - get_all = function () - local _cookie = COOKIE - local fields, err = _cookie:get_all() - - local t = {} - if not fields then - return nil - else - for k, v in pairs(fields) do - if k and v then - t[k] = v - end - end - return t - end - end - } - end - - next() - end -end - -return cookie_middleware diff --git a/website/backend/lor/lib/lor/lib/middleware/init.lua b/website/backend/lor/lib/lor/lib/middleware/init.lua deleted file mode 100755 index ec546d5..0000000 --- a/website/backend/lor/lib/lor/lib/middleware/init.lua +++ /dev/null @@ -1,9 +0,0 @@ -local init_middleware = function(req, res, next) - req.res = res - req.next = next - res.req = req - res.locals = res.locals or {} - next() -end - -return init_middleware diff --git a/website/backend/lor/lib/lor/lib/middleware/session.lua b/website/backend/lor/lib/lor/lib/middleware/session.lua deleted file mode 100755 index 0a7cc31..0000000 --- a/website/backend/lor/lib/lor/lib/middleware/session.lua +++ /dev/null @@ -1,184 +0,0 @@ -local type, xpcall = type, xpcall -local traceback = debug.traceback -local string_sub = string.sub -local string_len = string.len -local http_time = ngx.http_time -local ngx_time = ngx.time -local ck = require("resty.cookie") -local utils = require("lor.lib.utils.utils") -local aes = require("lor.lib.utils.aes") -local base64 = require("lor.lib.utils.base64") - - -local function decode_data(field, aes_key, ase_secret) - if not field or field == "" then return {} end - local payload = base64.decode(field) - local data = {} - local cipher = aes.new() - local decrypt_str = cipher:decrypt(payload, aes_key, ase_secret) - local decode_obj = utils.json_decode(decrypt_str) - return decode_obj or data -end - -local function encode_data(obj, aes_key, ase_secret) - local default = "{}" - local str = utils.json_encode(obj) or default - local cipher = aes.new() - local encrypt_str = cipher:encrypt(str, aes_key, ase_secret) - local encode_encrypt_str = base64.encode(encrypt_str) - return encode_encrypt_str -end - -local function parse_session(field, aes_key, ase_secret) - if not field then return end - return decode_data(field, aes_key, ase_secret) -end - ---- no much secure & performance consideration ---- TODO: optimization & security issues -local session_middleware = function(config) - config = config or {} - config.session_key = config.session_key or "_app_" - if config.refresh_cookie ~= false then - config.refresh_cookie = true - end - if not config.timeout or type(config.timeout) ~= "number" then - config.timeout = 3600 -- default session timeout is 3600 seconds - end - - - local err_tip = "session_aes_key should be set for session middleware" - -- backward compatibility for lor < v0.3.2 - config.session_aes_key = config.session_aes_key or "custom_session_aes_key" - if not config.session_aes_key then - ngx.log(ngx.ERR, err_tip) - end - - local session_key = config.session_key - local session_aes_key = config.session_aes_key - local refresh_cookie = config.refresh_cookie - local timeout = config.timeout - - -- session_aes_secret must be 8 charactors to respect lua-resty-string v0.10+ - local session_aes_secret = config.session_aes_secret or config.secret or "12345678" - if string_len(session_aes_secret) < 8 then - for i=1,8-string_len(session_aes_secret),1 do - session_aes_secret = session_aes_secret .. "0" - end - end - session_aes_secret = string_sub(session_aes_secret, 1, 8) - - ngx.log(ngx.INFO, "session middleware initialized") - return function(req, res, next) - if not session_aes_key then - return next(err_tip) - end - - local cookie, err = ck:new() - if not cookie then - ngx.log(ngx.ERR, "cookie is nil:", err) - end - - local current_session - local session_data, err = cookie:get(session_key) - if err then - ngx.log(ngx.ERR, "cannot get session_data:", err) - else - if session_data then - current_session = parse_session(session_data, session_aes_key, session_aes_secret) - end - end - current_session = current_session or {} - - req.session = { - set = function(...) - local p = ... - if type(p) == "table" then - for i, v in pairs(p) do - current_session[i] = v - end - else - local params = { ... } - if type(params[2]) == "table" then -- set("k", {1, 2, 3}) - current_session[params[1]] = params[2] - else -- set("k", "123") - current_session[params[1]] = params[2] or "" - end - end - - local value = encode_data(current_session, session_aes_key, session_aes_secret) - local expires = http_time(ngx_time() + timeout) - local max_age = timeout - local ok, err = cookie:set({ - key = session_key, - value = value or "", - expires = expires, - max_age = max_age, - path = "/" - }) - - ngx.log(ngx.INFO, "session.set: ", value) - - if err or not ok then - return ngx.log(ngx.ERR, "session.set error:", err) - end - end, - - refresh = function() - if session_data and session_data ~= "" then - local expires = http_time(ngx_time() + timeout) - local max_age = timeout - local ok, err = cookie:set({ - key = session_key, - value = session_data or "", - expires = expires, - max_age = max_age, - path = "/" - }) - if err or not ok then - return ngx.log(ngx.ERR, "session.refresh error:", err) - end - end - end, - - get = function(key) - return current_session[key] - end, - - destroy = function() - local expires = "Thu, 01 Jan 1970 00:00:01 GMT" - local max_age = 0 - local ok, err = cookie:set({ - key = session_key, - value = "", - expires = expires, - max_age = max_age, - path = "/" - }) - if err or not ok then - ngx.log(ngx.ERR, "session.destroy error:", err) - return false - end - - return true - end - } - - if refresh_cookie then - local e, ok - ok = xpcall(function() - req.session.refresh() - end, function() - e = traceback() - end) - - if not ok then - ngx.log(ngx.ERR, "refresh cookie error:", e) - end - end - - next() - end -end - -return session_middleware diff --git a/website/backend/lor/lib/lor/lib/node.lua b/website/backend/lor/lib/lor/lib/node.lua deleted file mode 100644 index efff5ff..0000000 --- a/website/backend/lor/lib/lor/lib/node.lua +++ /dev/null @@ -1,265 +0,0 @@ -local setmetatable = setmetatable -local type = type -local next = next -local ipairs = ipairs -local table_insert = table.insert -local string_lower = string.lower -local string_format = string.format - -local utils = require("lor.lib.utils.utils") -local supported_http_methods = require("lor.lib.methods") -local ActionHolder = require("lor.lib.holder").ActionHolder -local handler_error_tip = "handler must be `function` that matches `function(req, res, next) ... end`" -local middlware_error_tip = "middlware must be `function` that matches `function(req, res, next) ... end`" -local error_middlware_error_tip = "error middlware must be `function` that matches `function(err, req, res, next) ... end`" -local node_count = 0 - -local function gen_node_id() - local prefix = "node-" - local worker_part = "dw" - if ngx and ngx.worker then - worker_part = ngx.worker.id() - end - node_count = node_count + 1 -- simply count for lua vm level - local unique_part = node_count - local random_part = utils.random() - node_id = prefix .. worker_part .. "-" .. unique_part .. "-" .. random_part - return node_id -end - -local function check_method(method) - if not method then return false end - - method = string_lower(method) - if not supported_http_methods[method] then - return false - end - - return true -end - -local Node = {} - -function Node:new(root) - local is_root = false - if root == true then - is_root = true - end - - local instance = { - id = gen_node_id(), - is_root = is_root, - name = "", - allow = "", - pattern = "", - endpoint = false, - parent = nil, - colon_parent = nil, - children = {}, - colon_child= nil, - handlers = {}, - middlewares = {}, - error_middlewares = {}, - regex = nil - } - setmetatable(instance, { - __index = self, - __tostring = function(s) - local ok, result = pcall(function() - return string_format("name: %s", s.id) - end) - if ok then - return result - else - return "node.tostring() error" - end - end - }) - return instance -end - -function Node:find_child(key) - --print("find_child: ", self.id, self.name, self.children) - for _, c in ipairs(self.children) do - if key == c.key then - return c.val - end - end - return nil -end - -function Node:find_handler(method) - method = string_lower(method) - if not self.handlers or not self.handlers[method] or #self.handlers[method] == 0 then - return false - end - - return true -end - -function Node:use(...) - local middlewares = {...} - if not next(middlewares) then - error("middleware should not be nil or empty") - end - - local empty = true - for _, h in ipairs(middlewares) do - if type(h) == "function" then - local action = ActionHolder:new(h, self, "middleware") - table_insert(self.middlewares, action) - empty = false - elseif type(h) == "table" then - for _, hh in ipairs(h) do - if type(hh) == "function" then - local action = ActionHolder:new(hh, self, "middleware") - table_insert(self.middlewares, action) - empty = false - else - error(middlware_error_tip) - end - end - else - error(middlware_error_tip) - end - end - - if empty then - error("middleware should not be empty") - end - - return self -end - -function Node:error_use(...) - local middlewares = {...} - if not next(middlewares) then - error("error middleware should not be nil or empty") - end - - local empty = true - for _, h in ipairs(middlewares) do - if type(h) == "function" then - local action = ActionHolder:new(h, self, "error_middleware") - table_insert(self.error_middlewares, action) - empty = false - elseif type(h) == "table" then - for _, hh in ipairs(h) do - if type(hh) == "function" then - local action = ActionHolder:new(hh, self, "error_middleware") - table_insert(self.error_middlewares, action) - empty = false - else - error(error_middlware_error_tip) - end - end - else - error(error_middlware_error_tip) - end - end - - if empty then - error("error middleware should not be empty") - end - - return self -end - -function Node:handle(method, ...) - method = string_lower(method) - if not check_method(method) then - error("error method: ", method or "nil") - end - - if self:find_handler(method) then - error("[" .. self.pattern .. "] " .. method .. " handler exists yet!") - end - - if not self.handlers[method] then - self.handlers[method] = {} - end - - local empty = true - local handlers = {...} - if not next(handlers) then - error("handler should not be nil or empty") - end - - for _, h in ipairs(handlers) do - if type(h) == "function" then - local action = ActionHolder:new(h, self, "handler") - table_insert(self.handlers[method], action) - empty = false - elseif type(h) == "table" then - for _, hh in ipairs(h) do - if type(hh) == "function" then - local action = ActionHolder:new(hh, self, "handler") - table_insert(self.handlers[method], action) - empty = false - else - error(handler_error_tip) - end - end - else - error(handler_error_tip) - end - end - - if empty then - error("handler should not be empty") - end - - if self.allow == "" then - self.allow = method - else - self.allow = self.allow .. ", " .. method - end - - return self -end - -function Node:get_allow() - return self.allow -end - -function Node:remove_nested_property(node) - if not node then return end - if node.parent then - node.parent = nil - end - - if node.colon_child then - if node.colon_child.handlers then - for _, h in pairs(node.colon_child.handlers) do - if h then - for _, action in ipairs(h) do - action.func = nil - action.node = nil - end - end - end - end - self:remove_nested_property(node.colon_child) - end - - local children = node.children - if children and #children > 0 then - for _, v in ipairs(children) do - local c = v.val - if c.handlers then -- remove action func - for _, h in pairs(c.handlers) do - if h then - for _, action in ipairs(h) do - action.func = nil - action.node = nil - end - end - end - end - - self:remove_nested_property(v.val) - end - end -end - -return Node diff --git a/website/backend/lor/lib/lor/lib/request.lua b/website/backend/lor/lib/lor/lib/request.lua deleted file mode 100755 index a561cc3..0000000 --- a/website/backend/lor/lib/lor/lib/request.lua +++ /dev/null @@ -1,75 +0,0 @@ -local sfind = string.find -local pairs = pairs -local type = type -local setmetatable = setmetatable -local utils = require("lor.lib.utils.utils") - -local Request = {} - --- new request: init args/params/body etc from http request -function Request:new() - local body = {} -- body params - local headers = ngx.req.get_headers() - - local header = headers['Content-Type'] - -- the post request have Content-Type header set - if header then - if sfind(header, "application/x-www-form-urlencoded", 1, true) then - ngx.req.read_body() - local post_args = ngx.req.get_post_args() - if post_args and type(post_args) == "table" then - for k,v in pairs(post_args) do - body[k] = v - end - end - elseif sfind(header, "application/json", 1, true) then - ngx.req.read_body() - local json_str = ngx.req.get_body_data() - body = utils.json_decode(json_str) - -- form-data request - elseif sfind(header, "multipart", 1, true) then - -- upload request, should not invoke ngx.req.read_body() - -- parsed as raw by default - else - ngx.req.read_body() - body = ngx.req.get_body_data() - end - -- the post request have no Content-Type header set will be parsed as x-www-form-urlencoded by default - else - ngx.req.read_body() - local post_args = ngx.req.get_post_args() - if post_args and type(post_args) == "table" then - for k,v in pairs(post_args) do - body[k] = v - end - end - end - - local instance = { - path = ngx.var.uri, -- uri - method = ngx.req.get_method(), - query = ngx.req.get_uri_args(), - params = {}, - body = body, - body_raw = ngx.req.get_body_data(), - url = ngx.var.request_uri, - origin_uri = ngx.var.request_uri, - uri = ngx.var.request_uri, - headers = headers, -- request headers - - req_args = ngx.var.args, - found = false -- 404 or not - } - setmetatable(instance, { __index = self }) - return instance -end - -function Request:is_found() - return self.found -end - -function Request:set_found(found) - self.found = found -end - -return Request diff --git a/website/backend/lor/lib/lor/lib/response.lua b/website/backend/lor/lib/lor/lib/response.lua deleted file mode 100755 index 7409cca..0000000 --- a/website/backend/lor/lib/lor/lib/response.lua +++ /dev/null @@ -1,141 +0,0 @@ -local pairs = pairs -local type = type -local setmetatable = setmetatable -local tinsert = table.insert -local tconcat = table.concat -local utils = require("lor.lib.utils.utils") - -local Response = {} - -function Response:new() - --ngx.status = 200 - local instance = { - http_status = nil, - headers = {}, - locals = {}, - body = '--default body. you should not see this by default--', - view = nil - } - - setmetatable(instance, { __index = self }) - return instance -end - --- todo: optimize-compile before used -function Response:render(view_file, data) - if not self.view then - ngx.log(ngx.ERR, "`view` object is nil, maybe you disabled the view engine.") - error("`view` object is nil, maybe you disabled the view engine.") - else - self:set_header('Content-Type', 'text/html; charset=UTF-8') - data = data or {} - data.locals = self.locals -- inject res.locals - - local body = self.view:render(view_file, data) - self:_send(body) - end -end - - -function Response:html(data) - self:set_header('Content-Type', 'text/html; charset=UTF-8') - self:_send(data) -end - -function Response:json(data, empty_table_as_object) - self:set_header('Content-Type', 'application/json; charset=utf-8') - self:_send(utils.json_encode(data, empty_table_as_object)) -end - -function Response:redirect(url, code, query) - if url and not code and not query then -- only one param - ngx.redirect(url) - elseif url and code and not query then -- two param - if type(code) == "number" then - ngx.redirect(url ,code) - elseif type(code) == "table" then - query = code - local q = {} - local is_q_exist = false - if query and type(query) == "table" then - for i,v in pairs(query) do - tinsert(q, i .. "=" .. v) - is_q_exist = true - end - end - - if is_q_exist then - url = url .. "?" .. tconcat(q, "&") - end - - ngx.redirect(url) - else - ngx.redirect(url) - end - else -- three param - local q = {} - local is_q_exist = false - if query and type(query) == "table" then - for i,v in pairs(query) do - tinsert(q, i .. "=" .. v) - is_q_exist = true - end - end - - if is_q_exist then - url = url .. "?" .. tconcat(q, "&") - end - ngx.redirect(url ,code) - end -end - -function Response:location(url, data) - if data and type(data) == "table" then - ngx.req.set_uri_args(data) - ngx.req.set_uri(url, false) - else - ngx.say(url) - ngx.req.set_uri(url, false) - end -end - -function Response:send(text) - self:set_header('Content-Type', 'text/plain; charset=UTF-8') - self:_send(text) -end - ---~============================================================= - -function Response:_send(content) - ngx.status = self.http_status or 200 - ngx.say(content) - DEBUG("=response send content: ", content) -end - -function Response:get_body() - return self.body -end - -function Response:get_headers() - return self.headers -end - -function Response:get_header(key) - return self.headers[key] -end - -function Response:set_body(body) - if body ~= nil then self.body = body end -end - -function Response:status(status) - ngx.status = status - self.http_status = status - return self -end - -function Response:set_header(key, value) - ngx.header[key] = value -end - -return Response diff --git a/website/backend/lor/lib/lor/lib/router/group.lua b/website/backend/lor/lib/lor/lib/router/group.lua deleted file mode 100644 index 61a2019..0000000 --- a/website/backend/lor/lib/lor/lib/router/group.lua +++ /dev/null @@ -1,141 +0,0 @@ -local setmetatable = setmetatable -local pairs = pairs -local type = type -local error = error -local next = next -local string_format = string.format -local string_lower = string.lower -local table_insert = table.insert -local unpack = table.unpack or unpack - -local supported_http_methods = require("lor.lib.methods") -local debug = require("lor.lib.debug") -local utils = require("lor.lib.utils.utils") -local random = utils.random -local clone = utils.clone -local handler_error_tip = "handler must be `function` that matches `function(req, res, next) ... end`" - -local Group = {} - -function Group:new() - local group = {} - - group.id = random() - group.name = "group-" .. group.id - group.is_group = true - group.apis = {} - self:build_method() - - setmetatable(group, { - __index = self, - __call = self._call, - __tostring = function(s) - return s.name - end - }) - - return group -end - ---- a magick for usage like `lor:Router()` --- generate a new group for different routes group -function Group:_call() - local cloned = clone(self) - cloned.id = random() - cloned.name = cloned.name .. ":clone-" .. cloned.id - return cloned -end - -function Group:get_apis() - return self.apis -end - -function Group:set_api(path, method, ...) - if not path or not method then - return error("`path` & `method` should not be nil.") - end - - local handlers = {...} - if not next(handlers) then - return error("handler should not be nil or empty") - end - - if type(path) ~= "string" or type(method) ~= "string" or type(handlers) ~= "table" then - return error("params type error.") - end - - local extended_handlers = {} - for _, h in ipairs(handlers) do - if type(h) == "function" then - table_insert(extended_handlers, h) - elseif type(h) == "table" then - for _, hh in ipairs(h) do - if type(hh) == "function" then - table_insert(extended_handlers, hh) - else - error(handler_error_tip) - end - end - else - error(handler_error_tip) - end - end - - method = string_lower(method) - if not supported_http_methods[method] then - return error(string_format("[%s] method is not supported yet.", method)) - end - - self.apis[path] = self.apis[path] or {} - self.apis[path][method] = extended_handlers -end - -function Group:build_method() - for m, _ in pairs(supported_http_methods) do - m = string_lower(m) - - -- 1. group_router:get(func1) - -- 2. group_router:get(func1, func2) - -- 3. group_router:get({func1, func2}) - -- 4. group_router:get(path, func1) - -- 5. group_router:get(path, func1, func2) - -- 6. group_router:get(path, {func1, func2}) - Group[m] = function(myself, ...) - local params = {...} - if not next(params) then return error("params should not be nil or empty") end - - -- case 1 or 3 - if #params == 1 then - if type(params[1]) ~= "function" and type(params[1]) ~= "table" then - return error("it must be an function if there's only one param") - end - - if type(params[1]) == "table" and #(params[1]) == 0 then - return error("params should not be nil or empty") - end - - return Group.set_api(myself, "", m, ...) - end - - -- case 2,4,5,6 - if #params > 1 then - if type(params[1]) == "string" then -- case 4,5,6 - return Group.set_api(myself, params[1], m, unpack(params, 2)) - else -- case 2 - return Group.set_api(myself, "", m, ...) - end - end - - error("error params for group route define") - end - end -end - -function Group:clone() - local cloned = clone(self) - cloned.id = random() - cloned.name = cloned.name .. ":clone-" .. cloned.id - return cloned -end - -return Group diff --git a/website/backend/lor/lib/lor/lib/router/router.lua b/website/backend/lor/lib/lor/lib/router/router.lua deleted file mode 100755 index 4c17312..0000000 --- a/website/backend/lor/lib/lor/lib/router/router.lua +++ /dev/null @@ -1,353 +0,0 @@ -local pairs = pairs -local ipairs = ipairs -local pcall = pcall -local xpcall = xpcall -local type = type -local error = error -local setmetatable = setmetatable -local traceback = debug.traceback -local tinsert = table.insert -local table_concat = table.concat -local string_format = string.format -local string_lower = string.lower - -local utils = require("lor.lib.utils.utils") -local supported_http_methods = require("lor.lib.methods") -local debug = require("lor.lib.debug") -local Trie = require("lor.lib.trie") -local random = utils.random -local mixin = utils.mixin - -local allowed_conf = { - strict_route = { - t = "boolean" - }, - ignore_case = { - t = "boolean" - }, - max_uri_segments = { - t = "number" - }, - max_fallback_depth = { - t = "number" - }, -} - -local function restore(fn, obj) - local origin = { - path = obj['path'], - query = obj['query'], - next = obj['next'], - locals = obj['locals'], - } - - return function(err) - obj['path'] = origin.path - obj['query'] = origin.query - obj['next'] = origin.next - obj['locals'] = origin.locals - fn(err) - end -end - -local function compose_func(matched, method) - if not matched or type(matched.pipeline) ~= "table" then - return nil - end - - local exact_node = matched.node - local pipeline = matched.pipeline or {} - if not exact_node or not pipeline then - return nil - end - - local stack = {} - for _, p in ipairs(pipeline) do - local middlewares = p.middlewares - local handlers = p.handlers - if middlewares then - for _, middleware in ipairs(middlewares) do - tinsert(stack, middleware) - end - end - - if p.id == exact_node.id and handlers and handlers[method] then - for _, handler in ipairs(handlers[method]) do - tinsert(stack, handler) - end - end - end - - return stack -end - -local function compose_error_handler(node) - if not node then - return nil - end - - local stack = {} - while node do - for _, middleware in ipairs(node.error_middlewares) do - tinsert(stack, middleware) - end - node = node.parent - end - - return stack -end - - -local Router = {} - -function Router:new(options) - local opts = options or {} - local router = {} - - router.name = "router-" .. random() - router.trie = Trie:new({ - ignore_case = opts.ignore_case, - strict_route = opts.strict_route, - max_uri_segments = opts.max_uri_segments, - max_fallback_depth = opts.max_fallback_depth - }) - - self:init() - setmetatable(router, { - __index = self, - __tostring = function(s) - local ok, result = pcall(function() - return string_format("name: %s", s.name) - end) - if ok then - return result - else - return "router.tostring() error" - end - end - }) - - return router -end - ---- a magick to convert `router()` to `router:handle()` --- so a router() could be regarded as a `middleware` -function Router:call() - return function(req, res, next) - return self:handle(req, res, next) - end -end - --- dispatch a request -function Router:handle(req, res, out) - local path = req.path - if not path or path == "" then - path = "" - end - local method = req.method and string_lower(req.method) - local done = out - - local stack = nil - local matched = self.trie:match(path) - local matched_node = matched.node - - -- ngx.log(ngx.ERR, "rounter handler req: ", inspect(req)) - - if not method or not matched_node then - if res.status then res:status(404) end - return self:error_handle("404! not found.", req, res, self.trie.root, done) - else - local matched_handlers = matched_node.handlers and matched_node.handlers[method] - if not matched_handlers or #matched_handlers <= 0 then - return self:error_handle("Oh! no handler to process method: " .. method, req, res, self.trie.root, done) - end - - stack = compose_func(matched, method) - if not stack or #stack <= 0 then - return self:error_handle("Oh! no handlers found.", req, res, self.trie.root, done) - end - end - - local stack_len = #stack - req:set_found(true) - local parsed_params = matched.params or {} -- origin params, parsed - req.params = parsed_params - - local idx = 0 - local function next(err) - if err then - return self:error_handle(err, req, res, stack[idx].node, done) - end - - if idx > stack_len then - return done(err) -- err is nil or not - end - - idx = idx + 1 - local handler = stack[idx] - if not handler then - return done(err) - end - - local err_msg - local ok, ee = xpcall(function() - handler.func(req, res, next) - req.params = mixin(parsed_params, req.params) - end, function(msg) - if msg then - if type(msg) == "string" then - err_msg = msg - elseif type(msg) == "table" then - err_msg = "[ERROR]" .. table_concat(msg, "|") .. "[/ERROR]" - end - else - err_msg = "" - end - err_msg = err_msg .. "\n" .. traceback() - end) - - if not ok then - --debug("handler func:call error ---> to error_handle,", ok, "err_msg:", err_msg) - return self:error_handle(err_msg, req, res, handler.node, done) - end - end - - next() -end - --- dispatch an error -function Router:error_handle(err_msg, req, res, node, done) - local stack = compose_error_handler(node) - if not stack or #stack <= 0 then - return done(err_msg) - end - - local idx = 0 - local stack_len = #stack - local function next(err) - if idx >= stack_len then - return done(err) - end - - idx = idx + 1 - local error_handler = stack[idx] - if not error_handler then - return done(err) - end - - local ok, ee = xpcall(function() - error_handler.func(err, req, res, next) - end, function(msg) - if msg then - if type(msg) == "string" then - err_msg = msg - elseif type(msg) == "table" then - err_msg = "[ERROR]" .. table_concat(msg, "|") .. "[/ERROR]" - end - else - err_msg = "" - end - - err_msg = string_format("%s\n[ERROR in ErrorMiddleware#%s(%s)] %s \n%s", err, idx, error_handler.id, err_msg, traceback()) - end) - - if not ok then - return done(err_msg) - end - end - - next(err_msg) -end - -function Router:use(path, fn, fn_args_length) - if type(fn) == "function" then -- fn is a function - local node - if not path then - node = self.trie.root - else - node = self.trie:add_node(path) - end - if fn_args_length == 3 then - node:use(fn) - elseif fn_args_length == 4 then - node:error_use(fn) - end - elseif fn and fn.is_group == true then -- fn is a group router - if fn_args_length ~= 3 then - error("illegal param, fn_args_length should be 3") - end - - path = path or "" -- if path is nil, then mount it on `root` - self:merge_group(path, fn) - end - - return self -end - -function Router:merge_group(prefix, group) - local apis = group:get_apis() - - if apis then - for uri, api_methods in pairs(apis) do - if type(api_methods) == "table" then - local path - if uri == "" then -- for group index route - path = utils.clear_slash(prefix) - else - path = utils.clear_slash(prefix .. "/" .. uri) - end - - local node = self.trie:add_node(path) - if not node then - return error("cann't define node on router trie, path:" .. path) - end - - for method, handlers in pairs(api_methods) do - local m = string_lower(method) - if supported_http_methods[m] == true then - node:handle(m, handlers) - end -- supported method - end - end - end - end -- ugly arrow style for missing `continue` - - return self -end - -function Router:app_route(http_method, path, ...) - local node = self.trie:add_node(path) - node:handle(http_method, ...) - return self -end - -function Router:init() - for http_method, _ in pairs(supported_http_methods) do - self[http_method] = function(s, path, ...) - local node = s.trie:add_node(path) - node:handle(http_method, ...) - return s - end - end -end - -function Router:conf(setting, val) - local allow = allowed_conf[setting] - if allow then - if allow.t == "boolean" then - - if val == "true" or val == true then - self.trie[setting] = true - elseif val == "false" or val == false then - self.trie[setting] = false - end - elseif allow.t == "number" then - val = tonumber(val) - self.trie[setting] = val or self[setting] - end - end - - return self -end - -return Router diff --git a/website/backend/lor/lib/lor/lib/trie.lua b/website/backend/lor/lib/lor/lib/trie.lua deleted file mode 100644 index ff79a3e..0000000 --- a/website/backend/lor/lib/lor/lib/trie.lua +++ /dev/null @@ -1,532 +0,0 @@ -local setmetatable = setmetatable -local tonumber = tonumber -local string_lower = string.lower -local string_find = string.find -local string_sub = string.sub -local string_gsub = string.gsub -local string_len = string.len -local string_format = string.format -local table_insert = table.insert -local table_remove = table.remove -local table_concat = table.concat - -local utils = require("lor.lib.utils.utils") -local holder = require("lor.lib.holder") -local Node = require("lor.lib.node") -local NodeHolder = holder.NodeHolder -local Matched = holder.Matched -local mixin = utils.mixin -local valid_segment_tip = "valid path should only contains: [A-Za-z0-9._%-~]" - - -local function check_segment(segment) - local tmp = string_gsub(segment, "([A-Za-z0-9._%-~]+)", "") - if tmp ~= "" then - return false - end - return true -end - -local function check_colon_child(node, colon_child) - if not node or not colon_child then - return false, nil - end - - if node.name ~= colon_child.name or node.regex ~= colon_child.regex then - return false, colon_child - end - - return true, nil -- could be added -end - -local function get_or_new_node(parent, frag, ignore_case) - if not frag or frag == "/" or frag == "" then - frag = "" - end - - if ignore_case == true then - frag = string_lower(frag) - end - - local node = parent:find_child(frag) - if node then - return node - end - - node = Node:new() - node.parent = parent - - if frag == "" then - local nodePack = NodeHolder:new() - nodePack.key = frag - nodePack.val = node - table_insert(parent.children, nodePack) - else - local first = string_sub(frag, 1, 1) - if first == ":" then - local name = string_sub(frag, 2) - local trailing = string_sub(name, -1) - - if trailing == ')' then - local index = string_find(name, "%(") - if index and index > 1 then - local regex = string_sub(name, index+1, #name-1) - if #regex > 0 then - name = string_sub(name, 1, index-1 ) - node.regex = regex - else - error("invalid pattern[1]: " .. frag) - end - end - end - - local is_name_valid = check_segment(name) - if not is_name_valid then - error("invalid pattern[2], illegal path:" .. name .. ", " .. valid_segment_tip) - end - node.name = name - - local colon_child = parent.colon_child - if colon_child then - local valid, conflict = check_colon_child(node, colon_child) - if not valid then - error("invalid pattern[3]: [" .. name .. "] conflict with [" .. conflict.name .. "]") - else - return colon_child - end - end - - parent.colon_child = node - else - local is_name_valid = check_segment(frag) - if not is_name_valid then - error("invalid pattern[6]: " .. frag .. ", " .. valid_segment_tip) - end - - local nodePack = NodeHolder:new() - nodePack.key = frag - nodePack.val = node - table_insert(parent.children, nodePack) - end - end - - return node -end - -local function insert_node(parent, frags, ignore_case) - local frag = frags[1] - local child = get_or_new_node(parent, frag, ignore_case) - - if #frags >= 1 then - table_remove(frags, 1) - end - - if #frags == 0 then - child.endpoint = true - return child - end - - return insert_node(child, frags, ignore_case) -end - -local function get_pipeline(node) - local pipeline = {} - if not node then return pipeline end - - local tmp = {} - local origin_node = node - table_insert(tmp, origin_node) - while node.parent - do - table_insert(tmp, node.parent) - node = node.parent - end - - for i = #tmp, 1, -1 do - table_insert(pipeline, tmp[i]) - end - - return pipeline -end - - -local Trie = {} - -function Trie:new(opts) - opts = opts or {} - local trie = { - -- limit to avoid dead `while` or attack for fallback lookup - max_fallback_depth = 100, - - -- limit to avoid uri attack. e.g. a long uri, /a/b/c/d/e/f/g/h/i/j/k... - max_uri_segments = 100, - - -- should ignore case or not - ignore_case = true, - - -- [true]: "test.com/" is not the same with "test.com". - -- [false]: "test.com/" will match "test.com/" first, then try to math "test.com" if not exists - strict_route = true, - - -- the root node of this trie structure - root = Node:new(true) - } - - trie.max_fallback_depth = tonumber(opts.max_fallback_depth) or trie.max_fallback_depth - trie.max_uri_segments = tonumber(opts.max_uri_segments) or trie.max_uri_segments - trie.ignore_case = opts.ignore_case or trie.ignore_case - trie.strict_route = not (opts.strict_route == false) - - setmetatable(trie, { - __index = self, - __tostring = function(s) - return string_format("Trie, ignore_case:%s strict_route:%s max_uri_segments:%d max_fallback_depth:%d", - s.ignore_case, s.strict_route, s.max_uri_segments, s.max_fallback_depth) - end - }) - - return trie -end - -function Trie:add_node(pattern) - pattern = utils.trim_path_spaces(pattern) - - if string_find(pattern, "//") then - error("`//` is not allowed: " .. pattern) - end - - local tmp_pattern = utils.trim_prefix_slash(pattern) - local tmp_segments = utils.split(tmp_pattern, "/") - - local node = insert_node(self.root, tmp_segments, self.ignore_case) - if node.pattern == "" then - node.pattern = pattern - end - - return node -end - ---- get matched colon node -function Trie:get_colon_node(parent, segment) - local child = parent.colon_child - if child and child.regex and not utils.is_match(segment, child.regex) then - child = nil -- illegal & not mathed regrex - end - return child -end - ---- retry to fallback to lookup the colon nodes in `stack` -function Trie:fallback_lookup(fallback_stack, segments, params) - if #fallback_stack == 0 then - return false - end - - local fallback = table_remove(fallback_stack, #fallback_stack) - local segment_index = fallback.segment_index - local parent = fallback.colon_node - local matched = Matched:new() - - if parent.name ~= "" then -- fallback to the colon node and fill param if matched - matched.params[parent.name] = segments[segment_index] - end - mixin(params, matched.params) -- mixin params parsed before - - local flag = true - for i, s in ipairs(segments) do - if i <= segment_index then -- mind: should use <= not < - -- continue - else - local node, colon_node, is_same = self:find_matched_child(parent, s) - if self.ignore_case and node == nil then - node, colon_node, is_same = self:find_matched_child(parent, string_lower(s)) - end - - if colon_node and not is_same then - -- save colon node to fallback stack - table_insert(fallback_stack, { - segment_index = i, - colon_node = colon_node - }) - end - - if node == nil then -- both exact child and colon child is nil - flag = false -- should not set parent value - break - end - - parent = node - end - end - - if flag and parent.endpoint then - matched.node = parent - matched.pipeline = get_pipeline(parent) - end - - if matched.node then - return matched - else - return false - end -end - ---- find exactly mathed node and colon node -function Trie:find_matched_child(parent, segment) - local child = parent:find_child(segment) - local colon_node = self:get_colon_node(parent, segment) - - if child then - if colon_node then - return child, colon_node, false - else - return child, nil, false - end - else -- not child - if colon_node then - return colon_node, colon_node, true -- 后续不再压栈 - else - return nil, nil, false - end - end -end - -function Trie:match(path) - if not path or path == "" then - error("`path` should not be nil or empty") - end - - path = utils.slim_path(path) - - local first = string_sub(path, 1, 1) - if first ~= '/' then - error("`path` is not start with prefix /: " .. path) - end - - if path == "" then -- special case: regard "test.com" as "test.com/" - path = "/" - end - - local matched = self:_match(path) - if not matched.node and self.strict_route ~= true then - if string_sub(path, -1) == '/' then -- retry to find path without last slash - matched = self:_match(string_sub(path, 1, -2)) - end - end - - return matched -end - -function Trie:_match(path) - local start_pos = 2 - local end_pos = string_len(path) + 1 - local segments = {} - for i = 2, end_pos, 1 do -- should set max depth to avoid attack - if i < end_pos and string_sub(path, i, i) ~= '/' then - -- continue - else - local segment = string_sub(path, start_pos, i-1) - table_insert(segments, segment) - start_pos = i + 1 - end - end - - local flag = true -- whether to continue to find matched node or not - local matched = Matched:new() - local parent = self.root - local fallback_stack = {} - for i, s in ipairs(segments) do - local node, colon_node, is_same = self:find_matched_child(parent, s) - if self.ignore_case and node == nil then - node, colon_node, is_same = self:find_matched_child(parent, string_lower(s)) - end - - if colon_node and not is_same then - table_insert(fallback_stack, { - segment_index = i, - colon_node = colon_node - }) - end - - if node == nil then -- both exact child and colon child is nil - flag = false -- should not set parent value - break - end - - parent = node - if parent.name ~= "" then - matched.params[parent.name] = s - end - end - - if flag and parent.endpoint then - matched.node = parent - end - - local params = matched.params or {} - if not matched.node then - local depth = 0 - local exit = false - - while not exit do - depth = depth + 1 - if depth > self.max_fallback_depth then - error("fallback lookup reaches the limit: " .. self.max_fallback_depth) - end - - exit = self:fallback_lookup(fallback_stack, segments, params) - if exit then - matched = exit - break - end - - if #fallback_stack == 0 then - break - end - end - end - - matched.params = params - if matched.node then - matched.pipeline = get_pipeline(matched.node) - end - - return matched -end - ---- only for dev purpose: pretty json preview --- must not be invoked in runtime -function Trie:remove_nested_property(node) - if not node then return end - if node.parent then - node.parent = nil - end - if node.handlers then - for _, h in pairs(node.handlers) do - if h then - for _, action in ipairs(h) do - action.func = nil - action.node = nil - end - end - end - end - if node.middlewares then - for _, m in pairs(node.middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - if node.error_middlewares then - for _, m in pairs(node.error_middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - - if node.colon_child then - if node.colon_child.handlers then - for _, h in pairs(node.colon_child.handlers) do - if h then - for _, action in ipairs(h) do - action.func = nil - action.node = nil - end - end - end - end - if node.colon_child.middlewares then - for _, m in pairs(node.colon_child.middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - if node.colon_child.error_middlewares then - for _, m in pairs(node.colon_child.error_middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - self:remove_nested_property(node.colon_child) - end - - local children = node.children - if children and #children > 0 then - for _, v in ipairs(children) do - local c = v.val - if c.handlers then -- remove action func - for _, h in pairs(c.handlers) do - if h then - for _, action in ipairs(h) do - action.func = nil - action.node = nil - end - end - end - end - if c.middlewares then - for _, m in pairs(c.middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - if c.error_middlewares then - for _, m in pairs(c.error_middlewares) do - if m then - m.func = nil - m.node = nil - end - end - end - - self:remove_nested_property(v.val) - end - end -end - ---- only for dev purpose: graph preview --- must not be invoked in runtime -function Trie:gen_graph() - local cloned_trie = utils.clone(self) - cloned_trie:remove_nested_property(cloned_trie.root) - local result = {"graph TD", cloned_trie.root.id .. "((root))"} - - local function recursive_draw(node, res) - if node.is_root then node.key = "root" end - - local colon_child = node.colon_child - if colon_child then - table_insert(res, node.id .. "-->" .. colon_child.id .. "(:" .. colon_child.name .. "
" .. colon_child.id .. ")") - recursive_draw(colon_child, res) - end - - local children = node.children - if children and #children > 0 then - for _, v in ipairs(children) do - if v.key == "" then - --table_insert(res, node.id .. "-->" .. v.val.id .. "[*EMPTY*]") - local text = {node.id, "-->", v.val.id, "(
", "*EMPTY*", "
", v.val.id, "
)"} - table_insert(res, table_concat(text, "")) - else - local text = {node.id, "-->", v.val.id, "(
", v.key, "
", v.val.id, "
)"} - table_insert(res, table_concat(text, "")) - end - recursive_draw(v.val, res) - end - end - end - - recursive_draw(cloned_trie.root, result) - return table.concat(result, "\n") -end - -return Trie diff --git a/website/backend/lor/lib/lor/lib/utils/aes.lua b/website/backend/lor/lib/lor/lib/utils/aes.lua deleted file mode 100644 index 98456a1..0000000 --- a/website/backend/lor/lib/lor/lib/utils/aes.lua +++ /dev/null @@ -1,54 +0,0 @@ --- from lua-resty-session -local setmetatable = setmetatable -local tonumber = tonumber -local aes = require "resty.aes" -local cip = aes.cipher -local hashes = aes.hash -local var = ngx.var - -local CIPHER_MODES = { - ecb = "ecb", - cbc = "cbc", - cfb1 = "cfb1", - cfb8 = "cfb8", - cfb128 = "cfb128", - ofb = "ofb", - ctr = "ctr" -} - -local CIPHER_SIZES = { - ["128"] = 128, - ["192"] = 192, - ["256"] = 256 -} - -local defaults = { - size = CIPHER_SIZES[var.session_aes_size] or 256, - mode = CIPHER_MODES[var.session_aes_mode] or "cbc", - hash = hashes[var.session_aes_hash] or "sha512", - rounds = tonumber(var.session_aes_rounds) or 1 -} - -local cipher = {} - -cipher.__index = cipher - -function cipher.new(config) - local a = config and config.aes or defaults - return setmetatable({ - size = CIPHER_SIZES[a.size or defaults.size] or 256, - mode = CIPHER_MODES[a.mode or defaults.mode] or "cbc", - hash = hashes[a.hash or defaults.hash] or hashes.sha512, - rounds = tonumber(a.rounds or defaults.rounds) or 1 - }, cipher) -end - -function cipher:encrypt(d, k, s) - return aes:new(k, s, cip(self.size, self.mode), self.hash, self.rounds):encrypt(d) -end - -function cipher:decrypt(d, k, s) - return aes:new(k, s, cip(self.size, self.mode), self.hash, self.rounds):decrypt(d) -end - -return cipher diff --git a/website/backend/lor/lib/lor/lib/utils/base64.lua b/website/backend/lor/lib/lor/lib/utils/base64.lua deleted file mode 100644 index d1872aa..0000000 --- a/website/backend/lor/lib/lor/lib/utils/base64.lua +++ /dev/null @@ -1,27 +0,0 @@ -local ngx = ngx -local base64enc = ngx.encode_base64 -local base64dec = ngx.decode_base64 - -local ENCODE_CHARS = { - ["+"] = "-", - ["/"] = "_", - ["="] = "." -} - -local DECODE_CHARS = { - ["-"] = "+", - ["_"] = "/", - ["."] = "=" -} - -local base64 = {} - -function base64.encode(value) - return (base64enc(value):gsub("[+/=]", ENCODE_CHARS)) -end - -function base64.decode(value) - return base64dec((value:gsub("[-_.]", DECODE_CHARS))) -end - -return base64 diff --git a/website/backend/lor/lib/lor/lib/utils/utils.lua b/website/backend/lor/lib/lor/lib/utils/utils.lua deleted file mode 100755 index 52ca1d5..0000000 --- a/website/backend/lor/lib/lor/lib/utils/utils.lua +++ /dev/null @@ -1,152 +0,0 @@ -local type = type -local pairs = pairs -local setmetatable = setmetatable -local mrandom = math.random -local sreverse = string.reverse -local sfind = string.find -local sgsub = string.gsub -local smatch = string.match -local table_insert = table.insert -local json = require("cjson") - -local _M = {} - -function _M.clone(o) - local lookup_table = {} - local function _copy(object) - if type(object) ~= "table" then - return object - elseif lookup_table[object] then - return lookup_table[object] - end - local new_object = {} - lookup_table[object] = new_object - for key, value in pairs(object) do - new_object[_copy(key)] = _copy(value) - end - return setmetatable(new_object, getmetatable(object)) - end - return _copy(o) -end - -function _M.clear_slash(s) - local r, _ = sgsub(s, "(/+)", "/") - return r -end - -function _M.is_table_empty(t) - if t == nil or _G.next(t) == nil then - return true - else - return false - end -end - -function _M.table_is_array(t) - if type(t) ~= "table" then return false end - local i = 0 - for _ in pairs(t) do - i = i + 1 - if t[i] == nil then return false end - end - return true -end - -function _M.mixin(a, b) - if a and b then - for k, _ in pairs(b) do - a[k] = b[k] - end - end - return a -end - -function _M.random() - return mrandom(0, 10000) -end - -function _M.json_encode(data, empty_table_as_object) - local json_value - if json.encode_empty_table_as_object then - -- empty table encoded as array default - json.encode_empty_table_as_object(empty_table_as_object or false) - end - if require("ffi").os ~= "Windows" then - json.encode_sparse_array(true) - end - pcall(function(d) json_value = json.encode(d) end, data) - return json_value -end - -function _M.json_decode(str) - local ok, data = pcall(json.decode, str) - if ok then - return data - end -end - -function _M.start_with(str, substr) - if str == nil or substr == nil then - return false - end - if sfind(str, substr) ~= 1 then - return false - else - return true - end -end - -function _M.end_with(str, substr) - if str == nil or substr == nil then - return false - end - local str_reverse = sreverse(str) - local substr_reverse = sreverse(substr) - if sfind(str_reverse, substr_reverse) ~= 1 then - return false - else - return true - end -end - -function _M.is_match(uri, pattern) - if not pattern then - return false - end - - local ok = smatch(uri, pattern) - if ok then return true else return false end -end - -function _M.trim_prefix_slash(s) - local str, _ = sgsub(s, "^(//*)", "") - return str -end - -function _M.trim_suffix_slash(s) - local str, _ = sgsub(s, "(//*)$", "") - return str -end - -function _M.trim_path_spaces(path) - if not path or path == "" then return path end - return sgsub(path, "( *)", "") -end - -function _M.slim_path(path) - if not path or path == "" then return path end - return sgsub(path, "(//*)", "/") -end - -function _M.split(str, delimiter) - if not str or str == "" then return {} end - if not delimiter or delimiter == "" then return { str } end - - local result = {} - for match in (str .. delimiter):gmatch("(.-)" .. delimiter) do - table_insert(result, match) - end - return result -end - -return _M diff --git a/website/backend/lor/lib/lor/lib/view.lua b/website/backend/lor/lib/lor/lib/view.lua deleted file mode 100755 index 0090c4f..0000000 --- a/website/backend/lor/lib/lor/lib/view.lua +++ /dev/null @@ -1,54 +0,0 @@ -local pairs = pairs -local type = type -local setmetatable = setmetatable -local tostring = tostring -local template = require "resty.template" -local template_new = template.new - -local View = {} - -function View:new(view_config) - local instance = {} - instance.view_enable = view_config.view_enable - if instance.view_enable then - if ngx.var.template_root then - ngx.var.template_root = view_config.views - else - ngx.log(ngx.ERR, "$template_root is not set in nginx.conf") - end - end - instance.view_engine = view_config.view_engine - instance.view_ext = view_config.view_ext - instance.view_layout = view_config.view_layout - instance.views = view_config.views - - setmetatable(instance, {__index = self}) - return instance -end - -function View:caching() -end - --- to optimize -function View:render(view_file, data) - if not self.view_enable then - ngx.log(ngx.ERR, "view is not enabled. you may need `app:conf('view enable', true)`") - else - local view_file_name = view_file .. "." .. self.view_ext - local layout_file_name = self.view_layout .. "." .. self.view_ext - - local t = template_new(view_file_name) - if self.view_layout ~= "" then - t = template_new(view_file_name,layout_file_name) - end - if data and type(data) == 'table' then - for k,v in pairs(data) do - t[k] = v - end - end - - return tostring(t) - end -end - -return View \ No newline at end of file diff --git a/website/backend/lor/lib/lor/lib/wrap.lua b/website/backend/lor/lib/lor/lib/wrap.lua deleted file mode 100755 index 255893d..0000000 --- a/website/backend/lor/lib/lor/lib/wrap.lua +++ /dev/null @@ -1,40 +0,0 @@ -local setmetatable = setmetatable - -local _M = {} - -function _M:new(create_app, Router, Group, Request, Response) - local instance = {} - instance.router = Router - instance.group = Group - instance.request = Request - instance.response = Response - instance.fn = create_app - instance.app = nil - - setmetatable(instance, { - __index = self, - __call = self.create_app - }) - - return instance -end - --- Generally, this should only be used by `lor` framework itself. -function _M:create_app(options) - self.app = self.fn(options) - return self.app -end - -function _M:Router(options) - return self.group:new(options) -end - -function _M:Request() - return self.request:new() -end - -function _M:Response() - return self.response:new() -end - -return _M diff --git a/website/backend/lor/lib/lor/version.lua b/website/backend/lor/lib/lor/version.lua deleted file mode 100755 index b8cbfa0..0000000 --- a/website/backend/lor/lib/lor/version.lua +++ /dev/null @@ -1 +0,0 @@ -return "0.3.4" diff --git a/website/backend/lor/resty/cookie.lua b/website/backend/lor/resty/cookie.lua deleted file mode 100755 index cb5412f..0000000 --- a/website/backend/lor/resty/cookie.lua +++ /dev/null @@ -1,192 +0,0 @@ --- https://github.com/cloudflare/lua-resty-cookie/blob/master/lib/resty/cookie.lua - --- Copyright (C) 2013 Jiale Zhi (calio), Cloudflare Inc. --- See RFC6265 http://tools.ietf.org/search/rfc6265 --- require "luacov" - -local type = type -local byte = string.byte -local sub = string.sub -local format = string.format -local log = ngx.log -local ERR = ngx.ERR -local ngx_header = ngx.header - -local EQUAL = byte("=") -local SEMICOLON = byte(";") -local SPACE = byte(" ") -local HTAB = byte("\t") - --- table.new(narr, nrec) -local ok, new_tab = pcall(require, "table.new") -if not ok then - new_tab = function () return {} end -end - -local ok, clear_tab = pcall(require, "table.clear") -if not ok then - clear_tab = function(tab) for k, _ in pairs(tab) do tab[k] = nil end end -end - -local _M = new_tab(0, 2) - -_M._VERSION = '0.01' - - -local function get_cookie_table(text_cookie) - if type(text_cookie) ~= "string" then - log(ERR, format("expect text_cookie to be \"string\" but found %s", - type(text_cookie))) - return {} - end - - local EXPECT_KEY = 1 - local EXPECT_VALUE = 2 - local EXPECT_SP = 3 - - local n = 0 - local len = #text_cookie - - for i=1, len do - if byte(text_cookie, i) == SEMICOLON then - n = n + 1 - end - end - - local cookie_table = new_tab(0, n + 1) - - local state = EXPECT_SP - local i = 1 - local j = 1 - local key, value - - while j <= len do - if state == EXPECT_KEY then - if byte(text_cookie, j) == EQUAL then - key = sub(text_cookie, i, j - 1) - state = EXPECT_VALUE - i = j + 1 - end - elseif state == EXPECT_VALUE then - if byte(text_cookie, j) == SEMICOLON - or byte(text_cookie, j) == SPACE - or byte(text_cookie, j) == HTAB - then - value = sub(text_cookie, i, j - 1) - cookie_table[key] = value - - key, value = nil, nil - state = EXPECT_SP - i = j + 1 - end - elseif state == EXPECT_SP then - if byte(text_cookie, j) ~= SPACE - and byte(text_cookie, j) ~= HTAB - then - state = EXPECT_KEY - i = j - j = j - 1 - end - end - j = j + 1 - end - - if key ~= nil and value == nil then - cookie_table[key] = sub(text_cookie, i) - end - - return cookie_table -end - -function _M.new(self) - local _cookie = ngx.var.http_cookie - --if not _cookie then - --return nil, "no cookie found in current request" - --end - return setmetatable({ _cookie = _cookie, set_cookie_table = new_tab(4, 0) }, - { __index = self }) -end - -function _M.get(self, key) - if not self._cookie then - return nil, "no cookie found in the current request" - end - if self.cookie_table == nil then - self.cookie_table = get_cookie_table(self._cookie) - end - - return self.cookie_table[key] -end - -function _M.get_all(self) - if not self._cookie then - return nil, "no cookie found in the current request" - end - - if self.cookie_table == nil then - self.cookie_table = get_cookie_table(self._cookie) - end - - return self.cookie_table -end - -local function bake(cookie) - if not cookie.key or not cookie.value then - return nil, 'missing cookie field "key" or "value"' - end - - if cookie["max-age"] then - cookie.max_age = cookie["max-age"] - end - local str = cookie.key .. "=" .. cookie.value - .. (cookie.expires and "; Expires=" .. cookie.expires or "") - .. (cookie.max_age and "; Max-Age=" .. cookie.max_age or "") - .. (cookie.domain and "; Domain=" .. cookie.domain or "") - .. (cookie.path and "; Path=" .. cookie.path or "") - .. (cookie.secure and "; Secure" or "") - .. (cookie.httponly and "; HttpOnly" or "") - .. (cookie.extension and "; " .. cookie.extension or "") - return str -end - -function _M.set(self, cookie) - local cookie_str, err = bake(cookie) - if not cookie_str then - return nil, err - end - - local set_cookie = ngx_header['Set-Cookie'] - local set_cookie_type = type(set_cookie) - local t = self.set_cookie_table - clear_tab(t) - - if set_cookie_type == "string" then - -- only one cookie has been setted - if set_cookie ~= cookie_str then - t[1] = set_cookie - t[2] = cookie_str - ngx_header['Set-Cookie'] = t - end - elseif set_cookie_type == "table" then - -- more than one cookies has been setted - local size = #set_cookie - - -- we can not set cookie like ngx.header['Set-Cookie'][3] = val - -- so create a new table, copy all the values, and then set it back - for i=1, size do - t[i] = ngx_header['Set-Cookie'][i] - if t[i] == cookie_str then - -- new cookie is duplicated - return true - end - end - t[size + 1] = cookie_str - ngx_header['Set-Cookie'] = t - else - -- no cookie has been setted - ngx_header['Set-Cookie'] = cookie_str - end - return true -end - -return _M \ No newline at end of file diff --git a/website/backend/lor/resty/template.lua b/website/backend/lor/resty/template.lua deleted file mode 100755 index 0de71bd..0000000 --- a/website/backend/lor/resty/template.lua +++ /dev/null @@ -1,478 +0,0 @@ -local setmetatable = setmetatable -local loadstring = loadstring -local loadchunk -local tostring = tostring -local setfenv = setfenv -local require = require -local capture -local concat = table.concat -local assert = assert -local prefix -local write = io.write -local pcall = pcall -local phase -local open = io.open -local load = load -local type = type -local dump = string.dump -local find = string.find -local gsub = string.gsub -local byte = string.byte -local null -local sub = string.sub -local ngx = ngx -local jit = jit -local var - -local _VERSION = _VERSION -local _ENV = _ENV -local _G = _G - -local HTML_ENTITIES = { - ["&"] = "&", - ["<"] = "<", - [">"] = ">", - ['"'] = """, - ["'"] = "'", - ["/"] = "/" -} - -local CODE_ENTITIES = { - ["{"] = "{", - ["}"] = "}", - ["&"] = "&", - ["<"] = "<", - [">"] = ">", - ['"'] = """, - ["'"] = "'", - ["/"] = "/" -} - -local VAR_PHASES - -local ok, newtab = pcall(require, "table.new") -if not ok then newtab = function() return {} end end - -local caching = true -local template = newtab(0, 12) - -template._VERSION = "1.9" -template.cache = {} - -local function enabled(val) - if val == nil then return true end - return val == true or (val == "1" or val == "true" or val == "on") -end - -local function trim(s) - return gsub(gsub(s, "^%s+", ""), "%s+$", "") -end - -local function rpos(view, s) - while s > 0 do - local c = sub(view, s, s) - if c == " " or c == "\t" or c == "\0" or c == "\x0B" then - s = s - 1 - else - break - end - end - return s -end - -local function escaped(view, s) - if s > 1 and sub(view, s - 1, s - 1) == "\\" then - if s > 2 and sub(view, s - 2, s - 2) == "\\" then - return false, 1 - else - return true, 1 - end - end - return false, 0 -end - -local function readfile(path) - local file = open(path, "rb") - if not file then return nil end - local content = file:read "*a" - file:close() - return content -end - -local function loadlua(path) - return readfile(path) or path -end - -local function loadngx(path) - local vars = VAR_PHASES[phase()] - local file, location = path, vars and var.template_location - if sub(file, 1) == "/" then file = sub(file, 2) end - if location and location ~= "" then - if sub(location, -1) == "/" then location = sub(location, 1, -2) end - local res = capture(concat{ location, '/', file}) - if res.status == 200 then return res.body end - end - local root = vars and (var.template_root or var.document_root) or prefix - if sub(root, -1) == "/" then root = sub(root, 1, -2) end - return readfile(concat{ root, "/", file }) or path -end - -do - if ngx then - VAR_PHASES = { - set = true, - rewrite = true, - access = true, - content = true, - header_filter = true, - body_filter = true, - log = true - } - template.print = ngx.print or write - template.load = loadngx - prefix, var, capture, null, phase = ngx.config.prefix(), ngx.var, ngx.location.capture, ngx.null, ngx.get_phase - if VAR_PHASES[phase()] then - caching = enabled(var.template_cache) - end - else - template.print = write - template.load = loadlua - end - if _VERSION == "Lua 5.1" then - local context = { __index = function(t, k) - return t.context[k] or t.template[k] or _G[k] - end } - if jit then - loadchunk = function(view) - return assert(load(view, nil, nil, setmetatable({ template = template }, context))) - end - else - loadchunk = function(view) - local func = assert(loadstring(view)) - setfenv(func, setmetatable({ template = template }, context)) - return func - end - end - else - local context = { __index = function(t, k) - return t.context[k] or t.template[k] or _ENV[k] - end } - loadchunk = function(view) - return assert(load(view, nil, nil, setmetatable({ template = template }, context))) - end - end -end - -function template.caching(enable) - if enable ~= nil then caching = enable == true end - return caching -end - -function template.output(s) - if s == nil or s == null then return "" end - if type(s) == "function" then return template.output(s()) end - return tostring(s) -end - -function template.escape(s, c) - if type(s) == "string" then - if c then return gsub(s, "[}{\">/<'&]", CODE_ENTITIES) end - return gsub(s, "[\">/<'&]", HTML_ENTITIES) - end - return template.output(s) -end - -function template.new(view, layout) - assert(view, "view was not provided for template.new(view, layout).") - local render, compile = template.render, template.compile - if layout then - if type(layout) == "table" then - return setmetatable({ render = function(self, context) - local context = context or self - context.blocks = context.blocks or {} - context.view = compile(view)(context) - layout.blocks = context.blocks or {} - layout.view = context.view or "" - return layout:render() - end }, { __tostring = function(self) - local context = self - context.blocks = context.blocks or {} - context.view = compile(view)(context) - layout.blocks = context.blocks or {} - layout.view = context.view - return tostring(layout) - end }) - else - return setmetatable({ render = function(self, context) - local context = context or self - context.blocks = context.blocks or {} - context.view = compile(view)(context) - return render(layout, context) - end }, { __tostring = function(self) - local context = self - context.blocks = context.blocks or {} - context.view = compile(view)(context) - return compile(layout)(context) - end }) - end - end - return setmetatable({ render = function(self, context) - return render(view, context or self) - end }, { __tostring = function(self) - return compile(view)(self) - end }) -end - -function template.precompile(view, path, strip) - local chunk = dump(template.compile(view), strip ~= false) - if path then - local file = open(path, "wb") - file:write(chunk) - file:close() - end - return chunk -end - -function template.compile(view, key, plain) - assert(view, "view was not provided for template.compile(view, key, plain).") - if key == "no-cache" then - return loadchunk(template.parse(view, plain)), false - end - key = key or view - local cache = template.cache - if cache[key] then return cache[key], true end - local func = loadchunk(template.parse(view, plain)) - if caching then cache[key] = func end - return func, false -end - -function template.parse(view, plain) - assert(view, "view was not provided for template.parse(view, plain).") - if not plain then - view = template.load(view) - if byte(view, 1, 1) == 27 then return view end - end - local j = 2 - local c = {[[ -context=... or {} -local function include(v, c) return template.compile(v)(c or context) end -local ___,blocks,layout={},blocks or {} -]] } - local i, s = 1, find(view, "{", 1, true) - while s do - local t, p = sub(view, s + 1, s + 1), s + 2 - if t == "{" then - local e = find(view, "}}", p, true) - if e then - local z, w = escaped(view, s) - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - if z then - i = s - else - c[j] = "___[#___+1]=template.escape(" - c[j+1] = trim(sub(view, p, e - 1)) - c[j+2] = ")\n" - j=j+3 - s, i = e + 1, e + 2 - end - end - elseif t == "*" then - local e = find(view, "*}", p, true) - if e then - local z, w = escaped(view, s) - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - if z then - i = s - else - c[j] = "___[#___+1]=template.output(" - c[j+1] = trim(sub(view, p, e - 1)) - c[j+2] = ")\n" - j=j+3 - s, i = e + 1, e + 2 - end - end - elseif t == "%" then - local e = find(view, "%}", p, true) - if e then - local z, w = escaped(view, s) - if z then - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - i = s - else - local n = e + 2 - if sub(view, n, n) == "\n" then - n = n + 1 - end - local r = rpos(view, s - 1) - if i <= r then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, r) - c[j+2] = "]=]\n" - j=j+3 - end - c[j] = trim(sub(view, p, e - 1)) - c[j+1] = "\n" - j=j+2 - s, i = n - 1, n - end - end - elseif t == "(" then - local e = find(view, ")}", p, true) - if e then - local z, w = escaped(view, s) - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - if z then - i = s - else - local f = sub(view, p, e - 1) - local x = find(f, ",", 2, true) - if x then - c[j] = "___[#___+1]=include([=[" - c[j+1] = trim(sub(f, 1, x - 1)) - c[j+2] = "]=]," - c[j+3] = trim(sub(f, x + 1)) - c[j+4] = ")\n" - j=j+5 - else - c[j] = "___[#___+1]=include([=[" - c[j+1] = trim(f) - c[j+2] = "]=])\n" - j=j+3 - end - s, i = e + 1, e + 2 - end - end - elseif t == "[" then - local e = find(view, "]}", p, true) - if e then - local z, w = escaped(view, s) - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - if z then - i = s - else - c[j] = "___[#___+1]=include(" - c[j+1] = trim(sub(view, p, e - 1)) - c[j+2] = ")\n" - j=j+3 - s, i = e + 1, e + 2 - end - end - elseif t == "-" then - local e = find(view, "-}", p, true) - if e then - local x, y = find(view, sub(view, s, e + 1), e + 2, true) - if x then - local z, w = escaped(view, s) - if z then - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - i = s - else - y = y + 1 - x = x - 1 - if sub(view, y, y) == "\n" then - y = y + 1 - end - local b = trim(sub(view, p, e - 1)) - if b == "verbatim" or b == "raw" then - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - c[j] = "___[#___+1]=[=[" - c[j+1] = sub(view, e + 2, x) - c[j+2] = "]=]\n" - j=j+3 - else - if sub(view, x, x) == "\n" then - x = x - 1 - end - local r = rpos(view, s - 1) - if i <= r then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, r) - c[j+2] = "]=]\n" - j=j+3 - end - c[j] = 'blocks["' - c[j+1] = b - c[j+2] = '"]=include[=[' - c[j+3] = sub(view, e + 2, x) - c[j+4] = "]=]\n" - j=j+5 - end - s, i = y - 1, y - end - end - end - elseif t == "#" then - local e = find(view, "#}", p, true) - if e then - local z, w = escaped(view, s) - if i < s - w then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = sub(view, i, s - 1 - w) - c[j+2] = "]=]\n" - j=j+3 - end - if z then - i = s - else - e = e + 2 - if sub(view, e, e) == "\n" then - e = e + 1 - end - s, i = e - 1, e - end - end - end - s = find(view, "{", s + 1, true) - end - s = sub(view, i) - if s and s ~= "" then - c[j] = "___[#___+1]=[=[\n" - c[j+1] = s - c[j+2] = "]=]\n" - j=j+3 - end - c[j] = "return layout and include(layout,setmetatable({view=table.concat(___),blocks=blocks},{__index=context})) or table.concat(___)" - return concat(c) -end - -function template.render(view, context, key, plain) - assert(view, "view was not provided for template.render(view, context, key, plain).") - return template.print(template.compile(view, key, plain)(context)) -end - -return template diff --git a/website/backend/lor/resty/template/html.lua b/website/backend/lor/resty/template/html.lua deleted file mode 100755 index b3cbdfa..0000000 --- a/website/backend/lor/resty/template/html.lua +++ /dev/null @@ -1,51 +0,0 @@ -local template = require "resty.template" -local setmetatable = setmetatable -local escape = template.escape -local concat = table.concat -local pairs = pairs -local type = type - -local function tag(name, content, attr) - local r, a, content = {}, {}, content or attr - r[#r + 1] = "<" - r[#r + 1] = name - if attr then - for k, v in pairs(attr) do - if type(k) == "number" then - a[#a + 1] = escape(v) - else - a[#a + 1] = k .. '="' .. escape(v) .. '"' - end - end - if #a > 0 then - r[#r + 1] = " " - r[#r + 1] = concat(a, " ") - end - end - if type(content) == "string" then - r[#r + 1] = ">" - r[#r + 1] = escape(content) - r[#r + 1] = "" - else - r[#r + 1] = " />" - end - return concat(r) -end - -local html = { __index = function(_, name) - return function(attr) - if type(attr) == "table" then - return function(content) - return tag(name, content, attr) - end - else - return tag(name, attr) - end - end -end } - -template.html = setmetatable(html, html) - -return template.html diff --git a/website/backend/lor/resty/template/microbenchmark.lua b/website/backend/lor/resty/template/microbenchmark.lua deleted file mode 100755 index 068c23c..0000000 --- a/website/backend/lor/resty/template/microbenchmark.lua +++ /dev/null @@ -1,148 +0,0 @@ -local template = require "resty.template" - -local ok, new_tab = pcall(require, "table.new") -if not ok then - new_tab = function() return {} end -end - -local function run(iterations) - local gc, total, print, parse, compile, iterations, clock, format = collectgarbage, 0, ngx and ngx.say or print, template.parse, template.compile, iterations or 1000, os.clock, string.format - local view = [[ - ]] - - print(format("Running %d iterations in each test", iterations)) - - gc() - gc() - - local x = clock() - for _ = 1, iterations do - parse(view, true) - end - local z = clock() - x - print(format(" Parsing Time: %.6f", z)) - total = total + z - - gc() - gc() - - x = clock() - for _ = 1, iterations do - compile(view, nil, true) - template.cache = {} - end - z = clock() - x - print(format("Compilation Time: %.6f (template)", z)) - total = total + z - - compile(view, nil, true) - - gc() - gc() - - x = clock() - for _ = 1, iterations do - compile(view, 1, true) - end - z = clock() - x - print(format("Compilation Time: %.6f (template, cached)", z)) - total = total + z - - local context = { "Emma", "James", "Nicholas", "Mary" } - - template.cache = {} - - gc() - gc() - - x = clock() - for _ = 1, iterations do - compile(view, 1, true)(context) - template.cache = {} - end - z = clock() - x - print(format(" Execution Time: %.6f (same template)", z)) - total = total + z - - template.cache = {} - compile(view, 1, true) - - gc() - gc() - - x = clock() - for _ = 1, iterations do - compile(view, 1, true)(context) - end - z = clock() - x - print(format(" Execution Time: %.6f (same template, cached)", z)) - total = total + z - - template.cache = {} - - local views = new_tab(iterations, 0) - for i = 1, iterations do - views[i] = "

Iteration " .. i .. "

\n" .. view - end - - gc() - gc() - - x = clock() - for i = 1, iterations do - compile(views[i], i, true)(context) - end - z = clock() - x - print(format(" Execution Time: %.6f (different template)", z)) - total = total + z - - gc() - gc() - - x = clock() - for i = 1, iterations do - compile(views[i], i, true)(context) - end - z = clock() - x - print(format(" Execution Time: %.6f (different template, cached)", z)) - total = total + z - - local contexts = new_tab(iterations, 0) - - for i = 1, iterations do - contexts[i] = { "Emma", "James", "Nicholas", "Mary" } - end - - template.cache = {} - - gc() - gc() - - x = clock() - for i = 1, iterations do - compile(views[i], i, true)(contexts[i]) - end - z = clock() - x - print(format(" Execution Time: %.6f (different template, different context)", z)) - total = total + z - - gc() - gc() - - x = clock() - for i = 1, iterations do - compile(views[i], i, true)(contexts[i]) - end - z = clock() - x - print(format(" Execution Time: %.6f (different template, different context, cached)", z)) - total = total + z - print(format(" Total Time: %.6f", total)) -end - -return { - run = run -} \ No newline at end of file diff --git a/website/backend/lor/spec/cases/basic_spec.lua b/website/backend/lor/spec/cases/basic_spec.lua deleted file mode 100644 index 8d3e4e9..0000000 --- a/website/backend/lor/spec/cases/basic_spec.lua +++ /dev/null @@ -1,28 +0,0 @@ -expose("expose modules", function() - package.path = '../../lib/?.lua;' .. '../../?.lua;'.. './lib/?.lua;' .. package.path - _G.lor = require("lor.index") - _G.request = require("spec.cases.mock_request") - _G.response = require("spec.cases.mock_response") - - _G.json_view = function(t) - local cjson - pcall(function() cjson = require("cjson") end) - if not cjson then - print("\n[cjson should be installed...]\n") - else - if t.root then - t:remove_nested_property(t.root) - print("\n", cjson.encode(t.root), "\n") - else - t:remove_nested_property(t) - print("\n", cjson.encode(t), "\n") - end - end - end - - _G._debug = nil - pcall(function() _G._debug = require("lor.lib.debug") end) - if not _G._debug then - _G._debug = print - end -end) diff --git a/website/backend/lor/spec/cases/common_spec.lua b/website/backend/lor/spec/cases/common_spec.lua deleted file mode 100755 index e743c9f..0000000 --- a/website/backend/lor/spec/cases/common_spec.lua +++ /dev/null @@ -1,64 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - -describe("basic test for common usages", function() - it("use middleware should works.", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - count = 5 - end) - - app:use("/user/123", function(req, res, next) - count = 3 - next() - end) - - app:get("/user/:id/create", function(req, res, next) - count = 4 - end) - - req.path ="/user/123/create" - req.method = "get" - app:handle(req, res) - assert.is.equals(count, 5) - end) - - it("error middleware should work.", function() - local origin_error_msg, error_msg = "this is an error", "" - app:use("/user", function(req, res, next) - next() - end) - - app:get("/user/123/create", function(req, res, next) - next(origin_error_msg) -- let other handlers continue... - end) - - app:erroruse(function(err, req, res, next) - error_msg = err - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res) - assert.is.equals(error_msg, origin_error_msg) - end) -end) diff --git a/website/backend/lor/spec/cases/error_middleware_spec.lua b/website/backend/lor/spec/cases/error_middleware_spec.lua deleted file mode 100755 index 70852f0..0000000 --- a/website/backend/lor/spec/cases/error_middleware_spec.lua +++ /dev/null @@ -1,108 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - -describe("error middleware test:", function() - it("error middleware should stop the left error middlewares if has no `next`.", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:use("/user/123", function(req, res, next) - count = 3 - next() - end) - - app:get("/user/123/create", function(req, res, next) - count = 4 - error("an error occurs") - end) - - app:erroruse(function(err, req, res, next) - count = 5 - end) - - app:erroruse(function(err, req, res, next) - count = 100 - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res) - assert.is.equals(count, 5) - end) - - it("error middleware should continue the left error middlewares if has `next`.", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:use("/user/123", function(req, res, next) - count = 3 - next() - end) - - app:get("/user/123/create", function(req, res, next) - count = 4 - error("an error occurs") - end) - - app:erroruse(function(err, req, res, next) - count = 5 - next(err) - end) - - app:erroruse(function(err, req, res, next) - assert.is.truthy(err) - count = 100 - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res) - assert.is.equals(count, 100) - end) - - describe("if finall handler defined, it will always be executed", function() - it("error middleware should continue the left error middlewares if has `next`.", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:use("/user/123", function(req, res, next) - count = 3 - next() - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res, function(err) - count = 111 - end) - assert.is.equals(count, 111) - end) - end) -end) diff --git a/website/backend/lor/spec/cases/final_handler_spec.lua b/website/backend/lor/spec/cases/final_handler_spec.lua deleted file mode 100755 index 52c012c..0000000 --- a/website/backend/lor/spec/cases/final_handler_spec.lua +++ /dev/null @@ -1,178 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - --- remind: final handler is the last middleware that could be used to handle errors --- it will alwayes be executed but `err` object is not nil only when error occurs -describe("if finall handler defined, it will always be executed.", function() - it("the request has no execution", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:use("/user/123", function(req, res, next) - count = 3 - next() - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res, function(err) - count = 111 - end) - assert.is.equals(count, 111) - end) - - it("404! should reach the final handler", function() - local count = 1 - - app:use("/user", function(req, res, next) -- won't enter - count = 2 - next() - end) - - app:get("/user/123", function(req, res, next) -- won't enter - count = 4 - next() - end) - - req.path = "/user/123/create" -- won't match app:get("/user/123", function...) - req.method = "get" - app:handle(req, res, function(err) -- 404! not found error - assert.is_truthy(err) - if err then - count = 404 - end - end) - assert.is.equals(404, count) - end) -end) - - -describe("the request has one successful execution. final handler execs but `err` should be nil.", function() - it("test case 2", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:get("/user/123/create", function(req, res, next) - count = 4 - next() - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res, function(err) - assert.is_falsy(err) -- err should be nil - assert.is_true(req:is_found()) -- matched app:get("/user/123/create") - count = 222 -- - end) - assert.is.equals(count, 222) - end) -end) - -describe("the previous error middleware pass or not pass the `err` object.", function() - it("test case 1.", function() - local count = 1 - app:use("/user", function(req, res, next) - count = 2 - next() - end) - - app:erroruse(function(err, req, res, next) - count = 5 - end) - - req.path = "/user/123/create" - req.method = "get" - app:handle(req, res, function(err) - assert.is.equals(count, 5) -- not found: should match error middleware, so count is 5 - count = 444 - if err then - count = 333 - end - - assert.is.equals(count, 333) - end) - end) - - - it("test case 2.", function() - local count = 1 - - app:get("/user/123", function(req, res, next) - count = 4 - error("abc") - end) - - app:erroruse(function(err, req, res, next) - count = 5 - assert.is.equals(true, string.find(err, "abc")>0) - next("def") - end) - - app:erroruse(function(err, req, res, next) - count = 6 - assert.is.equals("def", err) - next("123") - end) - - req.path = "/user/123" - req.method = "get" - app:handle(req, res, function(err) - count = 333 - if err then - count = 222 - end - assert.is.equals(222, count) - end) - end) - - it("test case 3, when error occurs in `error middleware`, the process will jump to the final handler immediately.", function() - app:get("/user/123", function(req, res, next) - error("ERROR1") - end) - - -- error middleware 1 - app:erroruse(function(err, req, res, next) - local test_var = 1 / tonumber("error number") -- error occurs here - next(err .. "\nERROR2") -- won't be reached - end) - - -- error middleware 2 - -- won't be matched because an error `in error middleware` occurs before it - app:erroruse(function(err, req, res, next) - next(err .. "\nERROR3") - end) - - req.path = "/user/123" - req.method = "get" - app:handle(req, res, function(err) - assert.is.equals(true, string.find(err, "ERROR1") > 0) - assert.is.equals(nil, string.find(err, "ERROR2")) -- matched `error middleware1`, but error occured - assert.is.equals(nil, string.find(err, "ERROR3")) -- not matched `error middleware2` - assert.is.equals(true, string.find(err, "perform arithmetic on a nil value") > 0) - end) - end) -end) diff --git a/website/backend/lor/spec/cases/group_index_route_spec.lua b/website/backend/lor/spec/cases/group_index_route_spec.lua deleted file mode 100644 index dc657ef..0000000 --- a/website/backend/lor/spec/cases/group_index_route_spec.lua +++ /dev/null @@ -1,165 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - -describe("group index route: basic usages", function() - it("should be error when giving wrong params", function() - local flag = 0 - local test_router = lor:Router() - - assert.has_error(function() test_router:get() end, "params should not be nil or empty") - assert.has_error(function() test_router:get({}) end, "params should not be nil or empty") - - assert.has_error(function() test_router:get("/test") end, "it must be an function if there's only one param") - assert.has_error(function() test_router:get("/test", "abc") end) - end) - - it("uri should mathed", function() - local flag = 0 - - local test_router = lor:Router() - test_router:get(function(req, res, next) - flag = 1 - end) - - app:use("/test", test_router()) - - req.path = "/test" - req.method = "get" - app:handle(req, res) - assert.is.equals(1, flag) - end) - - it("uri should not mathed", function() - local flag = 0 - - local test_router = lor:Router() - test_router:get(function(req, res, next) - flag = 1 - end) - - app:use("/test", test_router()) - app:erroruse(function(err, req, res, next) -- 404 error - assert.is.truthy(err) - assert.is.equals(false, req:is_found()) - flag = 999 - end) - - req.path = "/test/" - req.method = "get" - app:handle(req, res) - assert.is.equals(999, flag) - end) -end) - - -describe("group index route: multi funcs", function() - it("array params", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:post({func1, func2, last_func}) - app:use("/test", test_router()) - - req.path = "/test" - req.method = "post" - app:handle(req, res) - assert.is.equals(3, flag) - end) - - it("unpacked params", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:put(func1, func2, last_func) - app:use("/test", test_router()) - - req.path = "/test" - req.method = "put" - app:handle(req, res) - assert.is.equals(3, flag) - end) - - it("mixed params, case1", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:get({func1, func2}, last_func) - app:use("/test", test_router()) - - req.path = "/test" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - end) - - it("mixed params, case2", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:put({func1}, func2, {last_func}) - app:use("/test", test_router()) - - req.path = "/test" - req.method = "put" - app:handle(req, res) - assert.is.equals(3, flag) - end) -end) diff --git a/website/backend/lor/spec/cases/group_router_spec.lua b/website/backend/lor/spec/cases/group_router_spec.lua deleted file mode 100755 index 49779db..0000000 --- a/website/backend/lor/spec/cases/group_router_spec.lua +++ /dev/null @@ -1,261 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - -describe("single group router middleware", function() - it("basic usage", function() - local count = 0 - local userRouter = lor:Router() - - userRouter:get("/find/:id", function(req, res, next) - count = 1 - next() - end) - - userRouter:post("/create/:id", function(req, res, next) - count = 2 - next() - end) - - app:use("/user", userRouter()) - - -- should not be reached, because `next` has no params and no error occurs - app:erroruse(function(err, req, res, next) - count = 3 - end) - - req.path = "/user/create/123" - req.method = "post" - app:handle(req, res) - assert.is.equals(2, count) - - req.path = "/user/find/123" - req.method = "get" - app:handle(req, res) - assert.is.equals(1, count) - end) - - - it("error middleware should work as normal", function() - local count = 0 - local errorMsg = "an error occurs." - local userRouter = lor:Router() - - userRouter:get("/find/:id", function(req, res, next) - count = 1 - error(errorMsg) - end) - - userRouter:post("/create/:id", function(req, res, next) - count = 2 - next(errorMsg) -- has one param, so this will pass to an error middleware - end) - - userRouter:post("/edit/:id", function(req, res, next) - count = 3 - end) - - app:use("/user", userRouter()) - - app:erroruse(function(err, req, res, next) - if err then -- double check - count = err - req.params.id = "11111111" - end - end) - - req.path = "/user/find/456" - req.method = "get" - app:handle(req, res) - assert.is.truthy(string.match(count, errorMsg)) - - req.path = "/user/create/123" - req.method = "post" - app:handle(req, res) - assert.is.truthy(string.match(count, errorMsg)) -- count contains errorMsg - - req.path = "/user/edit/987" - req.method = "post" - app:handle(req, res) - assert.is.equals(3, count) -- no error occurs - end) - - it("path variable parser should work", function() - local count = 0 - local errorMsg = "an error occurs." - local userRouter = lor:Router() - - userRouter:get("/find/:id", function(req, res, next) - count = 1 - error(errorMsg) - end) - - userRouter:post("/create/:id", function(req, res, next) - count = 2 - next(errorMsg) -- has one param, so this will pass to an error middleware - end) - - userRouter:post("/edit/:id", function(req, res, next) - count = 3 - end) - - app:use("/user", userRouter()) - - app:erroruse("/user", function(err, req, res, next) - --print("user error middleware", err) - --if err then -- double check - count = err - req.params.id = "22222" - --end - next(err) -- 继续传递,只会被下一个erroruse覆盖 - end) - - app:erroruse(function(err, req, res, next) - --print("common error middleware", err) - if err then -- double check - count = err - req.params.id = "11111111" - end - end) - - req.path = "/user/find/456" - req.method = "get" - app:handle(req, res) - assert.is.equals("11111111", req.params.id) - assert.is.truthy(string.match(count, errorMsg)) - - req.path = "/user/create/123" - req.method = "post" - app:handle(req, res) - assert.is.equals("11111111", req.params.id) - assert.is.truthy(string.match(count, errorMsg)) -- count contains errorMsg - - req.path = "/user/edit/987" - req.method = "post" - app:handle(req, res) - assert.is.equals("987", req.params.id) - assert.is.equals(3, count) - end) -end) - -describe("multi group router middleware", function() - it("basic usage", function() - local flag = "" - local userRouter = lor:Router() - local bookRouter = lor:Router() - - app:use(function(req, res, next) - flag = "first use" - req.params.flag = "origin value" - next() - end) - - userRouter:get("/find/:id", function(req, res, next) - flag = 1 - req.params.flag = 1 - next("error occurs") - end) - - userRouter:post("/create/:id", function(req, res, next) - flag = 2 - req.params.flag = 2 - next() - end) - - bookRouter:get("/view/:id", function(req, res, next) - flag = 3 - req.params.flag = 3 - error("common error") - req.params.flag = 33 - end) - - app:use("/user", userRouter()) -- must invoke before `erroruse` - app:use("/book", bookRouter()) -- must invoke before `erroruse` - - app:erroruse("/user", function(err, req, res, next) - --print("------------- user error m", err) - assert.is.truthy(err) - flag = "user_error_middleware" - req.params.flag = 111 - end) - - app:erroruse(function(err, req, res, next) - --print("------------- common error m", err) - flag = "common_error_middleware" - req.params.flag = 333 - assert.is.truthy(err) - end) - - req.path = "/user/create/123" - req.method = "post" - app:handle(req, res) - assert.is.equals(2, flag) - assert.is.equals(2, req.params.flag) - - req.path = "/user/find/123" - req.method = "get" - app:handle(req, res) - assert.is.equals("user_error_middleware", flag) - assert.is.equals(111, req.params.flag) - - req.path = "/book/view/999" - req.method = "get" - app:handle(req, res, function(err) - if err then - print(err) - end - -- not found path will be here - -- not processed error will be here - end) - assert.is.equals("common_error_middleware", flag) - assert.is.equals(333, req.params.flag) - end) -end) - -describe("'use' the same group router middleware", function() - it("basic usage", function() - local userRouter = lor:Router() - - local reach_first = false - local reach_second = false - - userRouter:get("/get", function(req, res, next) - reach_first = true - reach_second = true - end) - - app:use("/user", userRouter()) - app:use("/u", userRouter()) - - req.path = "/user/get" - req.method = "get" - app:handle(req, res) - assert.is.equals(true, reach_first) - - -- reset values - reach_first = false - reach_second = false - - req.path = "/u/get" - req.method = "get" - app:handle(req, res) - assert.is.equals(true, reach_second) - end) -end) diff --git a/website/backend/lor/spec/cases/mock_request.lua b/website/backend/lor/spec/cases/mock_request.lua deleted file mode 100755 index 5086e2a..0000000 --- a/website/backend/lor/spec/cases/mock_request.lua +++ /dev/null @@ -1,35 +0,0 @@ -local setmetatable = setmetatable - -local Request = {} - -function Request:new() - local body = {} -- body params - - local params = {} - - local instance = { - method = "", - query = {}, - params = {}, - body = body, - path = "", - url = "", - uri = "", - req_args = {}, - baseUrl = "", - found = false - } - setmetatable(instance, { __index = self }) - return instance -end - -function Request:is_found() - return self.found -end - -function Request:set_found(found) - self.found = found -end - - -return Request \ No newline at end of file diff --git a/website/backend/lor/spec/cases/mock_response.lua b/website/backend/lor/spec/cases/mock_response.lua deleted file mode 100755 index 424ddaa..0000000 --- a/website/backend/lor/spec/cases/mock_response.lua +++ /dev/null @@ -1,36 +0,0 @@ -local setmetatable = setmetatable - -local Response = {} - -function Response:new() - local instance = { - headers = {}, - body = '--default body. you should not see this by default--', - view = nil, - } - - setmetatable(instance, {__index = self}) - return instance -end - -function Response:json(data) - self:_send(data) -end - -function Response:send(text) - self:_send(text) -end - -function Response:_send(content) - print(content) -end - -function Response:setHeader(key, value) -end - -function Response:status(code) - self.http_status = code - return self -end - -return Response diff --git a/website/backend/lor/spec/cases/multi_route_spec.lua b/website/backend/lor/spec/cases/multi_route_spec.lua deleted file mode 100644 index b3b3b0f..0000000 --- a/website/backend/lor/spec/cases/multi_route_spec.lua +++ /dev/null @@ -1,254 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - -describe("multi route: mounted on `app`", function() - it("array param", function() - local flag = 0 - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = req.query.flag or 3 - end - app:get("/flag", {func1, func2, last_func}) - - app:erroruse(function(err, req, res, next) - assert.is.truthy(err) -- should not reach here. - flag = 999 - end) - - req.path = "/flag" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - - req.path = "/flag" - req.query = {flag=111} - req.method = "get" - app:handle(req, res) - assert.is.equals(111, flag) - end) - - it("unpacked params", function() - local flag = 0 - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = req.query.flag or 3 - end - app:get("/flag", func1, func2, last_func) - - app:erroruse(function(err, req, res, next) - assert.is.truthy(err) -- should not reach here. - flag = 999 - end) - - req.path = "/flag" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - - req.path = "/flag" - req.query = {flag=111} - req.method = "get" - app:handle(req, res) - assert.is.equals(111, flag) - end) -end) - -describe("multi route: mounted on `group router`", function() - it("array param", function() - local flag = 0 - - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = req.query.flag or 3 - end - test_router:get("/flag", {func1, func2, last_func}) - - app:use("/test", test_router()) - app:erroruse(function(err, req, res, next) - assert.is.truthy(err) -- should not reach here. - flag = 999 - end) - - req.path = "/test/flag" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - - req.path = "/test/flag" - req.query = {flag=111} - req.method = "get" - app:handle(req, res) - assert.is.equals(111, flag) - end) - - it("unpacked params", function() - local flag = 0 - - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = req.query.flag or 3 - end - test_router:get("/flag", func1, func2, last_func) - - app:use("/test", test_router()) - app:erroruse(function(err, req, res, next) - assert.is.truthy(err) -- should not reach here. - flag = 999 - end) - - req.path = "/test/flag" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - - req.path = "/test/flag" - req.query = {flag=111} - req.method = "get" - app:handle(req, res) - assert.is.equals(111, flag) - end) -end) - -describe("multi route: muixed funcs for group router", function() - it("mixed params, case1", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:put("mixed", {func1, func2}, last_func) - app:use("/test", test_router()) - - req.path = "/test/mixed" - req.method = "put" - app:handle(req, res) - assert.is.equals(3, flag) - end) - - it("mixed params, case2", function() - local flag = 0 - local test_router = lor:Router() - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - test_router:get("mixed", {func1}, func2, {last_func}) - app:use("/test", test_router()) - - req.path = "/test/mixed" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - end) -end) - -describe("multi route: muixed funcs for `app`", function() - it("mixed params, case1", function() - local flag = 0 - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local last_func = function(req, res, next) - flag = 3 - end - app:get("mixed", {func1, func2}, last_func) - - req.path = "/mixed" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, flag) - end) - - it("mixed params, case2", function() - local flag = 0 - local func1 = function(req, res, next) - flag = 1 - next() - end - local func2 = function(req, res, next) - flag = 2 - next() - end - local func3 = function(req, res, next) - flag = 3 - next() - end - local last_func = function(req, res, next) - flag = 4 - end - app:get("mixed", {func1}, func2, {func3}, last_func) - - req.path = "/mixed" - req.method = "get" - app:handle(req, res) - assert.is.equals(4, flag) - end) -end) diff --git a/website/backend/lor/spec/cases/node_id_spec.lua b/website/backend/lor/spec/cases/node_id_spec.lua deleted file mode 100644 index e86c9f2..0000000 --- a/website/backend/lor/spec/cases/node_id_spec.lua +++ /dev/null @@ -1,38 +0,0 @@ -before_each(function() - Trie = require("lor.lib.trie") - t = Trie:new() -end) - -after_each(function() - t = nil -end) - -function table_size(t) - local res = 0 - if t then - for _ in pairs(t) do - res = res + 1 - end - end - return res -end - -describe("node is should be unique", function() - it("test case 1", function() - local count = 100 - local nodes = {} - for i=1,count,1 do - local node = t:add_node(tostring(i)) - table.insert(nodes, node) - end - - assert.is.equals(count, #nodes) - assert.is.equals(count, table_size(nodes)) - - local node_map = {} - for i=1,count,1 do - node_map[nodes[i].id] = true - end - assert.is.equals(count, table_size(node_map)) - end) -end) diff --git a/website/backend/lor/spec/cases/not_found_spec.lua b/website/backend/lor/spec/cases/not_found_spec.lua deleted file mode 100755 index 769f13d..0000000 --- a/website/backend/lor/spec/cases/not_found_spec.lua +++ /dev/null @@ -1,125 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - -describe("not found test, error middleware and final handler should be reached correctly.", function() - it("test case 1", function() - local count = 0 - local errorMsg = "an error occurs." - - local userRouter = lor:Router() - userRouter:get("/find/:id", function(req, res, next) - count = 1 - error(errorMsg) - end) - app:use("/user", userRouter()) - - app:erroruse("/user", function(err, req, res, next) - count = err - req.params.id = "2222" - next(err) - end) - - app:erroruse(function(err, req, res, next) - count = err - req.params.id = "1111" - end) - - req.path = "/user/find/456" - req.method = "get" - app:handle(req, res) - assert.is.equals(req.params.id, "1111") - assert.is.equals(true, string.find(count, errorMsg) > 1) - end) - - it("test case 2", function() - local count = 0 - local errorMsg = "an error occurs." - - local userRouter = lor:Router() - userRouter:get("/find/:id", function(req, res, next) - count = 1 - error(errorMsg) - end) - app:use("/user", userRouter()) - - app:erroruse("/user", function(err, req, res, next) - count = err - req.params.id = "2222" - next(err) - end) - - app:erroruse(function(err, req, res, next) - count = "stop exec final handler" - req.params.id = "1111" - -- next(err) -- not invoke it, the final handler will not be reached! - end) - - req.params.id = nil --empty it - req.path = "/user/notfound" - req.method = "post" - app:handle(req, res, function(err) - if err then - count = "not found error catched" - end - end) - - assert.is.equals(404, res.http_status) - assert.is.equals(req.params.id, "1111") - assert.is.equals("stop exec final handler", count) - end) - - it("test case 3", function() - local count = 0 - local errorMsg = "an error occurs." - - local userRouter = lor:Router() - userRouter:get("/find/:id", function(req, res, next) - count = 1 - error(errorMsg) - end) - app:use("/user", userRouter()) - - app:erroruse("/user", function(err, req, res, next) - count = err - req.params.id = "2222" - next(err) - end) - - app:erroruse(function(err, req, res, next) - count = "stop exec final handler" - req.params.id = "1111" - next(err) -- invoke it, the final handler will be reached! - end) - - req.params.id = nil --empty it - req.path = "/notfound" - req.method = "post" - app:handle(req, res, function(err) - req.params.id = "3333" - if err then - count = "not found error catched" - end - end) - --print(app.router.trie:gen_graph()) - assert.is.equals(404, res.http_status) - assert.is.equals(req.params.id, "3333") - assert.is.equals("not found error catched", count) - end) -end) diff --git a/website/backend/lor/spec/cases/path_params_spec.lua b/website/backend/lor/spec/cases/path_params_spec.lua deleted file mode 100755 index 110d8c6..0000000 --- a/website/backend/lor/spec/cases/path_params_spec.lua +++ /dev/null @@ -1,181 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = true - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - - -describe("test about variables parsed from path", function() - describe("path variables should be correct after parsed", function() - it("test case 1.", function() - app:use("/user", function(req, res, next) - req.params.default_var = "user" - next() - end) - - app:get("/user/:id/visit", function(req, res, next) - next() - end) - - req.path = "/user/3/visit" - req.method = "get" - app:handle(req, res) - - assert.is.equals('3', req.params.id) - assert.is.equals("user", req.params.default_var) - end) - - it("test case 2.", function() - app:use("/user", function(req, res, next) - assert.is.equals("3", req.params.id) - next() - end) - - app:get("/user/:id/visit", function(req, res, next) - req.params.id = 5 - next() - end) - - req.path = "/user/3/visit" - req.method = "get" - - app:handle(req, res) - assert.is.equals(5, req.params.id) - end) - - it("test case 3.", function() - app:get("/user/:id/visit", function(req, res, next) - error("error occurs") - req.params.id = '2' - end) - - app:erroruse("/user/:id/visit", function(err, req, res, next) - assert.is_not_nil(err) - req.params.id = 'error' - end) - - req.path = "/user/3/visit" - req.method = "get" - - app:handle(req, res) - assert.is.equals('error', req.params.id) - end) - - it("test case 4.", function() - app:use("/user", function(req, res, next) - req.params.id = '1' - next() - req.params.id = 'return' - end) - - app:get("/user/:id/visit", function(req, res, next) - error("error occurs") - req.params.id = '2' - end) - - app:erroruse("/user/:id/visit", function(err, req, res, next) - req.params.id = 'error' - end) - - req.path = "/user/3/visit" - req.method = "get" - - app:handle(req, res) - assert.is.equals('return', req.params.id) - end) - - it("test case 5.", function() - app:use("/user", function(req, res, next) - req.params.id = '1' - next() - req.params.id = 'return' - end) - - app:get("/user/:id/visit", function(req, res, next) - error("error occurs") - req.params.id = '2' - end) - - app:erroruse("/user/:id/visit", function(err, req, res, next) - req.params.id = 'error' - end) - - req.path = "/user/3/visit" - req.method = "get" - app:handle(req, res, function(err) - req.params.id = "from final handler" - end) - assert.is.equals('return', req.params.id) - end) - end) - - describe("path variables should be correctly parsed when the next request comes", function() - it("test case 1.", function() - app:use("/todo", function(req, res, next) - if req.params.id == "33" then - req.params.id = '3' - elseif req.params.id == "44" then - req.params.id = "4" - elseif req.params.id == "55" then - req.params.id = "5" - end - next() - end) - - app:post("/todo/delete/:id", function(req, res, next) - --print(req.params.id) - end) - - req.path = "/todo/delete/33" - req.method = "post" - app:handle(req, res) - assert.is.equals('3', req.params.id) - - req.path = "/todo/delete/44" - req.method = "post" - app:handle(req, res) - assert.is.equals('4', req.params.id) - - req.url = "/todo/delete/55" - req.path = req.url - req.method = "post" - app:handle(req, res) - assert.is.equals('5', req.params.id) - end) - - it("test case 2.", function() - app:use("/todo", function(req, res, next) - next() - end) - - app:post("/todo/view/:id/:name", function(req, res, next) - end) - - req.path = "/todo/view/44/two" - req.method = "post" - app:handle(req, res) - assert.is.equals('44', req.params.id) - assert.is.equals('two', req.params.name) - - req.path = "/todo/view/55/three" - req.method = "post" - app:handle(req, res) - assert.is.equals('55', req.params.id) - assert.is.equals('three', req.params.name) - end) - end) -end) diff --git a/website/backend/lor/spec/cases/path_pattern_1_spec.lua b/website/backend/lor/spec/cases/path_pattern_1_spec.lua deleted file mode 100755 index c4b3ba4..0000000 --- a/website/backend/lor/spec/cases/path_pattern_1_spec.lua +++ /dev/null @@ -1,113 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = false - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() - - count = 0 - - app:use("/", function(req, res, next) - count = 1 - next() - end) - - app:use("/user/", function(req, res, next) - count = 2 - next() - end) - app:use("/user/:id/view", function(req, res, next) - count = 3 - next() - end) - app:get("/user/123/view", function(req, res, next) - count = 4 - next() - end) - - app:post("/book" , function(req, res, next) - count = 5 - next() - end) - - local testRouter = lor:Router() -- 一个新的router,区别于主router - testRouter:get("/get", function(req, res, next) - count = 6 - next() - end) - testRouter:post("/foo/bar", function(req, res, next) - count = 7 - next() - end) - app:use("/test", testRouter()) - - app:erroruse(function(err, req, res, next) - count = 999 - end) -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil -end) - -describe("next function usages test", function() - it("test case 1", function() - req.path = "/user/123/view" - req.method = "get" - app:handle(req, res, function(err) - assert.is_true(req:is_found()) - end) - - assert.is.equals(4, count) - assert.is.equals(nil, req.params.id) - end) - - it("test case 2", function() -- route found - app:conf("strict_route", false) -- 设置为非严格匹配 - req.path = "/user/123/view/" -- match app:get("/user/123/view", fn()) - req.method = "get" - app:handle(req, res, function(err) - assert.is_true(req:is_found()) - end) - - assert.is.equals(4, count) - assert.is.equals(nil, req.params.id) - end) - - it("test case 3", function() - req.path = "/book" - req.method = "get" - app:handle(req, res) - - assert.is.equals(999, count) - assert.is_nil( req.params.id) - - req.method = "post" -- post match - app:handle(req, res, function(err) - assert.is_true(req:is_found()) - end) - - assert.is.equals(5, count) - assert.is_nil( req.params.id) - end) - - it("test case 4", function() - req.path = "/notfound" - req.method = "get" - app:handle(req, res, function(err) - assert.is_not_true(req:is_found()) - assert.is_nil(err) - end) - - assert.is.equals(999, count) - assert.is_nil(req.params.id) - end) -end) diff --git a/website/backend/lor/spec/cases/path_pattern_2_spec.lua b/website/backend/lor/spec/cases/path_pattern_2_spec.lua deleted file mode 100755 index e6514f7..0000000 --- a/website/backend/lor/spec/cases/path_pattern_2_spec.lua +++ /dev/null @@ -1,70 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = false - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() - - count = 0 - match = 1 - - app:get("/all", function(req, res, next) - count = 1 - end) - - local testRouter = lor:Router() - testRouter:get("/all", function(req, res, next) - count = 6 - match = 2 - next() - end) - testRouter:get("/find/:type", function(req, res, next) - count = 7 - next() - end) - app:use("/test", testRouter()) - -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil - match = nil -end) - -describe("path match test", function() - it("test case 1", function() - req.path = "/test/all" - req.method = "get" - app:handle(req, res) - assert.is.equals(2, match) - assert.is.equals(6, count) - end) - - it("test case 2", function() - req.path = "/test/find/all" - req.method = "get" - app:handle(req, res) - assert.is.equals(1, match) -- should not match "/test/all" - assert.is.equals(7, count) - end) - - it("test case 3", function() - req.path = "/test/find/all/1" - req.method = "get" - app:erroruse(function(err, req, res, next) -- 404 error - assert.is.truthy(err) - assert.is.equals(false, req:is_found()) - end) - app:handle(req, res) - assert.is.equals(1, match) - assert.is.equals(0, count) - end) -end) diff --git a/website/backend/lor/spec/cases/path_pattern_3_spec.lua b/website/backend/lor/spec/cases/path_pattern_3_spec.lua deleted file mode 100755 index dc96f2d..0000000 --- a/website/backend/lor/spec/cases/path_pattern_3_spec.lua +++ /dev/null @@ -1,53 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = false - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() - - count = 0 - match = 1 - - app:get("/hello", function(req, res, next) - count = 1 - match = 2 - end) - - local testRouter = lor:Router() - testRouter:get("/hello", function(req, res, next) - match = 3 - end) - - app:use("/test", testRouter()) -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil - match = nil -end) - - -describe("path match test", function() - it("test case 1", function() - req.path = "/test/hello" - req.method = "get" - app:handle(req, res) - assert.is.equals(3, match) - assert.is.equals(0, count) - end) - - it("test case 2", function() - req.path = "/hello" - req.method = "get" - app:handle(req, res) - assert.is.equals(2, match) - end) -end) diff --git a/website/backend/lor/spec/cases/uri_char_spec.lua b/website/backend/lor/spec/cases/uri_char_spec.lua deleted file mode 100644 index 72d8606..0000000 --- a/website/backend/lor/spec/cases/uri_char_spec.lua +++ /dev/null @@ -1,45 +0,0 @@ -before_each(function() - lor = _G.lor - app = lor({ - debug = false - }) - Request = _G.request - Response = _G.response - req = Request:new() - res = Response:new() - - flag = 0 -end) - -after_each(function() - lor = nil - app = nil - Request = nil - Response = nil - req = nil - res = nil - match = nil -end) - -describe("uri should support `-`", function() - it("test case 1", function() - req.path = "/a-b-c" - req.method = "get" - app:get("/a-b-c", function(req, res, next) - flag = 1 - end) - app:handle(req, res) - assert.is.equals(1, flag) - end) - - it("test case 2", function() - req.path = "/a_-b-/cde/-f" - req.method = "get" - app:get("/a_-b-/cde/-f", function(req, res, next) - flag = 2 - end) - app:handle(req, res) - assert.is.equals(2, flag) - end) - -end) diff --git a/website/backend/lor/spec/trie/basic_spec.lua b/website/backend/lor/spec/trie/basic_spec.lua deleted file mode 100644 index 64387a4..0000000 --- a/website/backend/lor/spec/trie/basic_spec.lua +++ /dev/null @@ -1,27 +0,0 @@ -expose("expose modules", function() - package.path = '../../lib/?.lua;' .. '../../?.lua;'.. './lib/?.lua;' .. package.path - _G.Trie = require("lor.lib.trie") - _G.Node = require("lor.lib.node") - - _G.json_view = function(t) - local cjson - pcall(function() cjson = require("cjson") end) - if not cjson then - print("\n[cjson should be installed...]\n") - else - if t.root then - t:remove_nested_property(t.root) - print("\n", cjson.encode(t.root), "\n") - else - t:remove_nested_property(t) - print("\n", cjson.encode(t), "\n") - end - end - end - - _G._debug = nil - pcall(function() _G._debug = require("lor.lib.debug") end) - if not _G._debug then - _G._debug = print - end -end) diff --git a/website/backend/lor/spec/trie/complex_cases_spec.lua b/website/backend/lor/spec/trie/complex_cases_spec.lua deleted file mode 100644 index 21d0bdd..0000000 --- a/website/backend/lor/spec/trie/complex_cases_spec.lua +++ /dev/null @@ -1,96 +0,0 @@ -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - -describe("complex use cases: ", function() - it("should match the correct colon node.", function() - local n1 = t:add_node("/a/b/c/e") - local colon_n1 = t:add_node("/a/b/:name/d") - - local m1 = t:match("/a/b/c/d") - --print(t:gen_graph()) - assert.are.same(colon_n1, m1.node) - end) - - it("same prefix while different suffix.", function() - local n1 = t:add_node("/a/b/c/e/f") - local colon_n1 = t:add_node("/a/b/:name/d/g") - local colon_n2 = t:add_node("/a/b/:name/e/f") - - local m1 = t:match("/a/b/c/d/g") - assert.are.same(colon_n1, m1.node) - - local m2 = t:match("/a/b/other/e/f") - assert.are.same(colon_n2, m2.node) - end) - - it("confused prefix node", function() - local n1 = t:add_node("/people/:id") - local n2 = t:add_node("/people/list/:id") - local n3 = t:add_node("/people/list") - - local m1 = t:match("/people/123") - assert.are.same(n1, m1.node) - - local m2 = t:match("/people/list") - assert.are.same(n3, m2.node) - - local m3 = t:match("/people/list/123") - assert.are.same(n2, m3.node) - - local m4 = t:match("/people/list/123/456") - assert.are.same(nil, m4.node) - end) - - it("should succeed to match colon & common node.", function() - local n1 = t:add_node("/user") - local n2 = t:add_node("/user/123") - local n3 = t:add_node("/user/:id/create") - - local m1 = t:match("/user/123/create") - assert.are.same(n3, m1.node) -- should not match n2 - assert.is.equals("123", m1.params["id"]) - end) - - it("a complicated example.", function() - local n1 = t:add_node("/a/:p1/:p2/:p3/g") - local n2 = t:add_node("/a/:p1/:p2/f/h") - local n3 = t:add_node("/a/:p1/:p2/f") - local n4 = t:add_node("/a/:p1/e") - local n5 = t:add_node("/a/:p1/c/o") - local n6 = t:add_node("/a/d/c") - local n7 = t:add_node("/a/m") - - local m1 = t:match("/a/d/c/o") - local m2 = t:match("/a/n/e/f") - local m3 = t:match("/a/n/e/f/g") - - assert.are.same(n5, m1.node) - assert.is.equals("d", m1.params["p1"]) - - assert.are.same(n3, m2.node) - assert.is.equals("n", m2.params["p1"]) - assert.is.equals("e", m2.params["p2"]) - - assert.are.same(n1, m3.node) - assert.is.equals("n", m3.params["p1"]) - assert.is.equals("e", m3.params["p2"]) - assert.is.equals("f", m3.params["p3"]) - - end) -end) - - - - diff --git a/website/backend/lor/spec/trie/debug_cases.lua b/website/backend/lor/spec/trie/debug_cases.lua deleted file mode 100644 index c08fb64..0000000 --- a/website/backend/lor/spec/trie/debug_cases.lua +++ /dev/null @@ -1,49 +0,0 @@ -setup(function() - _G.LOR_FRAMEWORK_DEBUG = false -end) - -teardown(function() -end) - -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - - - -describe("for debug cases: ", function() - it("a complicated example.", function() - local n1 = t:add_node("/a/:p1/:p2/:p3/g") - local n2 = t:add_node("/a/:p1/:p2/f/h") - local n3 = t:add_node("/a/:p1/:p2/f") - local n4 = t:add_node("/a/:p1/e") - local n5 = t:add_node("/a/:p1/c/o") - local n6 = t:add_node("/a/d/c") - local n7 = t:add_node("/a/m") - - local m3 = t:match("/a/n/e/f/g") - --json_view(t) - --print(t:gen_graph()) - - assert.are.same(n1, m3.node) - assert.is.equals("n", m3.params["p1"]) - assert.is.equals("e", m3.params["p2"]) - assert.is.equals("f", m3.params["p3"]) - - end) -end) - - - - diff --git a/website/backend/lor/spec/trie/define_node_spec.lua b/website/backend/lor/spec/trie/define_node_spec.lua deleted file mode 100644 index 048166d..0000000 --- a/website/backend/lor/spec/trie/define_node_spec.lua +++ /dev/null @@ -1,315 +0,0 @@ -setup(function() - _G.LOR_FRAMEWORK_DEBUG = true -end) - -teardown(function() -end) - -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - -describe("objects check: ", function() - it("objects or modules should not be nil.", function() - assert.is.truthy(Trie) - assert.is.truthy(Node) - assert.is.truthy(t) - assert.is.truthy(t1) - assert.is.truthy(t2) - end) -end) - -describe("add node: ", function() - it("wrong patterns with `/` to add.", function() - assert.has_error(function() - t1:add_node("//") - end) - assert.has_error(function() - t1:add_node("///") - end) - assert.has_error(function() - t1:add_node("/a/b//") - end) - assert.has_error(function() - t1:add_node("//a/b/") - end) - assert.has_error(function() - t1:add_node("/a//b/") - end) - assert.has_error(function() - t1:add_node("/a///b/") - end) - end) - - it("wrong patterns with spaces to add.", function() - assert.has_error(function() - t1:add_node(" / / ") - end) - - assert.has_error(function() - t1:add_node("/ /") - end) - end) - - it("correct pattern to add.", function() - assert.has_no_error(function() - t1:add_node(" ") -- slim to "" - t1:add_node("/") - t1:add_node("") - t1:add_node("/a") - t1:add_node("/a/b") - t1:add_node("/a/b/c/") - end) - - assert.has_no.error(function() - t1:add_node(" ") - end) - end) - - it("these patterns should get same node.", function() - local node = t1:add_node("/") - - assert.is.equals(node, t1:add_node("/")) - assert.is.equals(node, t1:add_node("")) - assert.is.equals(t1:add_node("/"), t1:add_node("")) - assert.is.equals(node.parent, t1.root) - - assert.is_not.equals(node, t2:add_node("/")) - assert.is_not.equals(node, t2:add_node("")) - end) - - it("spaces in patterns are trimed.", function() - local node = t:add_node("/") - assert.is.equals(node, t:add_node(" ")) - assert.is.equals(node, t:add_node(" ")) - assert.is.equals(node, t:add_node(" /")) - assert.is.equals(node, t:add_node(" / ")) - - end) -end) - -describe("illegal & legal path: ", function() - it("wrong path", function() - assert.has_error(function() - t:add_node("/#+") - end) - assert.has_error(function() - t:add_node(":+abc") - end) - assert.has_error(function() - t:add_node(":&abc") - end) - - assert.has_error(function() - t:add_node(":abc*") - end) - - end) - it("correct path", function() - assert.has_no_error(function() - t:add_node(":abc") - end) - assert.has_no_error(function() - t:add_node("abc") - end) - assert.has_no_error(function() - t:add_node("/abc") - end) - end) -end) - -describe("node's name: ", function() - it("check names", function() - local node = t1:add_node("/") - assert.is.equals(node.name, "") - end) -end) - -describe("parent/children relation: ", function() - it("use case 1.", function() - local node = t1:add_node("/a/b") - assert.is.equals(node.name, "") - assert.is.equals(node.pattern, "/a/b") - - assert.is.equals(node, t1:add_node("/a/b")) - assert.is_not.equals(node, t1:add_node("a/b/")) - assert.is_not.equals(node, t1:add_node("/a/b/")) - assert.is.equals(t1:add_node("/a/b/"), t1:add_node("a/b/")) - - parent = t1:add_node("/a") - assert.is.equals(node.parent, parent) - assert.is_not.equals(parent.varyChild, node) - assert.is.equals(parent:find_child("b"), node) - child = t1:add_node("/a/b/c") - assert.is.equals(child.parent, node) - assert.is.equals(node:find_child("c"), child) - - assert.has_error(function() - t1:add_node("/a//b") - end) - end) - - it("use case 2.", function() - local root = t.root - - local slash_level = t:add_node("/") - local level0 = t:add_node("/00") - local level1 = t:add_node("/01") - local level2 = t:add_node("/02") - - local level0_0 = t:add_node("/00/0") - local level0_1 = t:add_node("/00/1") - local level0_2 = t:add_node("/00/2") - - local level1_0 = t:add_node("/01/0") - local level1_1 = t:add_node("/01/1") - local level1_2 = t:add_node("/01/2") - - local level2_0 = t:add_node("/02/0") - local level2_1 = t:add_node("/02/1") - local level2_2 = t:add_node("/02/2") - - local level0_0_0 = t:add_node("/00/0/0") - local level0_0_1 = t:add_node("/00/0/1") - local level0_0_2 = t:add_node("/00/0/2") - - assert.is.equals(root.name, "") - assert.is.equals(root.pattern, "") - - assert.is.equals(slash_level.name, "") - assert.is.equals(slash_level.pattern, "/") - assert.is.equals(level0.name, "") - assert.is.equals(level0.pattern, "/00") - - assert.are.same(slash_level.parent, level1.parent) - assert.are.same(level0.parent, level1.parent) - assert.are.same(level1.parent, level2.parent) - - assert.is.equals(root, level0.parent) - assert.is.equals(root, level1.parent) - assert.is.equals(root, level2.parent) - - assert.is.equals(level0, level0_0.parent) - assert.is.equals(level0_0.parent, level0_1.parent) - assert.is.equals(level1, level1_0.parent) - assert.is.equals(level1_0.parent, level1_1.parent) - - assert.is.equals(root, level0_0_0.parent.parent.parent) - assert.is.equals(level0, level0_0_0.parent.parent) - end) -end) - -describe("colon child define: ", function() - it("should failed to define conflict node.", function() - local root = t.root - - local slash_level = t:add_node("/") - local level0 = t:add_node("/00") - - t:add_node("/00/0") - t:add_node("/00/0/:0") - - assert.has_error(function() - t:add_node("/00/0/:1") - end) - - assert.has_error(function() - t:add_node("/00/0/:01") - end) - - assert.has_no_error(function() - t:add_node("/00/0/absolute") - end) - end) - - it("should succeed to define not conflict nodes.", function() - local root = t.root - - local slash_level = t:add_node("/") - local level0 = t:add_node("/00") - - t:add_node("/00/0") - t:add_node("/00/0/:0") - - assert.has_no_error(function() - t:add_node("/00/0/absolute") - end) - - assert.has_no_error(function() - t:add_node("/00/0/123") - end) - - assert.has_no_error(function() - t:add_node("/00/0/123/456") - end) - end) -end) - -describe("shadow child define: ", function() - it("should failed to define conflict node.", function() - local level0_0_0 = t:add_node("/00/0/:0") - local level0_0_0_shadow = t:add_node("/00/0/:0") - local level0_0_0_shadow2 = t:add_node("/00/0/:0") - assert.is.equals(level0_0_0, level0_0_0_shadow) - assert.is.equals(level0_0_0_shadow, level0_0_0_shadow2) - end) -end) - -describe("regex node define: ", function() - it("should failed to define error regex node.", function() - assert.has_error(function() - t:add_node("/a/:(^abc)") - end) - assert.has_error(function() - t:add_node("/a/(^abc)") - end) - assert.has_error(function() - t:add_node("/a/:abc(^abc") - end) - assert.has_error(function() - t:add_node("/a/:abc^abc)") - end) - end) - it("should succeed to define regex node.", function() - assert.has_no_error(function() - t:add_node("/a/:b(^abc)") - end) - assert.has_no_error(function() - t:add_node("/a/b/:c(^abc)") - end) - - - local n1 = t:add_node("/a/:b(^abc)") - assert.is.equals("^abc", n1.regex) - end) -end) - - -describe("just for dev, print json/tree : ", function() - it("case 1.", function() - local root = t.root - - local slash_level = t:add_node("/") - local level0 = t:add_node("/00") - local level0_0 = t:add_node("/00/0") - - local level0_0_1 = t:add_node("/00/0/1") - - local level0_0_0 = t:add_node("/00/0/:0") - local level0_0_0_shadow = t:add_node("/00/0/:0") - assert.is.equals(level0_0_0, level0_0_0_shadow) - - end) -end) - diff --git a/website/backend/lor/spec/trie/find_node_spec.lua b/website/backend/lor/spec/trie/find_node_spec.lua deleted file mode 100644 index 84d698c..0000000 --- a/website/backend/lor/spec/trie/find_node_spec.lua +++ /dev/null @@ -1,162 +0,0 @@ -setup(function() - _G.LOR_FRAMEWORK_DEBUG = false -end) - -teardown(function() -end) - -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - -describe("path match: ", function() - it("should succeed to match colon node.", function() - local n1 = t:add_node("/a/:name") - - local m1 = t:match("/a/b") - assert.are.same(n1, m1.node) - local m2 = t:match("/a/demo") - assert.are.same(n1, m2.node) - assert.is.equals("demo", m2.params.name) - - t.strict_route = false - local m3 = t:match("/a/mock/") - assert.are.same(n1, m3.node) - assert.is.equals("mock", m3.params["name"]) - - t.strict_route = true - m3 = t:match("/a/mock/") - assert.are.same(nil, m3.node) - end) -end) - -describe("path matched pipeline: ", function() - it("should get correct pipeline.", function() - local n0 = t:add_node("/a") - local n1 = t:add_node("/a/b") - local n2 = t:add_node("/a/b/c") - - local m1 = t:match("/a/b/c") - assert.are.same(n2, m1.node) - - local p1 = m1.pipeline - assert.is.equals(4, #m1.pipeline) - assert.is.equals(t.root.id, p1[1].id) - assert.is.equals(n0.id, p1[2].id) - assert.is.equals(n1.id, p1[3].id) - assert.is.equals(n2.id, p1[4].id) - end) - - it("slash node not included in pipeline.", function() - local slash_node = t:add_node("/") - local n0 = t:add_node("/a") - local n1 = t:add_node("/a/b") - local n2 = t:add_node("/a/b/c") - - local m1 = t:match("/a/b/c") -- won't match slash_node - assert.are.same(n2, m1.node) - - local p1 = m1.pipeline - assert.is_not.equals(5, #m1.pipeline) - assert.is.equals(4, #m1.pipeline) - for i, v in ipairs(p1) do - assert.is_not.equals(slash_node.id, v.id) - end - end) - - it("pipeline contains the right parent node.", function() - local n1 = t:add_node("/a/b/c") - - local m1 = t:match("/a/b/c") - assert.are.same(n1, m1.node) - - local p1 = m1.pipeline - assert.is.equals(4, #m1.pipeline) - assert.is.equals(t.root.id, p1[1].id) - assert.is.equals(n1.parent.parent.id, p1[2].id) - assert.is.equals(n1.parent.id, p1[3].id) - assert.is.equals(n1.id, p1[4].id) - end) - - it("children pipelines should contain same parents node.", function() - local n1 = t:add_node("/a/b/c") - local colon_n1 = t:add_node("/a/b/:name") - - local m1 = t:match("/a/b/c") - assert.are.same(n1, m1.node) - - local m2 = t:match("/a/b/sumory") - assert.are.same(colon_n1, m2.node) - - local p1 = m1.pipeline - assert.is.equals(4, #m1.pipeline) - assert.is.equals(t.root.id, p1[1].id) - assert.is.equals(n1.parent.parent.id, p1[2].id) - assert.is.equals(n1.parent.id, p1[3].id) - assert.is.equals(n1.id, p1[4].id) - - local p2 = m2.pipeline - assert.is.equals(4, #m2.pipeline) - assert.is.equals(t.root.id, p2[1].id) - assert.is.equals(colon_n1.parent.parent.id, p2[2].id) - assert.is.equals(colon_n1.parent.id, p2[3].id) - assert.is.equals(colon_n1.id, p2[4].id) - - assert.is.equals(p1[1].id, p2[1].id) - assert.is.equals(p1[2].id, p2[2].id) - assert.is.equals(p1[3].id, p2[3].id) - assert.is_not.equals(p1[4].id, p2[4].id) - end) -end) - - -describe("use cases that are hard to understand: ", function() - it("absolute & colon node math.", function() - local n1 = t:add_node("/a/b/c") - local colon_n1 = t:add_node("/a/b/:name") - - local m1 = t:match("/a/b/c") - assert.are.same(n1, m1.node) - - local m2 = t:match("/a/b/sumory") - assert.are.same(colon_n1, m2.node) - - end) - - it("confused prefix node", function() - local n1 = t:add_node("/people/:id") - local n2 = t:add_node("/people/list/:id") - - local m1 = t:match("/people/1") - assert.are.same(n1, m1.node) - local m11 = t:match("/people/abc") - assert.are.same(n1, m11.node) - - local m2 = t:match("/people/abc/123") - assert.are.same(nil, m2.node) - - local m3 = t:match("/people/list/123") - assert.are.same(n2, m3.node) - end) - - it("children pipelines should contain same parents node.", function() - local n1 = t:add_node("/a/b/c") - local colon_n1 = t:add_node("/a/b/:name") - - local m1 = t:match("/a/b/c") - assert.are.same(n1, m1.node) - end) -end) - - diff --git a/website/backend/lor/spec/trie/handle_spec.lua b/website/backend/lor/spec/trie/handle_spec.lua deleted file mode 100644 index bba5c9d..0000000 --- a/website/backend/lor/spec/trie/handle_spec.lua +++ /dev/null @@ -1,68 +0,0 @@ -setup(function() - _G.LOR_FRAMEWORK_DEBUG = false -end) - -teardown(function() -end) - -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - -describe("`handler` test cases: ", function() - it("should succeed to define handlers.", function() - local n1 = t:add_node("/a") - local m1 = t:add_node("/a/b") - local m2 = t:add_node("/a/c") - local m3 = t:add_node("/a/:name") - - n1:handle("get", function(req, res, next) end) - assert.is.equals(1, #n1.handlers["get"]) - - n1:handle("post", function(req, res, next) end) - assert.is.equals(1, #n1.handlers["post"]) - - n1:handle("put", function(req, res, next) end, function(req, res, next) end, function(req, res, next) end) - assert.is.equals(3, #n1.handlers["put"]) - - n1:handle("DELETE", {function(req, res, next) end, function(req, res, next) end}) - assert.is.equals(2, #n1.handlers["delete"]) - - m2:handle("get", function(req, res, next) end) - assert.is.equals(1, #m2.handlers["get"]) - end) - - it("should failed to define handlers.", function() - local n1 = t:add_node("/a") - - assert.has_error(function() - n1:handle("getabc", function(req, res, next) end) -- wrong `method` name - end) - - assert.has_error(function() - n1:handle("get", {}) - end) - - assert.has_error(function() - n1:handle("get", function(req, res, next) end) - n1:handle("get", function(req, res, next) end) -- define handler repeatly - end) - - -- _G.LOR_FRAMEWORK_DEBUG = true - --_debug(n1) - --json_view(t) - --print(t:gen_graph()) - end) -end) - diff --git a/website/backend/lor/spec/trie/strict_route_spec.lua b/website/backend/lor/spec/trie/strict_route_spec.lua deleted file mode 100644 index e036746..0000000 --- a/website/backend/lor/spec/trie/strict_route_spec.lua +++ /dev/null @@ -1,73 +0,0 @@ -setup(function() - _G.LOR_FRAMEWORK_DEBUG = false -end) - -teardown(function() -end) - -before_each(function() - Trie = _G.Trie - t = Trie:new() - t1 = Trie:new() - t2 = Trie:new() -end) - -after_each(function() - Trie = nil - t = nil - t1 = nil - t2 = nil - _debug = nil -end) - -describe("strict route: ", function() - it("should match if strict route is false.", function() - local t = Trie:new({ - strict_route = false -- default value is true - }) - local n1 = t:add_node("/a/b") - - local m1 = t:match("/a/b/") - assert.are.same(n1, m1.node) - - local m2 = t:match("/a/b") - assert.are.same(n1, m2.node) - end) - - it("should not match if strict route is true.", function() - local t = Trie:new({ - strict_route = true -- default value is true - }) - local n1 = t:add_node("/a/b") - - local m1 = t:match("/a/b") - assert.are.same(n1, m1.node) - - local m2 = t:match("/a/b/") - assert.is.falsy(m2.node) - end) - - it("should match if strict route is false and the exact route is not given.", function() - local t = Trie:new({ - strict_route = false -- default value is true - }) - local n1 = t:add_node("/a/b") - - local m1 = t:match("/a/b/") - assert.are.same(n1, m1.node) - end) - - it("should not match if strict route is true and the exact route is not given.", function() - local t = Trie:new({ - strict_route = true -- default value is true - }) - local n1 = t:add_node("/a/b") - - local m1 = t:match("/a/b/") - assert.is.falsy(m1.node) - assert.is.equals(nil, m1.node) - end) -end) - - - diff --git a/website/backend/reload.sh b/website/backend/reload.sh deleted file mode 100755 index b38966d..0000000 --- a/website/backend/reload.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -##################################################################### -# usage: -# sh reload.sh -- reload application @dev -# sh reload.sh ${env} -- reload application @${env} - -# examples: -# sh reload.sh prod -- use conf/nginx-prod.conf to reload OpenResty -# sh reload.sh -- use conf/nginx-dev.conf to reload OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "reload lor application with profile: "${PROFILE} -/usr/local/openresty/nginx/sbin/nginx -s reload -p `pwd`/ -c conf/nginx-${PROFILE}.conf diff --git a/website/backend/start.sh b/website/backend/start.sh deleted file mode 100755 index 5a21bfc..0000000 --- a/website/backend/start.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -##################################################################### -# usage: -# sh start.sh -- start application @dev -# sh start.sh ${env} -- start application @${env} - -# examples: -# sh start.sh prod -- use conf/nginx-prod.conf to start OpenResty -# sh start.sh -- use conf/nginx-dev.conf to start OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "start lor application with profile: "${PROFILE} -/usr/local/openresty/nginx/sbin/nginx -p `pwd`/ -c conf/nginx-${PROFILE}.conf diff --git a/website/backend/stop.sh b/website/backend/stop.sh deleted file mode 100755 index 26788c7..0000000 --- a/website/backend/stop.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -##################################################################### -# usage: -# sh stop.sh -- stop application @dev -# sh stop.sh ${env} -- stop application @${env} - -# examples: -# sh stop.sh prod -- use conf/nginx-prod.conf to stop OpenResty -# sh stop.sh -- use conf/nginx-dev.conf to stop OpenResty -##################################################################### - -if [ -n "$1" ];then - PROFILE="$1" -else - PROFILE=dev -fi - -mkdir -p logs & mkdir -p tmp -echo "stop lor application with profile: "${PROFILE} -/usr/local/openresty/nginx/sbin/nginx -s stop -p `pwd`/ -c conf/nginx-${PROFILE}.conf diff --git a/website/backend/www/.gitkeep b/website/backend/www/.gitkeep deleted file mode 100755 index e69de29..0000000