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