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):

Impressum / About Us