moonbridge
changeset 157:99a70d18e47c
Further work on new HTTP layer (code cleanup, work on body reading)
author | jbe |
---|---|
date | Wed May 27 01:51:04 2015 +0200 (2015-05-27) |
parents | 0c4221702ce1 |
children | bd7225b30391 |
files | moonbridge_http.lua |
line diff
1.1 --- a/moonbridge_http.lua Tue May 26 02:06:17 2015 +0200 1.2 +++ b/moonbridge_http.lua Wed May 27 01:51:04 2015 +0200 1.3 @@ -260,9 +260,6 @@ 1.4 self._survive = true 1.5 self._socket_set = {[socket] = true} 1.6 self._faulty = false 1.7 - self._consume_input = self._drain_input 1.8 - self._headers = {} 1.9 - self._headers_value_nil = {} 1.10 self._connection_close_requested = false 1.11 self._connection_close_responded = false 1.12 self:_create_magictable("headers") 1.13 @@ -270,7 +267,6 @@ 1.14 self:_create_magictable("headers_csv_string") 1.15 self:_create_magictable("headers_value") 1.16 self:_create_magictable("headers_flags") 1.17 - self.cookies = {} 1.18 repeat 1.19 -- wait for input: 1.20 if not moonbridge_io.poll(self._socket_set, nil, self._request_idle_timeout) then 1.21 @@ -302,16 +298,48 @@ 1.22 end 1.23 end 1.24 end 1.25 + -- prepare reading of body: 1.26 + self._read_body_coro = coroutine.wrap(self._read_body) 1.27 + -- set timeout for application handler: 1.28 timeout(self._response_timeout or 0) 1.29 + -- call application handler: 1.30 if self._application_handler(self) ~= true then 1.31 self._survive = false 1.32 end 1.33 + -- enforce request:finish() 1.34 request:finish() 1.35 + -- reset timeout of application handler 1.36 timeout(0) 1.37 until self._connection_close_responded 1.38 return self._survive 1.39 end 1.40 1.41 +function request_pt:_drain_input() 1.42 + self._read_body_coro = "drain" 1.43 +end 1.44 + 1.45 +function request_pt:_consume_some_input() 1.46 + local coro = self._read_body_coro 1.47 + if coro == "drain" then 1.48 + local bytes, status = self._socket:drain_nb(self._input_chunk_size) 1.49 + if status == "eof" then 1.50 + coro = nil 1.51 + end 1.52 + elseif coro then 1.53 + local retval = coro(self) 1.54 + if retval ~= nil then 1.55 + coro = nil -- can't consume more data 1.56 + end 1.57 + end 1.58 +end 1.59 + 1.60 +function request_pt:_consume_all_input() 1.61 + while self._read_body_coro do 1.62 + self._poll(socket_set) 1.63 + self:_consume_some_input() 1.64 + end 1.65 +end 1.66 + 1.67 function request_pt:_error(status, explanation) 1.68 end 1.69 1.70 @@ -352,6 +380,8 @@ 1.71 end 1.72 end 1.73 -- read and parse headers: 1.74 + self._headers = {} 1.75 + self._headers_value_nil = {} 1.76 while true do 1.77 local line, status = self:_read(remaining, "\n"); 1.78 if status == "maxlen" then 1.79 @@ -433,6 +463,7 @@ 1.80 end 1.81 elseif not (target == "*" and self.method == "OPTIONS") then 1.82 self:_error("400 Bad Request", "Invalid request target") 1.83 + return false 1.84 end 1.85 end 1.86 -- parse GET params: 1.87 @@ -441,6 +472,7 @@ 1.88 self.get_params = get_first_values(self.get_params_list) 1.89 end 1.90 -- parse cookies: 1.91 + self.cookies = {} 1.92 for i, line in ipairs(self.headers["Cookie"]) do 1.93 for rawkey, rawvalue in 1.94 string.gmatch(line, "([^=; ]*)=([^=; ]*)") 1.95 @@ -448,10 +480,11 @@ 1.96 self.cookies[decode_uri(rawkey)] = decode_uri(rawvalue) 1.97 end 1.98 end 1.99 + -- indicate success: 1.100 + return true 1.101 end 1.102 1.103 function request_pt:_read_body() 1.104 - self:_assert_not_faulty() 1.105 local remaining = self._body_size_limit 1.106 if request.headers_flags["Transfer-Encoding"]["chunked"] then 1.107 while true do 1.108 @@ -503,7 +536,8 @@ 1.109 if line == "\r\n" or line == "\n" then break end 1.110 remaining = remaining - #line 1.111 if remaining < 0 then 1.112 - request_error(true, "413 Request Entity Too Large", "Request body size limit exceeded while reading trailer section of chunked request body") 1.113 + self:_error("413 Request Entity Too Large", "Request body size limit exceeded while reading trailer section of chunked request body") 1.114 + return false 1.115 end 1.116 end 1.117 elseif request_body_content_length then 1.118 @@ -511,6 +545,8 @@ 1.119 return false 1.120 end 1.121 end 1.122 + -- indicate success: 1.123 + return true 1.124 end 1.125 1.126 function request_pt:_read_body_bytes(remaining, callback) 1.127 @@ -531,6 +567,7 @@ 1.128 self._body_streamer(chunk) 1.129 end 1.130 end 1.131 + return true 1.132 end 1.133 1.134 function request_pt:_assert_not_faulty() 1.135 @@ -538,7 +575,7 @@ 1.136 end 1.137 1.138 function request_pt:_write_yield() 1.139 - self:_consume_input() 1.140 + self:_consume_some_input() 1.141 self._poll(self._socket_set, self._socket_set) 1.142 end 1.143 1.144 @@ -550,10 +587,6 @@ 1.145 assert(self._socket:write_call(self._write_yield_closure, ...)) 1.146 end 1.147 1.148 -function request_pt:_drain_input() 1.149 - socket:drain_nb(self._input_chunk_size) 1.150 -end 1.151 - 1.152 -- function creating a HTTP handler: 1.153 function generate_handler(handler, options) 1.154 -- swap arguments if necessary (for convenience):