rev |
line source |
jbe@0
|
1 -- Moonbridge example application
|
jbe@0
|
2 -- invoke with ./moonbridge example_application.lua
|
jbe@33
|
3 --
|
jbe@33
|
4 -- see helloworld.lua for a simpler example
|
jbe@0
|
5
|
jbe@4
|
6 local http = require "moonbridge_http"
|
jbe@0
|
7
|
jbe@26
|
8 -- preparation before forking:
|
jbe@13
|
9 local documents = {}
|
jbe@194
|
10 for i, document_name in ipairs{"example_webpage.html", "example_webpage.css"} do
|
jbe@15
|
11 local file = assert(io.open(document_name))
|
jbe@26
|
12 documents[document_name] = file:read("*a") -- store file contents in memory
|
jbe@13
|
13 file:close()
|
jbe@13
|
14 end
|
jbe@0
|
15
|
jbe@0
|
16 listen{
|
jbe@0
|
17 -- listen to a tcp version 4 socket
|
jbe@125
|
18 --{ proto = "tcp", host = "0.0.0.0", port = 8080 },
|
jbe@0
|
19
|
jbe@0
|
20 -- listen to a tcp version 6 socket
|
jbe@125
|
21 { proto = "tcp", host = "::", port = 8080},
|
jbe@0
|
22
|
jbe@0
|
23 -- listen to a unix domain socket
|
jbe@0
|
24 --{ proto = "local", path = 'socket' },
|
jbe@0
|
25
|
jbe@0
|
26 -- execute the listener regularly (without incoming connection)
|
jbe@0
|
27 --{ proto = "interval", name = "myint", delay = 10, strict = false },
|
jbe@0
|
28
|
jbe@0
|
29 -- desired number of spare (idle) processes
|
jbe@0
|
30 pre_fork = 1, -- number of forks
|
jbe@0
|
31
|
jbe@0
|
32 -- minimum number of processes
|
bsw@121
|
33 min_fork = 4, -- number of forks
|
jbe@0
|
34
|
jbe@0
|
35 -- maximum number of processes (hard limit)
|
jbe@0
|
36 max_fork = 16, -- number of forks
|
jbe@0
|
37
|
jbe@0
|
38 -- delay between creation of spare processes
|
jbe@61
|
39 fork_delay = 0.25, -- seconds
|
jbe@0
|
40
|
jbe@0
|
41 -- delay before retry of failed process creation
|
jbe@0
|
42 fork_error_delay = 2, -- seconds
|
jbe@0
|
43
|
jbe@0
|
44 -- delay between destruction of excessive spare processes
|
jbe@0
|
45 exit_delay = 60, -- seconds
|
jbe@0
|
46
|
jbe@0
|
47 -- idle time after a fork gets terminated
|
jbe@0
|
48 idle_timeout = 0, -- seconds (0 for no timeout)
|
jbe@0
|
49
|
jbe@0
|
50 -- maximum memory consumption before process gets terminated
|
jbe@23
|
51 --memory_limit = 1024*1024, -- bytes
|
jbe@0
|
52
|
jbe@11
|
53 -- preparation of process (executed after fork)
|
jbe@0
|
54 prepare = function()
|
jbe@26
|
55 -- e.g. open database connection
|
jbe@0
|
56 end,
|
jbe@0
|
57
|
jbe@0
|
58 -- connection handler
|
jbe@0
|
59 connect = http.generate_handler(
|
jbe@0
|
60 {
|
jbe@0
|
61 static_headers = {"Server: Moonbridge Example Server"},
|
jbe@54
|
62 request_body_size_limit = 16*1024*1024*1024, -- allow big file uploads
|
jbe@115
|
63 request_idle_timeout = 330, -- 5 minutes and 30 seconds after which an idle connection will be closed
|
jbe@115
|
64 request_header_timeout = 30, -- request headers must be sent within 30 seconds after first byte was received
|
jbe@54
|
65 timeout = 1800 -- request body and response must be sent within 30 minutes
|
jbe@0
|
66 },
|
jbe@0
|
67 function(request)
|
jbe@0
|
68
|
jbe@33
|
69 local function error_response(status)
|
jbe@33
|
70 request:send_status(status)
|
jbe@33
|
71 request:send_header("Content-Type", "text/html")
|
jbe@33
|
72 request:send_data("<html>\n<head><title>", status, "</title></head>\n<body><h1>", status, "</h1></body>\n</html>\n")
|
jbe@33
|
73 request:finish()
|
jbe@23
|
74 end
|
jbe@23
|
75
|
jbe@0
|
76 if request.method == "GET" or request.method == "HEAD" then
|
jbe@0
|
77
|
jbe@10
|
78 if request.path == "" then
|
jbe@0
|
79 request:send_status("303 See Other")
|
jbe@0
|
80 request:send_header("Location", "http://" .. request.headers_value.host .. "/example_webpage.html")
|
jbe@0
|
81
|
jbe@0
|
82 else
|
jbe@10
|
83 local document_name = request.path
|
jbe@0
|
84 local document_extension = string.match(document_name, "%.([^.])$")
|
jbe@26
|
85 local document = documents[document_name] -- loads file contents from memory
|
jbe@0
|
86 if document then
|
jbe@0
|
87 request:send_status("200 OK")
|
jbe@0
|
88 if document_extension == "html" then
|
jbe@0
|
89 request:send_header("Content-Type", "text/html; charset=UTF-8")
|
jbe@0
|
90 elseif document_extension == "css" then
|
jbe@0
|
91 request:send_header("Content-Type", "text/css; charset=UTF-8")
|
jbe@0
|
92 end
|
jbe@0
|
93 request:send_data(document)
|
jbe@0
|
94 else
|
jbe@33
|
95 error_response("404 Not Found")
|
jbe@0
|
96 end
|
jbe@0
|
97
|
jbe@0
|
98 end
|
jbe@0
|
99
|
jbe@0
|
100 elseif request.method == "POST" then
|
jbe@0
|
101
|
jbe@10
|
102 if request.path == "post_example" then
|
jbe@0
|
103 local files = {}
|
jbe@0
|
104 do
|
jbe@0
|
105 local file
|
jbe@0
|
106 request:stream_post_param("files", function(chunk, field_name, meta)
|
jbe@0
|
107 if meta then
|
jbe@0
|
108 file = {
|
jbe@0
|
109 file_name = meta.file_name,
|
jbe@0
|
110 content_type = meta.content_type,
|
jbe@0
|
111 length = 0
|
jbe@0
|
112 }
|
jbe@0
|
113 end
|
jbe@0
|
114 if chunk then
|
jbe@0
|
115 file.length = file.length + #chunk
|
jbe@0
|
116 else
|
jbe@0
|
117 files[#files+1] = file
|
jbe@0
|
118 end
|
jbe@0
|
119 end)
|
jbe@0
|
120 end
|
jbe@0
|
121
|
jbe@0
|
122 request:send_status("200 OK")
|
jbe@194
|
123 request:send_header("Content-Type", "text/html; charset=UTF-8")
|
jbe@0
|
124 request:send_data("<html>\n<head>\n")
|
jbe@0
|
125 request:send_data('<link href="example_webpage.css" rel="stylesheet" type="text/css">\n')
|
jbe@0
|
126 request:send_data("<title>Moonbridge Network Server for Lua Applications – Example Application</title>\n")
|
jbe@0
|
127 request:send_data("</head>\n<body>\n")
|
jbe@0
|
128 request:send_data("<h1>Moonbridge Network Server for Lua – Example Application</h1>\n")
|
jbe@0
|
129 request:send_data("<h2>POST request successful</h2>\n")
|
jbe@0
|
130 request:send_data('<table>\n<thead><th>File name</th><th>Content type</th><th class="numeric">Bytes received</th></thead>\n<tbody>\n')
|
jbe@192
|
131 request:consume_input()
|
jbe@0
|
132 for i, file in ipairs(files) do
|
jbe@0
|
133 request:send_data("<tr>")
|
jbe@0
|
134 request:send_data("<td>", http.encode_html(file.file_name or "(unknown)"), "</td>")
|
jbe@0
|
135 request:send_data("<td>", http.encode_html(file.content_type or "(unknown)"), "</td>")
|
jbe@0
|
136 request:send_data('<td class="numeric">', http.encode_html(tostring(file.length)), "</td>")
|
jbe@0
|
137 request:send_data("</tr>\n")
|
jbe@0
|
138 end
|
jbe@0
|
139 request:send_data("</tbody>\n</table>\n")
|
jbe@0
|
140 request:send_data("<p>Submitted comment: ", http.encode_html(request.post_params.comment), "</p>\n")
|
jbe@0
|
141 request:send_data("</body>\n</html>\n")
|
jbe@0
|
142
|
jbe@0
|
143 else
|
jbe@33
|
144 error_response("404 Not Found")
|
jbe@0
|
145
|
jbe@23
|
146 end
|
jbe@0
|
147
|
jbe@0
|
148 else
|
jbe@33
|
149 error_response("405 Method not allowed")
|
jbe@0
|
150
|
jbe@0
|
151 end
|
jbe@0
|
152
|
jbe@0
|
153 -- returning false causes termination of current process (and re-forking)
|
jbe@0
|
154 return true
|
jbe@0
|
155 end),
|
jbe@0
|
156
|
jbe@0
|
157 -- executed on process termination
|
jbe@0
|
158 finish = function()
|
jbe@26
|
159 -- e.g. close database connection
|
jbe@0
|
160 end
|
jbe@0
|
161 }
|
jbe@0
|
162
|