f48ad7ef9bd827bf7107134aa654a1eaa0819277
[project/luci.git] / libs / sgi-uhttpd / luasrc / sgi / uhttpd.lua
1 --[[
2 LuCI - Server Gateway Interface for the uHTTPd server
3
4 Copyright 2010 Jo-Philipp Wich <xm@subsignal.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at 
9
10         http://www.apache.org/licenses/LICENSE-2.0 
11
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17
18 ]]--
19
20 exectime = os.clock()
21 require "nixio.util"
22 require "luci.http"
23 require "luci.sys"
24 require "luci.dispatcher"
25 require "luci.ltn12"
26
27 function handle_request(env)
28         local renv = {
29                 CONTENT_LENGTH  = env.CONTENT_LENGTH,
30                 CONTENT_TYPE    = env.CONTENT_TYPE,
31                 REQUEST_METHOD  = env.REQUEST_METHOD,
32                 REQUEST_URI     = env.REQUEST_URI,
33                 PATH_INFO       = env.PATH_INFO,
34                 SCRIPT_NAME     = env.SCRIPT_NAME:gsub("/+$", ""),
35                 SCRIPT_FILENAME = env.SCRIPT_NAME,
36                 SERVER_PROTOCOL = env.SERVER_PROTOCOL,
37                 QUERY_STRING    = env.QUERY_STRING
38         }
39
40         local k, v
41         for k, v in pairs(env.headers) do
42                 k = k:upper():gsub("%-", "_")
43                 renv["HTTP_" .. k] = v
44         end
45
46         local len = env.CONTENT_LENGTH or 0
47         local function recv()
48                 if len > 0 then
49                         local rlen, rbuf = uhttpd.recv(4096)
50                         if rlen >= 0 then
51                                 len = len - rlen
52                                 return rbuf
53                         end
54                 end
55                 return nil
56         end
57
58         local function send(...)
59                 return uhttpd.send(...)
60         end
61
62         local function sendc(...)
63                 if env.HTTP_VERSION > 1.0 then
64                         return uhttpd.sendc(...)
65                 else
66                         return uhttpd.send(...)
67                 end
68         end
69
70         local req = luci.http.Request(
71                 renv, recv, luci.ltn12.sink.file(io.stderr)
72         )
73         
74
75         local x = coroutine.create(luci.dispatcher.httpdispatch)
76         local hcache = { }
77         local active = true
78
79         if env.HTTP_VERSION > 1.0 then
80                 hcache["Transfer-Encoding"] = "chunked"
81         end
82
83         while coroutine.status(x) ~= "dead" do
84                 local res, id, data1, data2 = coroutine.resume(x, req)
85
86                 if not res then
87                         send(env.SERVER_PROTOCOL)
88                         send(" 500 Internal Server Error\r\n")
89                         send("Content-Type: text/plain\r\n\r\n")
90                         send(tostring(id))
91                         break
92                 end
93
94                 if active then
95                         if id == 1 then
96                                 send(env.SERVER_PROTOCOL)
97                                 send(" ")
98                                 send(tostring(data1))
99                                 send(" ")
100                                 send(tostring(data2))
101                                 send("\r\n")
102                         elseif id == 2 then
103                                 hcache[data1] = data2
104                         elseif id == 3 then
105                                 for k, v in pairs(hcache) do
106                                         send(tostring(k))
107                                         send(": ")
108                                         send(tostring(v))
109                                         send("\r\n")
110                                 end
111                                 send("\r\n")
112                         elseif id == 4 then
113                                 sendc(tostring(data1 or ""))
114                         elseif id == 5 then
115                                 active = false
116                         elseif id == 6 then
117                                 data1:copyz(nixio.stdout, data2)
118                         end
119                 end
120         end
121 end