# HG changeset patch # User jbe # Date 1432598777 -7200 # Node ID 0c4221702ce17876b2e3faf20c6fe003462a2133 # Parent 2c22b0f222c76d22bf5d9e60d4dbaa36e1d7cf6a Further work on new HTTP layer (read body, without parsing yet) diff -r 2c22b0f222c7 -r 0c4221702ce1 moonbridge_http.lua --- a/moonbridge_http.lua Mon May 25 02:28:34 2015 +0200 +++ b/moonbridge_http.lua Tue May 26 02:06:17 2015 +0200 @@ -140,6 +140,7 @@ self._input_chunk_size = options.maximum_input_chunk_size or options.chunk_size or 16384 self._output_chunk_size = options.minimum_output_chunk_size or options.chunk_size or 1024 self._header_size_limit = options.header_size_limit or 1024*1024 + self._body_size_limit = options.body_size_limit or 64*1024*1024 local function init_timeout(name, default) local value = options[name] if value == nil then @@ -449,6 +450,89 @@ end end +function request_pt:_read_body() + self:_assert_not_faulty() + local remaining = self._body_size_limit + if request.headers_flags["Transfer-Encoding"]["chunked"] then + while true do + local line, status = self:_read(32 + remaining, "\n") + if status == "maxlen" then + self:_error("400 Bad Request", "Request body size limit exceeded") + return false + elseif status == "eof" then + self:_error("400 Bad Request", "Encoding error or unexpected EOF while reading next chunk of request body") + return false + end + local zeros, lenstr = string.match(line, "^(0*)([1-9A-Fa-f]+[0-9A-Fa-f]*)\r?\n$") + local chunkext + if lenstr then + chunkext = "" + else + zeros, lenstr, chunkext = string.match(line, "^(0*)([1-9A-Fa-f]+[0-9A-Fa-f]*)([ \t;].-)\r?\n$") + end + if not lenstr or #lenstr > 13 then + self:_error("400 Bad Request", "Encoding error while reading chunk of request body") + return false + end + local len = tonumber("0x" .. lenstr) + remaining = remaining - (#zeros + #chunkext + len) + if remaining < 0 then + self:_error("400 Bad Request", "Request body size limit exceeded") + return false + end + if len == 0 then break end + if self:_read_body_bytes(len) == false then + return false + end + local term, status = self:_read(2, "\n") + if status == "eof" then + self:_error("400 Bad Request", "Unexpected EOF while reading next chunk of request body") + return false + end + if term ~= "\r\n" and term ~= "\n" then + self:_error("400 Bad Request", "Encoding error while reading chunk of request body") + return false + end + end + while true do + local line, status = self:_read(2 + remaining, "\n") + if status == "eof" then + self:_error("400 Bad Request", "Unexpected EOF while reading chunk of request body") + return false + end + if line == "\r\n" or line == "\n" then break end + remaining = remaining - #line + if remaining < 0 then + request_error(true, "413 Request Entity Too Large", "Request body size limit exceeded while reading trailer section of chunked request body") + end + end + elseif request_body_content_length then + if self._read_body_bytes(request_body_content_length) == false then + return false + end + end +end + +function request_pt:_read_body_bytes(remaining, callback) + while remaining > 0 do + local limit + if remaining > self._input_chunk_size then + limit = self._input_chunk_size + else + limit = remaining + end + local chunk, status = self:_read(limit) + if status == "eof" then + self:_error("400 Bad Request", "Unexpected EOF while reading chunk of request body") + return false + end + remaining = remaining - limit + if self._body_streamer then + self._body_streamer(chunk) + end + end +end + function request_pt:_assert_not_faulty() assert(not self._faulty, "Tried to use faulty request handle") end