From d3a6c7549a1a8c5def068d2f2dc8cda8943fbdb3 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 13 Aug 2016 15:09:43 +0200 Subject: net.http.parser: Remove unused argument [luacheck] --- net/http/parser.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http') diff --git a/net/http/parser.lua b/net/http/parser.lua index 6d7187da..70df6513 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -35,7 +35,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) local have_body; local error; return { - feed = function(self, data) + feed = function(_, data) if error then return nil, "parse has failed"; end if not data then -- EOF if state and client and not len then -- reading client body until EOF -- cgit v1.2.3 From 96e44863cf8d6bad4feb1d22954906f0629cfb89 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 13 Aug 2016 16:10:17 +0200 Subject: net.http.codes: Remove used argument --- net/http/codes.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http') diff --git a/net/http/codes.lua b/net/http/codes.lua index bc31c7dd..1801c6b3 100644 --- a/net/http/codes.lua +++ b/net/http/codes.lua @@ -70,4 +70,4 @@ local response_codes = { }; for k,v in pairs(response_codes) do response_codes[k] = k.." "..v; end -return setmetatable(response_codes, { __index = function(t, k) return k.." Unassigned"; end }) +return setmetatable(response_codes, { __index = function(_, k) return k.." Unassigned"; end }) -- cgit v1.2.3 From 8165818e268f3995d34bdd5f4fcf61ff196446ae Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 13 Aug 2016 16:11:30 +0200 Subject: net.http.codes: Add HTTP status code 451 Unavailable For Legal Reasons from RFC 7725 --- net/http/codes.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'net/http') diff --git a/net/http/codes.lua b/net/http/codes.lua index 1801c6b3..1090e545 100644 --- a/net/http/codes.lua +++ b/net/http/codes.lua @@ -55,6 +55,7 @@ local response_codes = { [428] = "Precondition Required"; [429] = "Too Many Requests"; [431] = "Request Header Fields Too Large"; + [451] = "Unavailable For Legal Reasons"; [500] = "Internal Server Error"; [501] = "Not Implemented"; -- cgit v1.2.3 From 6bfab345b90ad62ff64a5aba8342fa500669fd1b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 13 Aug 2016 20:19:08 +0200 Subject: net.http.parser: Buffer into a table to reduce GC pressure, collapse to string when needed (fixes #603) --- net/http/parser.lua | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'net/http') diff --git a/net/http/parser.lua b/net/http/parser.lua index 6d7187da..af43e7a0 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -1,5 +1,6 @@ local tonumber = tonumber; local assert = assert; +local t_insert, t_concat = table.insert, table.concat; local url_parse = require "socket.url".parse; local urldecode = require "util.http".urldecode; @@ -27,7 +28,7 @@ local httpstream = {}; function httpstream.new(success_cb, error_cb, parser_type, options_cb) local client = true; if not parser_type or parser_type == "server" then client = false; else assert(parser_type == "client", "Invalid parser type"); end - local buf = ""; + local buf, buflen, buftable = {}, 0, true; local chunked, chunk_size, chunk_start; local state = nil; local packet; @@ -38,6 +39,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) feed = function(self, data) if error then return nil, "parse has failed"; end if not data then -- EOF + if buftable then buf, buftable = t_concat(buf), false; end if state and client and not len then -- reading client body until EOF packet.body = buf; success_cb(packet); @@ -46,9 +48,16 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) end return; end - buf = buf..data; - while #buf > 0 do + if buftable then + t_insert(buf, data); + else + buf = { buf, data }; + buftable = true; + end + buflen = buflen + #data; + while buflen > 0 do if state == nil then -- read request + if buftable then buf, buftable = t_concat(buf), false; end local index = buf:find("\r\n\r\n", nil, true); if not index then return; end -- not enough data local method, path, httpversion, status_code, reason_phrase; @@ -115,11 +124,13 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) }; end buf = buf:sub(index + 4); + buflen = #buf; state = true; end if state then -- read body if client then if chunked then + if buftable then buf, buftable = t_concat(buf), false; end if not buf:find("\r\n", nil, true) then return; end -- not enough data @@ -132,25 +143,29 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) state, chunk_size = nil, nil; buf = buf:gsub("^.-\r\n\r\n", ""); -- This ensure extensions and trailers are stripped success_cb(packet); - elseif #buf - chunk_start - 2 >= chunk_size then -- we have a chunk + elseif buflen - chunk_start - 2 >= chunk_size then -- we have a chunk packet.body = packet.body..buf:sub(chunk_start, chunk_start + (chunk_size-1)); buf = buf:sub(chunk_start + chunk_size + 2); chunk_size, chunk_start = nil, nil; else -- Partial chunk remaining break; end - elseif len and #buf >= len then + elseif len and buflen >= len then + if buftable then buf, buftable = t_concat(buf), false; end if packet.code == 101 then - packet.body, buf = buf, ""; + packet.body, buf, buflen, buftable = buf, {}, 0, true; else packet.body, buf = buf:sub(1, len), buf:sub(len + 1); + buflen = #buf; end state = nil; success_cb(packet); else break; end - elseif #buf >= len then + elseif buflen >= len then + if buftable then buf, buftable = t_concat(buf), false; end packet.body, buf = buf:sub(1, len), buf:sub(len + 1); + buflen = #buf; state = nil; success_cb(packet); else break; -- cgit v1.2.3 From 3f97ca99c3f49c9204e8d4e4b4bd4e12c9d7bb60 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 18 Aug 2016 14:47:58 +0200 Subject: net.http.parser: Add a limit on content length, default to 10M --- net/http/parser.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/http') diff --git a/net/http/parser.lua b/net/http/parser.lua index af43e7a0..0f764d12 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -29,6 +29,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) local client = true; if not parser_type or parser_type == "server" then client = false; else assert(parser_type == "client", "Invalid parser type"); end local buf, buflen, buftable = {}, 0, true; + local bodylimit = 10*1024*1024; local chunked, chunk_size, chunk_start; local state = nil; local packet; @@ -88,6 +89,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) if not first_line then error = true; return error_cb("invalid-status-line"); end chunked = have_body and headers["transfer-encoding"] == "chunked"; len = tonumber(headers["content-length"]); -- TODO check for invalid len + if len and len > bodylimit then error = true; return error_cb("content-length-limit-exceeded"); end if client then -- FIXME handle '100 Continue' response (by skipping it) if not have_body then len = 0; end -- cgit v1.2.3 From 113551b7c8f605334985db178480770a19aa5773 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 18 Aug 2016 14:48:42 +0200 Subject: net.http.parser: Add a limit on maximum buffer size, default to 20M --- net/http/parser.lua | 2 ++ 1 file changed, 2 insertions(+) (limited to 'net/http') diff --git a/net/http/parser.lua b/net/http/parser.lua index 0f764d12..e3a2554f 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -30,6 +30,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) if not parser_type or parser_type == "server" then client = false; else assert(parser_type == "client", "Invalid parser type"); end local buf, buflen, buftable = {}, 0, true; local bodylimit = 10*1024*1024; + local buflimit = bodylimit * 2; local chunked, chunk_size, chunk_start; local state = nil; local packet; @@ -56,6 +57,7 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) buftable = true; end buflen = buflen + #data; + if buflen > buflimit then error = true; return error_cb("max-buffer-size-exceeded"); end while buflen > 0 do if state == nil then -- read request if buftable then buf, buftable = t_concat(buf), false; end -- cgit v1.2.3 From c3ed1636820fde85ab0d9ce0e84f6d01d5bd950a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 18 Aug 2016 14:50:06 +0200 Subject: net.http.parser: Allow limits to be configurable via options callback --- net/http/parser.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/http') diff --git a/net/http/parser.lua b/net/http/parser.lua index e3a2554f..1e698728 100644 --- a/net/http/parser.lua +++ b/net/http/parser.lua @@ -29,8 +29,8 @@ function httpstream.new(success_cb, error_cb, parser_type, options_cb) local client = true; if not parser_type or parser_type == "server" then client = false; else assert(parser_type == "client", "Invalid parser type"); end local buf, buflen, buftable = {}, 0, true; - local bodylimit = 10*1024*1024; - local buflimit = bodylimit * 2; + local bodylimit = tonumber(options_cb and options_cb().body_size_limit) or 10*1024*1024; + local buflimit = tonumber(options_cb and options_cb().buffer_size_limit) or bodylimit * 2; local chunked, chunk_size, chunk_start; local state = nil; local packet; -- cgit v1.2.3 From 369c2c05506cac2e96e972ea540c91da2bc05982 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 18 Aug 2016 14:50:39 +0200 Subject: net.http.server: Expose way to set http server options --- net/http/server.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'net/http') diff --git a/net/http/server.lua b/net/http/server.lua index f091595c..32cda8aa 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -19,6 +19,7 @@ local sessions = {}; local listener = {}; local hosts = {}; local default_host; +local options = {}; local function is_wildcard_event(event) return event:sub(-2, -1) == "/*"; @@ -130,7 +131,10 @@ function listener.onconnect(conn) sessions[conn] = nil; conn:close(); end - sessions[conn] = parser_new(success_cb, error_cb); + local function options_cb() + return options; + end + sessions[conn] = parser_new(success_cb, error_cb, "server", options_cb); end function listener.ondisconnect(conn) @@ -300,6 +304,9 @@ end function _M.fire_event(event, ...) return events.fire_event(event, ...); end +function _M.set_option(name, value) + options[name] = value; +end _M.listener = listener; _M.codes = codes; -- cgit v1.2.3 From 33a8994b3cf6aabe428b7cdf6bba7bdf68d9c366 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Thu, 18 Aug 2016 15:21:30 +0200 Subject: net.http.server: Add luacheck annotations --- net/http/server.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/http') diff --git a/net/http/server.lua b/net/http/server.lua index 93bbffb4..8aa28f5c 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -32,7 +32,7 @@ local function is_wildcard_match(wildcard_event, event) end local _handlers = events._handlers; -local recent_wildcard_events = cache.new(10000, function (key, value) +local recent_wildcard_events = cache.new(10000, function (key, value) -- luacheck: ignore 212/value rawset(_handlers, key, nil); end); @@ -174,7 +174,7 @@ local headerfix = setmetatable({}, { end }); -function _M.hijack_response(response, listener) +function _M.hijack_response(response, listener) -- luacheck: ignore error("TODO"); end function handle_request(conn, request, finish_cb) -- cgit v1.2.3