aboutsummaryrefslogtreecommitdiff
path: root/samples/sse.lua
blob: 16eece9baba08674def448bef8aeac2f2fefc130 (plain)
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
-----------------------------------------------------------------------------
-- Server-Sent Events (SSE) demo client
-- LuaSocket sample files
--
-- Usage: lua sse.lua [<url>] [<event-count>]
-- Both arguments are positional and optional; with none given, connects to
-- a public live test feed and stops after 5 events.
-----------------------------------------------------------------------------
local http = require("socket.http")
local sse = require("socket.sse")

-- default target: Wikimedia's public, continuously-streaming recent-changes
-- feed -- a real, live text/event-stream endpoint, handy for trying out
-- socket.sse without standing up a server of your own
local DEFAULT_URL = "https://stream.wikimedia.org/v2/stream/recentchange"
local DEFAULT_LIMIT = 5

-- shortens a long data payload for readable terminal output
local function preview(text, limit)
    limit = limit or 100
    if #text > limit then return string.sub(text, 1, limit) .. "..." end
    return text
end

-- builds a message callback that prints each received Message, then stops
-- the stream once "limit" of them have been printed. This module parses a
-- single request/response and never reconnects on its own (see
-- docs/adr/0001-sse-single-shot-no-auto-reconnect.md), so a caller who wants
-- to stop early just does what we do here: return an error from the
-- callback, which ends the request the same way any sink error would
local function makeprinter(limit)
    local count = 0
    return function(message)
        count = count + 1
        io.write(string.format("[%d] event=%s id=%s\n    data=%s\n",
            count, message.event, tostring(message.id), preview(message.data)))
        if count >= limit then
            return nil, string.format("stopped after %d events", limit)
        end
        return 1
    end
end

-- main program
arg = arg or {}
local url = arg[1] or DEFAULT_URL
local limit = tonumber(arg[2]) or DEFAULT_LIMIT

io.write("connecting to ", url, " (stopping after ", limit, " events)\n")
local ok, code = http.request{
    url = url,
    headers_callback = sse.responseheaders(makeprinter(limit))
}

if ok then
    -- the server closed the connection on its own before we hit our limit
    io.write("connection closed by server, code=", tostring(code), "\n")
else
    -- once the callback above returns an error, http.request reports it the
    -- same way it reports any failure: (nil, message) -- so "code" here is
    -- really our own "stopped after N events" message, not a real error
    io.write(code, "\n")
end