1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- -- bi-directional http-channel
- -- with long-poll GET and POST on the same URL
- local function Channel(http, url, cfg)
- cfg = cfg or {}
- local extra_headers = cfg.extra_headers or {}
- local timeout = cfg.timeout or 1
- local long_poll_timeout = cfg.long_poll_timeout or 30
- local error_retry = cfg.error_retry or 10
- -- assemble post-header with json content
- local post_headers = { "Content-Type: application/json" }
- for _,header in pairs(cfg.extra_headers) do
- table.insert(post_headers, header)
- end
- local recv_listeners = {}
- local run = true
- local recv_loop
- recv_loop = function()
- assert(run)
- -- long-poll GET
- http.fetch({
- url = url,
- extra_headers = extra_headers,
- timeout = long_poll_timeout
- }, function(res)
- if res.succeeded and res.code == 200 then
- local data = minetest.parse_json(res.data)
- if data then
- for _,listener in pairs(recv_listeners) do
- if #data > 0 then
- -- array received
- for _, entry in ipairs(data) do
- listener(entry)
- end
- else
- -- single item received
- listener(data)
- end
- end
- end
- -- reschedule immediately
- minetest.after(0, recv_loop)
- else
- -- error, retry after some time
- minetest.after(error_retry, recv_loop)
- end
- end)
- end
- local send = function(data)
- assert(run)
- -- POST
- http.fetch({
- url = url,
- extra_headers = post_headers,
- timeout = timeout,
- post_data = minetest.write_json(data)
- }, function()
- -- TODO: error-handling
- end)
- end
- local receive = function(listener)
- table.insert(recv_listeners, listener)
- end
- local close = function()
- run = false
- end
- recv_loop();
- return {
- send = send,
- receive = receive,
- close = close
- }
- end
- return Channel
|