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