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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
if not modules then modules = { } end modules ['util-imp-evohome-server'] = {
version = 1.002,
comment = "simple server for simple evohome extensions",
author = "Hans Hagen, PRAGMA-ADE, Hasselt NL",
copyright = "PRAGMA ADE",
license = "see context related readme files"
}
local P, C, patterns, lpegmatch = lpeg.P, lpeg.C, lpeg.patterns, lpeg.match
local urlhashed, urlquery, urlunescapeget = url.hashed, url.query, url.unescapeget
local ioflush = io.flush
local newline = patterns.newline
local spacer = patterns.spacer
local whitespace = patterns.whitespace
local method = P("GET")
+ P("POST")
local identify = (1-method)^0
* C(method)
* spacer^1
* C((1-spacer)^1)
* spacer^1
* P("HTTP/")
* (1-whitespace)^0
* C(P(1)^0)
do
local loaded = package.loaded
if not loaded.socket then loaded.socket = loaded["socket.core"] end
if not loaded.mime then loaded.mime = loaded["mime.core"] end
end
local evohome = require("util-evo")
require("trac-lmx")
local report = logs.reporter("evohome","server")
local convert = lmx.convert
function evohome.server(specification)
local filename = specification.filename
if not filename then
report("unable to run server, no filename given")
return
end
local step, process, presets = evohome.actions.poller(filename)
if not (step and process and presets) then
report("unable to run server, invalid presets")
return
end
local template = presets.files.template
if not template then
report("unable to run server, no template given")
return
end
local port = specification.port or (presets.server and presets.server.port) or 8068
local host = specification.host or (presets.server and presets.server.host) or "*"
package.extraluapath(presets.filepath)
local socket = socket or require("socket")
local copas = copas or require("copas")
local function copashttp(skt)
local client = copas.wrap(skt)
local request, e = client:receive()
if not e then
local method, fullurl, body = lpegmatch(identify,request)
if method ~= "" and fullurl ~= "" then
local fullurl = urlunescapeget(fullurl)
local hashed = urlhashed(fullurl)
process(hashed.queries or { })
ioflush()
end
-- todo: split off css and use that instead of general one, now too much
local content = convert(presets.results and presets.results.template or template,false,presets)
if not content then
report("error in converting template")
content = "error in template"
end
client:send("HTTP/1.1 200 OK\r\n")
client:send("Connection: close\r\n")
client:send("Content-Length: " .. #content .. "\r\n")
client:send("Content-Type: text/html\r\n")
client:send("Location: " .. host .. "\r\n")
client:send("Cache-Control: no-cache, no-store, must-revalidate, max-age=0\r\n")
client:send("\r\n")
client:send(content)
client:send("\r\n")
client:close()
end
end
local function copaspoll()
while step do
local delay = step()
if type(delay) == "number" then
copas.sleep(delay or 0)
end
end
end
local server = socket.bind(host,port)
if server then
report("server started at %s:%s",host,port)
ioflush()
copas.addserver(server,copashttp)
copas.addthread(copaspoll)
copas.loop()
else
report("unable to start server at %s:%s",host,port)
os.exit()
end
end
return evohome
|