local socket = require "skynet.socket" local httpd = require "http.httpd" local sockethelper = require "http.sockethelper" local urllib = require "http.url" local cjson = require "cjson" local msgCode = require "code" local skynet = require "skynet" local mode, agent_count, server_port, command_path = ... if mode == "agent" then local httpcommand = require (command_path) local function response(id, response_status, response_data) local response_header = {["Content-Type"] = "application/text;charset=utf-8"} if type(response_data) == "table" then response_header = {["Content-Type"] = "application/json;charset=utf-8"} response_data = cjson.encode(response_data) end local ok, err = httpd.write_response(sockethelper.writefunc(id), response_status, response_data, response_header) --log.info("httpserver id:%s write response ok:%s, err:%s, response_status:%s, data_type:%s response_data:%s", id, ok, err or "nil", response_status, type(response_data), response_data) end local function format_params(id, url, method, header, body) local request_data = {} if header.host then request_data.host = header.host end local path, query = urllib.parse(url) request_data.path = path request_data.param = {} if query then local q = urllib.parse_query(query) for k, v in pairs(q) do request_data.param[k] = v end end request_data.header = {} for k, v in pairs(header) do request_data.header[k] = v end if body and body ~= "" then local decode_success, json_object = pcall(cjson.decode, body) if not decode_success then return msgCode.PARAMTER_ERROR end for k, v in pairs(json_object) do request_data.param[k] = v end end return msgCode.OK, request_data end local function write_error_msg(id, status) response(id, status, "http logic handle error") end local function handle_request(id, addr) local status, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), 8192) --log.info("httpserver id:%s, addr:%s read data, status:%s, url:%s, method:%s, header:%s, body:%s", id, addr, status, url, method or "nil", header and tostring(header) or "nil", body and tostring(body) or "nil") if not status then log.info("httpserver id:%s read data not status", id) write_error_msg(id, 500) return end --[[ if type(header) == "string" and #header > 0 then header = cjson.decode(header) end if type(body) == "string" and #body > 0 then body = cjson.decode(body) end --]] if status ~= 200 then log.info("httpserver id:%s status:%s ~= 200", id, status) write_error_msg(id, status) return end local code, request_data = format_params(id, url, method, header, body) if code ~= msgCode.OK then log.info("httpserver id:%s parse data error, code:%s", id, code) write_error_msg(id, status) return end --log.info("httpserver id:%s request_data:%s", id, tostring(request_data)) local response_data = httpcommand.handle(request_data) response(id, status, response_data) end skynet.start(function () skynet.dispatch("lua", function (_, _, id, addr) socket.start(id) -- limit request body size to 8192 (you can fill nil to unlimit) local is_success = safeRun(handle_request, id, addr) if not is_success then log.info("httpserver id:%s system error", id) pcall(write_error_msg, id, 500) end log.info("fd close id:%s", id) socket.close(id) end) if httpcommand.init then httpcommand.init() end end) else skynet.start(function () local agent = {} for i = 1, agent_count do agent[i] = skynet.newservice(SERVICE_NAME, "agent", agent_count, server_port, command_path) end local id = socket.listen("0.0.0.0", server_port) log.info("httpserver listen web port " .. server_port) local balance = 1 socket.start(id, function (id, addr) skynet.send(agent[balance], "lua", id, addr) balance = balance + 1 if balance > #agent then balance = 1 end end) end) end