simpleweb.lua 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. local skynet = require "skynet"
  2. local socket = require "skynet.socket"
  3. local httpd = require "http.httpd"
  4. local sockethelper = require "http.sockethelper"
  5. local urllib = require "http.url"
  6. local table = table
  7. local string = string
  8. local mode, protocol = ...
  9. protocol = protocol or "http"
  10. if mode == "agent" then
  11. local function response(id, write, ...)
  12. local ok, err = httpd.write_response(write, ...)
  13. if not ok then
  14. -- if err == sockethelper.socket_error , that means socket closed.
  15. skynet.error(string.format("fd = %d, %s", id, err))
  16. end
  17. end
  18. local SSLCTX_SERVER = nil
  19. local function gen_interface(protocol, fd)
  20. if protocol == "http" then
  21. return {
  22. init = nil,
  23. close = nil,
  24. read = sockethelper.readfunc(fd),
  25. write = sockethelper.writefunc(fd),
  26. }
  27. elseif protocol == "https" then
  28. local tls = require "http.tlshelper"
  29. if not SSLCTX_SERVER then
  30. SSLCTX_SERVER = tls.newctx()
  31. -- gen cert and key
  32. -- openssl req -x509 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem -out server-cert.pem
  33. local certfile = skynet.getenv("certfile") or "./server-cert.pem"
  34. local keyfile = skynet.getenv("keyfile") or "./server-key.pem"
  35. print(certfile, keyfile)
  36. SSLCTX_SERVER:set_cert(certfile, keyfile)
  37. end
  38. local tls_ctx = tls.newtls("server", SSLCTX_SERVER)
  39. return {
  40. init = tls.init_responsefunc(fd, tls_ctx),
  41. close = tls.closefunc(tls_ctx),
  42. read = tls.readfunc(fd, tls_ctx),
  43. write = tls.writefunc(fd, tls_ctx),
  44. }
  45. else
  46. error(string.format("Invalid protocol: %s", protocol))
  47. end
  48. end
  49. skynet.start(function()
  50. skynet.dispatch("lua", function (_,_,id)
  51. socket.start(id)
  52. local interface = gen_interface(protocol, id)
  53. if interface.init then
  54. interface.init()
  55. end
  56. -- limit request body size to 8192 (you can pass nil to unlimit)
  57. local code, url, method, header, body = httpd.read_request(interface.read, 8192)
  58. if code then
  59. if code ~= 200 then
  60. response(id, interface.write, code)
  61. else
  62. local tmp = {}
  63. if header.host then
  64. table.insert(tmp, string.format("host: %s", header.host))
  65. end
  66. local path, query = urllib.parse(url)
  67. table.insert(tmp, string.format("path: %s", path))
  68. if query then
  69. local q = urllib.parse_query(query)
  70. for k, v in pairs(q) do
  71. table.insert(tmp, string.format("query: %s= %s", k,v))
  72. end
  73. end
  74. table.insert(tmp, "-----header----")
  75. for k,v in pairs(header) do
  76. table.insert(tmp, string.format("%s = %s",k,v))
  77. end
  78. table.insert(tmp, "-----body----\n" .. body)
  79. response(id, interface.write, code, table.concat(tmp,"\n"))
  80. end
  81. else
  82. if url == sockethelper.socket_error then
  83. skynet.error("socket closed")
  84. else
  85. skynet.error(url)
  86. end
  87. end
  88. socket.close(id)
  89. if interface.close then
  90. interface.close()
  91. end
  92. end)
  93. end)
  94. else
  95. skynet.start(function()
  96. local agent = {}
  97. local protocol = "http"
  98. for i= 1, 20 do
  99. agent[i] = skynet.newservice(SERVICE_NAME, "agent", protocol)
  100. end
  101. local balance = 1
  102. local id = socket.listen("0.0.0.0", 8001)
  103. skynet.error(string.format("Listen web port 8001 protocol:%s", protocol))
  104. socket.start(id , function(id, addr)
  105. skynet.error(string.format("%s connected, pass it to agent :%08x", addr, agent[balance]))
  106. skynet.send(agent[balance], "lua", id)
  107. balance = balance + 1
  108. if balance > #agent then
  109. balance = 1
  110. end
  111. end)
  112. end)
  113. end