httpserver.lua 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. local socket = require "skynet.socket"
  2. local httpd = require "http.httpd"
  3. local sockethelper = require "http.sockethelper"
  4. local urllib = require "http.url"
  5. local cjson = require "cjson"
  6. local msgCode = require "code"
  7. local skynet = require "skynet"
  8. local mode, agent_count, server_port, command_path = ...
  9. if mode == "agent" then
  10. local httpcommand = require (command_path)
  11. local function response(id, response_status, response_data)
  12. local response_header = {["Content-Type"] = "application/text;charset=utf-8"}
  13. if type(response_data) == "table" then
  14. response_header = {["Content-Type"] = "application/json;charset=utf-8"}
  15. response_data = cjson.encode(response_data)
  16. end
  17. local ok, err = httpd.write_response(sockethelper.writefunc(id), response_status, response_data, response_header)
  18. --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)
  19. end
  20. local function format_params(id, url, method, header, body)
  21. local request_data = {}
  22. if header.host then
  23. request_data.host = header.host
  24. end
  25. local path, query = urllib.parse(url)
  26. request_data.path = path
  27. request_data.param = {}
  28. if query then
  29. local q = urllib.parse_query(query)
  30. for k, v in pairs(q) do
  31. request_data.param[k] = v
  32. end
  33. end
  34. request_data.header = {}
  35. for k, v in pairs(header) do
  36. request_data.header[k] = v
  37. end
  38. if body and body ~= "" then
  39. local decode_success, json_object = pcall(cjson.decode, body)
  40. if not decode_success then
  41. return msgCode.PARAMTER_ERROR
  42. end
  43. for k, v in pairs(json_object) do
  44. request_data.param[k] = v
  45. end
  46. end
  47. return msgCode.OK, request_data
  48. end
  49. local function write_error_msg(id, status)
  50. response(id, status, "http logic handle error")
  51. end
  52. local function handle_request(id, addr)
  53. local status, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), 8192)
  54. --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")
  55. if not status then
  56. log.info("httpserver id:%s read data not status", id)
  57. write_error_msg(id, 500)
  58. return
  59. end
  60. --[[
  61. if type(header) == "string" and #header > 0 then
  62. header = cjson.decode(header)
  63. end
  64. if type(body) == "string" and #body > 0 then
  65. body = cjson.decode(body)
  66. end
  67. --]]
  68. if status ~= 200 then
  69. log.info("httpserver id:%s status:%s ~= 200", id, status)
  70. write_error_msg(id, status)
  71. return
  72. end
  73. local code, request_data = format_params(id, url, method, header, body)
  74. if code ~= msgCode.OK then
  75. log.info("httpserver id:%s parse data error, code:%s", id, code)
  76. write_error_msg(id, status)
  77. return
  78. end
  79. --log.info("httpserver id:%s request_data:%s", id, tostring(request_data))
  80. local response_data = httpcommand.handle(request_data)
  81. response(id, status, response_data)
  82. end
  83. skynet.start(function ()
  84. skynet.dispatch("lua", function (_, _, id, addr)
  85. socket.start(id)
  86. -- limit request body size to 8192 (you can fill nil to unlimit)
  87. local is_success = safeRun(handle_request, id, addr)
  88. if not is_success then
  89. log.info("httpserver id:%s system error", id)
  90. pcall(write_error_msg, id, 500)
  91. end
  92. log.info("fd close id:%s", id)
  93. socket.close(id)
  94. end)
  95. if httpcommand.init then
  96. httpcommand.init()
  97. end
  98. end)
  99. else
  100. skynet.start(function ()
  101. local agent = {}
  102. for i = 1, agent_count do
  103. agent[i] = skynet.newservice(SERVICE_NAME, "agent", agent_count, server_port, command_path)
  104. end
  105. local id = socket.listen("0.0.0.0", server_port)
  106. log.info("httpserver listen web port " .. server_port)
  107. local balance = 1
  108. socket.start(id, function (id, addr)
  109. skynet.send(agent[balance], "lua", id, addr)
  110. balance = balance + 1
  111. if balance > #agent then
  112. balance = 1
  113. end
  114. end)
  115. end)
  116. end