123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355 |
- local md5 = require "md5"
- local code = require "code"
- local lfsUtil = require "utils.lfsUtil"
- local staticfile = require "staticfile"
- local protoUtil = require "utils.protoUtil"
- local SALT_MD5 = "b8JKMN1UhanX" -- 商城md5 验签
- local GAME_SALT_MD5 = "0bdb9a5863c8c9063a42f38a9d5166fe" -- 游戏服加盐 md5
- local root = {}
- local controllerList = {}
- -- 无控制器
- local function l_get_unmatch_controller(res)
- res.code = 404
- res.body = "<html><head><title>404 Not Found Controller </title></head><body> <p>404 Not Found</p></body></html>"
- res.headers["Content-Type"] = "text/html"
- return res.code, res.body, res.headers
- end
- -- 无响应函数处理
- local function l_get_unmatch_process(res)
- res.code = 404
- res.body = "<html><head><title>404 Not Found Process </title></head><body> <p>404 Not Found</p></body></html>"
- res.headers["Content-Type"] = "text/html"
- return res.code, res.body, res.headers
- end
- -- 服务器内部错误处理
- local function serverError(res)
- res.code = 500
- res.body =
- "<html><head><title>Internal Server Error</title></head><body> <p>500 Internal Server Error</p></body></html>"
- res.headers["Content-Type"] = "text/html"
- return res.code, res.body, res.headers
- end
- local function l_get_req_headers(isHtml)
- local headers = {
- ["Access-Control-Allow-Origin"] = "*",
- ["Content-Type"] = "application/json",
- ["Access-Control-Allow-Methods"] = "POST,GET,OPTIONS",
- ["Access-Control-Allow-Credentials"] = true,
- ["Access-Control-Allow-Headers"] = "content-type,x-requested-with,x-ui-request,lang"
- }
- if isHtml then
- headers["Content-Type"] = "text/html"
- end
- return headers
- end
- local function l_get_math_controller_and_func(path)
- path = string.sub(path, 2, -1) -- 去除/
- local data = nil
- if string.match(path, "_") then
- data = string.split(path, "_")
- else
- data = string.split(path, "/")
- end
- local controller = table.remove(data, 1)
- local func = table.concat(data, "_")
- return string.format("%s", controller), func
- end
- -- 根据协议获取模块
- local function _get_cotroller(proto)
- local data = string.split(proto, "_")
- return data[1]
- end
- -- 匹配静态资源
- local function l_is_match_static(path)
- if not IS_TEST then
- return false
- end
- if path == "/" then
- path = "/static/index.html"
- end
- local offset = path:find("/", 2, true)
- if not offset then
- return false
- end
- -- 非静态资源
- local controller = path:sub(1, offset - 1)
- if controller ~= "/static" then
- return false
- end
- -- 读取静态文件
- local filename = path:sub(offset + 1)
- local content = staticfile[filename]
- if content then
- return true, 200, content
- end
- return true, 404, "404 Not found"
- end
- -- 匹配GM后台
- local function l_is_match_gm_json(path)
- local offset = path:find("json")
- if not offset then
- return false
- end
- return true, "/sgm_interface"
- end
- local function l_pack_rsp(errCode, resData)
- local res = {code = errCode, data = resData}
- return cjson_encode(res)
- end
- local function l_pack_gm_rsp(errCode, resData)
- resData = resData or {}
- resData.code = errCode or -1
- return cjson_encode(resData)
- end
- -- 请求
- local function GET(path, query)
- local isStatic, errCode, body = l_is_match_static(path)
- if isStatic then
- return errCode, body, l_get_req_headers(true)
- end
- local isGmJson, pathData = l_is_match_gm_json(path)
- if isGmJson then
- path = pathData
- body = body or query.body
- local ok, data = pcall(cjson_decode, body)
- if not ok then
- log.error("get params %s", tostring(body))
- body = nil
- else
- body = data
- end
- end
- local res = {code = 200, body = nil, headers = l_get_req_headers()}
- local controllerName, method = l_get_math_controller_and_func(path)
- local controller = controllerList[controllerName]
- if not controller then
- log.error("controller[%s] not exist", controllerName)
- return l_get_unmatch_controller(res)
- end
- local func = controller[method]
- if not func then
- log.error("controller[%s] has no method[%s] ", controllerName, method)
- return l_get_unmatch_process(res)
- end
- local errCode, ret = func(body or query)
- if isGmJson then
- res.body = l_pack_gm_rsp(errCode, ret)
- else
- res.body = l_pack_rsp(errCode, ret)
- end
- return res.code, res.body, res.headers
- end
- local function l_get_gm_param(body)
- local function split(str, reps)
- local res = {}
- str:gsub(
- "[^" .. reps .. "]+",
- function(w)
- table.insert(res, w)
- end
- )
- return res
- end
- local query = {}
- for index, value in ipairs(split(body, "&")) do
- for k, v in value:gmatch("([^=]+)=([^=]+)") do
- query[k] = v
- end
- end
- return query
- end
- local function POST(path, body, response)
- local isStatic, errCode, sbody = l_is_match_static(path)
- if isStatic then
- return errCode, sbody, l_get_req_headers(true)
- end
- local isGmJson, pathData = l_is_match_gm_json(path)
- if isGmJson then
- path = pathData
- body = cjson_decode(body)
- end
- local res = {code = 200, body = nil, headers = l_get_req_headers()}
- local controllerName, method = l_get_math_controller_and_func(path)
- local controller = controllerList[controllerName]
- if not controller then
- log.error("controller[%s] not exist", controllerName)
- return l_get_unmatch_controller(res)
- end
- local func = controller[method]
- if not func then
- log.error("controller[%s] has no method[%s] ", controllerName, method)
- return l_get_unmatch_process(res)
- end
- local param = controllerName == "sgm" and body or l_get_gm_param(body)
- local errCode, ret = func(param)
- if isGmJson then
- res.body = l_pack_gm_rsp(errCode, ret)
- else
- res.body = l_pack_rsp(errCode, ret)
- end
- return res.code, res.body, res.headers
- end
- local function OPTIONS(body)
- local headers = l_get_req_headers()
- headers["Content-Type"] = nil
- return 200, body, headers
- end
- local function ERROR()
- return 200, l_pack_rsp(code.REQUEST_NOT_FOUND), l_get_req_headers()
- end
- local function SPROTO(name, args, response)
- local res = {code = 200, body = nil, headers = l_get_req_headers()}
- local controllerName = _get_cotroller(name)
- local controller = controllerList[controllerName]
- if not controller then
- log.error("SPROTO controller[%s] not exist", controllerName)
- res.body = response({code = code.REQUEST_NOT_FOUND})
- return res.code, res.body, res.headers
- end
- local func = controller[name]
- if not func then
- log.error("SPROTO controller[%s] has no name[%s] ", controllerName, name)
- res.body = response({code = code.REQUEST_NOT_FOUND})
- return res.code, res.body, res.headers
- end
- local errCode, resData = func(args)
- resData = resData or {}
- resData.code = errCode
- res.body = response(resData)
- return res.code, res.body, res.headers
- end
- -- 解析请求参数
- local function l_decode_sproto(ip, headers, path, body)
- if path ~= "/pb" then
- return
- end
- local sz = headers["content-length"] or #body
- local ok, pType, pName, args, response = protoUtil:decode_c2s_req(body, sz)
- if not ok then
- return
- end
- -- pName = pName:gsub("_", "/")
- -- pName = string.format("/%s", pName)
- if headers and headers["proxy-client-ip"] then
- ip = headers["proxy-client-ip"]
- end
- args.ip = ip
- return "SPROTO", pName, args, response
- end
- local function l_is_match_sign(path, query, body)
- log.info("l_is_match_sign path[%s] query[%s]", tostring(path), tostring(query))
- local salt = ""
- local sign = query.sign
- if path == "/pb" then
- salt = GAME_SALT_MD5
- elseif path == "/json" then
- salt = SALT_MD5
- end
- log.info("l_is_match_sign salt[%s]", tostring(salt))
- if not sign then
- return false
- end
- local genSign = md5.sumhexa(body .. salt)
- log.info("l_is_match_sign genSign[%s]", tostring(genSign))
- if genSign == sign then
- return true
- end
- return false
- end
- -- 初始化
- function root:init()
- local files = lfsUtil:get_path_lua_files("nodes/login/controllers")
- for _, v in ipairs(files) do
- controllerList[v] = require("controllers." .. v)
- end
- end
- -- 热更新
- function root:update()
- protoUtil:update()
- end
- -- 处理http请求
- function root:http_request(ip, url, method, headers, path, query, body)
- log.info(
- "http_request ip[%s] url[%s] method[%s] headers[%s] path[%s] query[%s]",
- tostring(ip),
- tostring(url),
- tostring(method),
- tostring(headers),
- tostring(path),
- tostring(query)
- )
- if method == "POST" and not l_is_match_sign(path, query, body) then
- return ERROR()
- end
- local smethod, name, args, response = l_decode_sproto(ip, headers, path, body)
- log.info(
- "http_request l_decode_sproto smethod[%s] name[%s] args[%s] response[%s]",
- tostring(smethod),
- tostring(name),
- tostring(args),
- tostring(response)
- )
- smethod = smethod or method
- if smethod == "OPTIONS" then
- return OPTIONS()
- elseif smethod == "GET" then
- return GET(path, query)
- elseif smethod == "POST" then
- return POST(path, body)
- elseif smethod == "SPROTO" then
- return SPROTO(name, args, response)
- else
- return ERROR()
- end
- end
- return root
|