summaryrefslogtreecommitdiff
path: root/tex/context/base/mkiv/util-evo-imp-server.lua
blob: f4dd5b3f7fc8d99eae4a813c340b6b9a57127731 (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
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