channel.lua 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. -- bi-directional http-channel
  2. -- with long-poll GET and POST on the same URL
  3. local function Channel(http, url, cfg)
  4. cfg = cfg or {}
  5. local extra_headers = cfg.extra_headers or {}
  6. local timeout = cfg.timeout or 1
  7. local long_poll_timeout = cfg.long_poll_timeout or 30
  8. local error_retry = cfg.error_retry or 10
  9. -- assemble post-header with json content
  10. local post_headers = { "Content-Type: application/json" }
  11. for _,header in pairs(cfg.extra_headers) do
  12. table.insert(post_headers, header)
  13. end
  14. local recv_listeners = {}
  15. local run = true
  16. local recv_loop
  17. recv_loop = function()
  18. assert(run)
  19. -- long-poll GET
  20. http.fetch({
  21. url = url,
  22. extra_headers = extra_headers,
  23. timeout = long_poll_timeout
  24. }, function(res)
  25. if res.succeeded and res.code == 200 then
  26. local data = minetest.parse_json(res.data)
  27. if data then
  28. for _,listener in pairs(recv_listeners) do
  29. if #data > 0 then
  30. -- array received
  31. for _, entry in ipairs(data) do
  32. listener(entry)
  33. end
  34. else
  35. -- single item received
  36. listener(data)
  37. end
  38. end
  39. end
  40. -- reschedule immediately
  41. minetest.after(0, recv_loop)
  42. else
  43. -- error, retry after some time
  44. minetest.after(error_retry, recv_loop)
  45. end
  46. end)
  47. end
  48. local send = function(data)
  49. assert(run)
  50. -- POST
  51. http.fetch({
  52. url = url,
  53. extra_headers = post_headers,
  54. timeout = timeout,
  55. post_data = minetest.write_json(data)
  56. }, function()
  57. -- TODO: error-handling
  58. end)
  59. end
  60. local receive = function(listener)
  61. table.insert(recv_listeners, listener)
  62. end
  63. local close = function()
  64. run = false
  65. end
  66. recv_loop();
  67. return {
  68. send = send,
  69. receive = receive,
  70. close = close
  71. }
  72. end
  73. return Channel