diff options
Diffstat (limited to 'plugins/weblit/websocket.lua')
-rw-r--r-- | plugins/weblit/websocket.lua | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/plugins/weblit/websocket.lua b/plugins/weblit/websocket.lua new file mode 100644 index 00000000000..d5dfe572ea6 --- /dev/null +++ b/plugins/weblit/websocket.lua @@ -0,0 +1,82 @@ + +local websocketCodec = require('websocket-codec') + +local function websocketHandler(options, handler) + return function (req, res, go) + -- Websocket connections must be GET requests + -- with 'Upgrade: websocket' + -- and 'Connection: Upgrade' headers + local headers = req.headers + local connection = headers.connection + local upgrade = headers.upgrade + if not ( + req.method == "GET" and + upgrade and upgrade:lower():find("websocket", 1, true) and + connection and connection:lower():find("upgrade", 1, true) + ) then + return go() + end + + if options.filter and not options.filter(req) then + return go() + end + + -- If there is a sub-protocol specified, filter on it. + local protocol = options.protocol + if protocol then + local list = headers["sec-websocket-protocol"] + local foundProtocol + if list then + for item in list:gmatch("[^, ]+") do + if item == protocol then + foundProtocol = true + break + end + end + end + if not foundProtocol then + return go() + end + end + + -- Make sure it's a new client speaking v13 of the protocol + assert(tonumber(headers["sec-websocket-version"]) >= 13, "only websocket protocol v13 supported") + + -- Get the security key + local key = assert(headers["sec-websocket-key"], "websocket security required") + + res.code = 101 + headers = res.headers + headers.Upgrade = "websocket" + headers.Connection = "Upgrade" + headers["Sec-WebSocket-Accept"] = websocketCodec.acceptKey(key) + if protocol then + headers["Sec-WebSocket-Protocol"] = protocol + end + function res.upgrade(read, write, updateDecoder, updateEncoder) + updateDecoder(websocketCodec.decode) + updateEncoder(websocketCodec.encode) + local success, err = pcall(handler, req, read, write) + if not success then + print(err) + write({ + opcode = 1, + payload = err, + }) + return write() + end + end + end +end + +local server = require('weblit-app') +function server.websocket(options, handler) + server.route({ + method = "GET", + path = options.path, + host = options.host, + }, websocketHandler(options, handler)) + return server +end + +return websocketHandler |