-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.lua
103 lines (95 loc) · 4.03 KB
/
server.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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
local http_server = require "http.server"
local http_headers = require "http.headers"
local http_websocket = require "http.websocket"
local utils = require "mp.utils"
local msg = require "mp.msg"
local remote = require "remote"
local M = {}
M.create = function(cqueue, host, port)
local parse_url = function(url)
local result = {}
for w in url:gmatch("([^/]+)/?") do
result[#result + 1] = w
end
return result
end
local mime_types = {
["text"] = "text/plaintext";
["html"] = "text/html";
["css"] = "text/css";
["js"] = "text/javascript";
["json"] = "application/json";
["svg"] = "image/svg+xml";
["woff2"] = "font/woff2";
};
local routes = {
["index"] = function(request_headers, stream, path_tail)
local response_headers = http_headers.new()
local page = io.open(utils.join_path(mp.get_script_directory(), "www/index.html"), "r")
response_headers:append(":status", "200")
response_headers:append("Content-Type", "text/html")
assert(stream:write_headers(response_headers, false), "failed to write response headers")
assert(stream:write_body_from_file(page))
end;
["socket"] = function(request_headers, stream, path_tail)
if request_headers:get("upgrade") == "websocket" then
local ws = http_websocket.new_from_stream(stream, request_headers)
ws:accept({}, 5)
remote.listen(ws)
end
end;
["static"] = function(request_headers, stream, path_tail)
local response_headers = http_headers.new()
local fpath = "www/static/"..path_tail
local _, _, ftype = string.find(path_tail, "%.([^%.]+)$")
local page = io.open(utils.join_path(mp.get_script_directory(), fpath), "r")
response_headers:append(":status", "200")
response_headers:append("Content-Type", mime_types[ftype])
assert(stream:write_headers(response_headers, false))
assert(stream:write_body_from_file(page))
end;
["file-picker"] = function(request_header, stream, path_tail)
local response_headers = http_headers.new()
dirs = utils.readdir(utils.join_path(utils.getcwd(), (path_tail or "")), "dirs")
files = utils.readdir(utils.join_path(utils.getcwd(), (path_tail or "")), "files")
response_headers:append(":status", "200")
response_headers:append("Content-Type", "application/json")
assert(stream:write_headers(response_headers, false))
assert(stream:write_body_from_string(utils.format_json{files = files or {}, dirs = dirs or {}}))
end;
};
local onstream = function(server, stream)
local request_headers = assert(stream:get_headers(), "failed to retrieve request headers")
msg.debug(string.format('"%s %s HTTP/%g" "%s" "%s"',
request_headers:get(":method") or "",
request_headers:get(":path") or "",
stream.connection.version,
request_headers:get("referer") or "-",
request_headers:get("user-agent") or "-"))
local raw_path = request_headers:get(":path")
local _, _, path_root, path_tail = string.find(raw_path, "([^/]+)/?(.*)$")
local route = routes[path_root or "index"]
assert(route, raw_path.." is not a valid route")
route(request_headers, stream, path_tail)
end;
local onerror = function(myserver, context, op, err, errno)
local message = op .. " on " .. utils.to_string(context) .. " failed"
if err then
message = message .. ": " .. utils.to_string(err)
end
msg.error(message)
end;
return {
_server = http_server.listen {
cq = cqueue;
host = host;
port = port;
onstream = onstream;
onerror = onerror;
};
listen = function(self)
return self._server:listen()
end;
}
end
return M