9155e93f54ec31b9fa8054bc55d4a1b45a166db3
[project/luci.git] / libs / httpd / luasrc / httpd / server.lua
1 --[[
2
3 HTTP server implementation for LuCI - helper class
4 (c) 2008 Freifunk Leipzig / Jo-Philipp Wich <xm@leipzig.freifunk.net>
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 $Id$
13
14 ]]--
15
16 module("luci.httpd.server", package.seeall)
17
18
19 MAX_CLIENTS  = 15
20 READ_BUFSIZE = 1024
21
22
23 function error400( client, msg )
24         client:send( "HTTP/1.0 400 Bad request\r\n" )
25         client:send( "Content-Type: text/plain\r\n\r\n" )
26
27         if msg then
28                 client:send( msg .. "\r\n" )
29         end
30
31         client:close()
32 end
33
34 function error503( client )
35         client:send( "HTTP/1.0 503 Server unavailable\r\n" )
36         client:send( "Content-Type: text/plain\r\n\r\n" )
37         client:send( "There are too many clients connected, try again later\r\n" )
38         client:close()
39 end
40
41
42 function client_handler(client)
43
44         client:settimeout( 0 )
45
46         -- Create LTN12 block source
47         local block_source = function()
48
49                 coroutine.yield()
50
51                 local chunk, err, part = client:receive( READ_BUFSIZE )
52
53                 if chunk == nil and err == "timeout" then
54                         return part
55                 elseif chunk ~= nil then
56                         return chunk
57                 else
58                         return nil, err
59                 end
60
61         end
62
63         -- Create LTN12 line source
64         local line_source = ltn12.source.simplify( function()
65
66                 coroutine.yield()
67
68                 local chunk, err, part = client:receive("*l")
69
70                 -- Line too long
71                 if chunk == nil and err ~= "timeout" then
72
73                         return nil, part
74                                 and "Line exceeds maximum allowed length["..part.."]"
75                                 or  "Unexpected EOF"
76
77                 -- Line ok
78                 else
79
80                         -- Strip trailing CR
81                         chunk = chunk:gsub("\r$","")
82
83                         -- We got end of headers, switch to dummy source
84                         if #chunk == 0 then
85                                 return "", function()
86                                         return nil
87                                 end
88                         else
89                                 return chunk, nil
90                         end
91                 end
92         end )
93
94         coroutine.yield(client)
95
96
97         -- parse message
98         local message, err = luci.http.protocol.parse_message_header( line_source )
99
100         if message then
101
102                 -- If we have a HTTP/1.1 client and an Expect: 100-continue header then
103                 -- respond with HTTP 100 Continue message
104                 if message.http_version == 1.1 and message.headers['Expect'] and
105                         message.headers['Expect'] == '100-continue'
106                 then
107                         client:send("HTTP/1.1 100 Continue\r\n\r\n")
108                 end
109
110
111                 local s, e = luci.http.protocol.parse_message_body( block_source, message )
112
113                 -- XXX: debug
114                 luci.util.dumptable( message )
115
116                 if not s and e then
117                         error400( client, e )
118                 end
119         else
120                 error400( client, err )
121         end
122
123         -- send response
124         error400( client, "Dummy response" )
125 end