sjson-streaming.lua 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. -- Test sjson and GitHub API
  2. local s = tls.createConnection()
  3. s:on("connection", function(sck)
  4. sck:send(
  5. [[GET /repos/nodemcu/nodemcu-firmware/git/trees/master HTTP/1.0
  6. User-agent: nodemcu/0.1
  7. Host: api.github.com
  8. Connection: close
  9. Accept: application/json
  10. ]])
  11. end)
  12. local function startswith(String, Start)
  13. return string.sub(String, 1, string.len(Start)) == Start
  14. end
  15. local seenBlank = false
  16. local partial
  17. local wantval = { tree = 1, path = 1, url = 1 }
  18. -- Make an sjson decoder that only keeps certain fields
  19. local decoder = sjson.decoder({
  20. metatable =
  21. {
  22. __newindex = function(t, k, v)
  23. if wantval[k] or type(k) == "number" then
  24. rawset(t, k, v)
  25. end
  26. end
  27. }
  28. })
  29. local function handledata(sck)
  30. decoder:write(sck)
  31. end
  32. -- The receive callback is somewhat gnarly as it has to deal with find the end of the header
  33. -- and having the newline sequence split across packets
  34. s:on("receive", function(socket, c) -- luacheck: no unused
  35. if partial then
  36. c = partial .. c
  37. partial = nil
  38. end
  39. if seenBlank then
  40. handledata(c)
  41. return
  42. end
  43. while c do
  44. if startswith(c, "\r\n") then
  45. seenBlank = true
  46. c = c:sub(3)
  47. handledata(c)
  48. return
  49. end
  50. local str, e = c:find("\r\n")
  51. if str then
  52. -- Throw away line
  53. c = c:sub(e + 1)
  54. else
  55. partial = c
  56. c = nil
  57. end
  58. end
  59. end)
  60. local function getresult()
  61. local result = decoder:result()
  62. -- This gets the resulting decoded object with only the required fields
  63. print(result['tree'][4]['path'], "is at",
  64. result['tree'][4]['url'])
  65. end
  66. s:on("disconnection", getresult)
  67. s:on("reconnection", getresult)
  68. -- Make it all happen!
  69. s:connect(443, "api.github.com")