moonbridge
diff moonbridge_http.lua @ 156:0c4221702ce1
Further work on new HTTP layer (read body, without parsing yet)
author | jbe |
---|---|
date | Tue May 26 02:06:17 2015 +0200 (2015-05-26) |
parents | 2c22b0f222c7 |
children | 99a70d18e47c |
line diff
1.1 --- a/moonbridge_http.lua Mon May 25 02:28:34 2015 +0200 1.2 +++ b/moonbridge_http.lua Tue May 26 02:06:17 2015 +0200 1.3 @@ -140,6 +140,7 @@ 1.4 self._input_chunk_size = options.maximum_input_chunk_size or options.chunk_size or 16384 1.5 self._output_chunk_size = options.minimum_output_chunk_size or options.chunk_size or 1024 1.6 self._header_size_limit = options.header_size_limit or 1024*1024 1.7 + self._body_size_limit = options.body_size_limit or 64*1024*1024 1.8 local function init_timeout(name, default) 1.9 local value = options[name] 1.10 if value == nil then 1.11 @@ -449,6 +450,89 @@ 1.12 end 1.13 end 1.14 1.15 +function request_pt:_read_body() 1.16 + self:_assert_not_faulty() 1.17 + local remaining = self._body_size_limit 1.18 + if request.headers_flags["Transfer-Encoding"]["chunked"] then 1.19 + while true do 1.20 + local line, status = self:_read(32 + remaining, "\n") 1.21 + if status == "maxlen" then 1.22 + self:_error("400 Bad Request", "Request body size limit exceeded") 1.23 + return false 1.24 + elseif status == "eof" then 1.25 + self:_error("400 Bad Request", "Encoding error or unexpected EOF while reading next chunk of request body") 1.26 + return false 1.27 + end 1.28 + local zeros, lenstr = string.match(line, "^(0*)([1-9A-Fa-f]+[0-9A-Fa-f]*)\r?\n$") 1.29 + local chunkext 1.30 + if lenstr then 1.31 + chunkext = "" 1.32 + else 1.33 + zeros, lenstr, chunkext = string.match(line, "^(0*)([1-9A-Fa-f]+[0-9A-Fa-f]*)([ \t;].-)\r?\n$") 1.34 + end 1.35 + if not lenstr or #lenstr > 13 then 1.36 + self:_error("400 Bad Request", "Encoding error while reading chunk of request body") 1.37 + return false 1.38 + end 1.39 + local len = tonumber("0x" .. lenstr) 1.40 + remaining = remaining - (#zeros + #chunkext + len) 1.41 + if remaining < 0 then 1.42 + self:_error("400 Bad Request", "Request body size limit exceeded") 1.43 + return false 1.44 + end 1.45 + if len == 0 then break end 1.46 + if self:_read_body_bytes(len) == false then 1.47 + return false 1.48 + end 1.49 + local term, status = self:_read(2, "\n") 1.50 + if status == "eof" then 1.51 + self:_error("400 Bad Request", "Unexpected EOF while reading next chunk of request body") 1.52 + return false 1.53 + end 1.54 + if term ~= "\r\n" and term ~= "\n" then 1.55 + self:_error("400 Bad Request", "Encoding error while reading chunk of request body") 1.56 + return false 1.57 + end 1.58 + end 1.59 + while true do 1.60 + local line, status = self:_read(2 + remaining, "\n") 1.61 + if status == "eof" then 1.62 + self:_error("400 Bad Request", "Unexpected EOF while reading chunk of request body") 1.63 + return false 1.64 + end 1.65 + if line == "\r\n" or line == "\n" then break end 1.66 + remaining = remaining - #line 1.67 + if remaining < 0 then 1.68 + request_error(true, "413 Request Entity Too Large", "Request body size limit exceeded while reading trailer section of chunked request body") 1.69 + end 1.70 + end 1.71 + elseif request_body_content_length then 1.72 + if self._read_body_bytes(request_body_content_length) == false then 1.73 + return false 1.74 + end 1.75 + end 1.76 +end 1.77 + 1.78 +function request_pt:_read_body_bytes(remaining, callback) 1.79 + while remaining > 0 do 1.80 + local limit 1.81 + if remaining > self._input_chunk_size then 1.82 + limit = self._input_chunk_size 1.83 + else 1.84 + limit = remaining 1.85 + end 1.86 + local chunk, status = self:_read(limit) 1.87 + if status == "eof" then 1.88 + self:_error("400 Bad Request", "Unexpected EOF while reading chunk of request body") 1.89 + return false 1.90 + end 1.91 + remaining = remaining - limit 1.92 + if self._body_streamer then 1.93 + self._body_streamer(chunk) 1.94 + end 1.95 + end 1.96 +end 1.97 + 1.98 function request_pt:_assert_not_faulty() 1.99 assert(not self._faulty, "Tried to use faulty request handle") 1.100 end