From d095fb09d3783d7891ebbaa4b20cefb0b8d1618f Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 10:08:35 +0800 Subject: luacheckrc: make test helpers read-only globals, add testlib_new_env and runtest --- .luacheckrc | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 2fc05e75..0da4a0e7 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -11,13 +11,15 @@ files["plugins/"] = { ignore = { "122/module" }; } files["tests/"] = { - ignore = { - "113/assert_equal", - "113/assert_table", - "113/assert_function", - "113/assert_string", - "113/assert_boolean", - "113/assert_is", - "113/assert_is_not", + read_globals = { + "testlib_new_env", + "assert_equal", + "assert_table", + "assert_function", + "assert_string", + "assert_boolean", + "assert_is", + "assert_is_not", + "runtest", }; } -- cgit v1.2.3 From a70183bcec1791c55df3679773c0d3a46e94c777 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 10:17:00 +0800 Subject: luacheckrc: make module a global in plugins/ --- .luacheckrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index 0da4a0e7..90d2e273 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -8,7 +8,7 @@ codes = true ignore = { "411/err", "421/err", "411/ok", "421/ok", "211/_ENV" } files["plugins/"] = { - ignore = { "122/module" }; + globals = { "module" }; } files["tests/"] = { read_globals = { -- cgit v1.2.3 From 8320418d385a874beac20693e1f0f64716c0c485 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 10:26:18 +0800 Subject: net.dns: don't use "for s,s in pairs..." (unused loop variable s) [luacheck] --- net/dns.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/dns.lua b/net/dns.lua index 4a35fc1b..726b2b80 100644 --- a/net/dns.lua +++ b/net/dns.lua @@ -1011,7 +1011,7 @@ end function resolver.print(response) -- - - - - - - - - - - - - resolver.print - for s,s in pairs { 'id', 'qr', 'opcode', 'aa', 'tc', 'rd', 'ra', 'z', + for _, s in pairs { 'id', 'qr', 'opcode', 'aa', 'tc', 'rd', 'ra', 'z', 'rcode', 'qdcount', 'ancount', 'nscount', 'arcount' } do print( string.format('%-30s', 'header.'..s), response.header[s], hint(response.header, s) ); end @@ -1024,7 +1024,7 @@ function resolver.print(response) -- - - - - - - - - - - - - resolver.print local common = { name=1, type=1, class=1, ttl=1, rdlength=1, rdata=1 }; local tmp; - for s,s in pairs({'answer', 'authority', 'additional'}) do + for _, s in pairs({'answer', 'authority', 'additional'}) do for i,rr in pairs(response[s]) do for j,t in pairs({ 'name', 'type', 'class', 'ttl', 'rdlength' }) do tmp = string.format('%s[%i].%s', s, i, t); -- cgit v1.2.3 From 416f381c39bfe659428c6398d8499674b79bd4b8 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 10:27:57 +0800 Subject: util.ip: remove unused one-letter loop variables [luacheck] --- util/ip.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/ip.lua b/util/ip.lua index ec3b4d7e..1f32d1b5 100644 --- a/util/ip.lua +++ b/util/ip.lua @@ -51,11 +51,11 @@ local function toBits(ip) if not ip:match(":$") then fields[#fields] = nil; end for i, field in ipairs(fields) do if field:len() == 0 and i ~= 1 and i ~= #fields then - for i = 1, 16 * (9 - #fields) do + for _ = 1, 16 * (9 - #fields) do result = result .. "0"; end else - for i = 1, 4 - field:len() do + for _ = 1, 4 - field:len() do result = result .. "0000"; end for i = 1, field:len() do -- cgit v1.2.3 From f710b07b55aacbd2b375a6a04251565ee4f58936 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 13:52:04 +0800 Subject: util.openssl: remove unused one-letter loop variable [luacheck] --- util/openssl.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/openssl.lua b/util/openssl.lua index 33234a7d..abd90a84 100644 --- a/util/openssl.lua +++ b/util/openssl.lua @@ -70,7 +70,7 @@ function ssl_config:serialize() end end elseif k == "distinguished_name" then - for i, k in ipairs(t[1] and t or DN_order) do + for _, k in ipairs(t[1] and t or DN_order) do local v = t[k]; if v then s = s .. ("%s = %s\n"):format(k, v); -- cgit v1.2.3 From 7ebb2bd49371e1d8f3f1382a3883e3570de2543d Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 13:52:57 +0800 Subject: prosodyctl: remove unused one-letter loop variable [luacheck] --- prosodyctl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prosodyctl b/prosodyctl index 226ff2cf..34a67e68 100755 --- a/prosodyctl +++ b/prosodyctl @@ -717,7 +717,7 @@ function cert_commands.config(arg) else show_message("Please provide details to include in the certificate config file."); show_message("Leave the field empty to use the default value or '.' to exclude the field.") - for i, k in ipairs(openssl._DN_order) do + for _, k in ipairs(openssl._DN_order) do local v = conf.distinguished_name[k]; if v then local nv; -- cgit v1.2.3 From 7a73da002f1103255298713d97365ae16452ac28 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 17:30:23 +0800 Subject: test_util_cache: remove unused argument c3 [luacheck] --- tests/test_util_cache.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_util_cache.lua b/tests/test_util_cache.lua index 78666edc..dea1bf4c 100644 --- a/tests/test_util_cache.lua +++ b/tests/test_util_cache.lua @@ -219,7 +219,7 @@ function new(new) local evicted_key, evicted_value; - local c3 = new(1, function (_key, _value, c3) + local c3 = new(1, function (_key, _value) evicted_key, evicted_value = _key, _value; if _key == "a" then -- Sanity check for what we're evicting -- cgit v1.2.3 From b1cda685448c51b911ea5f6b9c7714088dd38ef0 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 17:30:56 +0800 Subject: test_util_cache: rename a variable (c is already defined) [luacheck] --- tests/test_util_cache.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_util_cache.lua b/tests/test_util_cache.lua index dea1bf4c..cbc60bc7 100644 --- a/tests/test_util_cache.lua +++ b/tests/test_util_cache.lua @@ -196,12 +196,12 @@ function new(new) assert_equal(i, 4); local evicted_key, evicted_value; - local c = new(3, function (_key, _value) + local c2 = new(3, function (_key, _value) evicted_key, evicted_value = _key, _value; end); local function set(k, v, should_evict_key, should_evict_value) evicted_key, evicted_value = nil, nil; - c:set(k, v); + c2:set(k, v); assert_equal(evicted_key, should_evict_key); assert_equal(evicted_value, should_evict_value); end -- cgit v1.2.3 From 1e78e0f2365dcf25ff5fb863afc783ebc158ad9b Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 17:33:38 +0800 Subject: util.ip: rename variable (i is already defined) [luacheck] --- util/ip.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util/ip.lua b/util/ip.lua index 1f32d1b5..81a98ef7 100644 --- a/util/ip.lua +++ b/util/ip.lua @@ -58,8 +58,8 @@ local function toBits(ip) for _ = 1, 4 - field:len() do result = result .. "0000"; end - for i = 1, field:len() do - result = result .. hex2bits[field:sub(i,i)]; + for j = 1, field:len() do + result = result .. hex2bits[field:sub(j, j)]; end end end -- cgit v1.2.3 From b33e46e4acf543c1c3b2f72ad3da28a2873e1b97 Mon Sep 17 00:00:00 2001 From: Anton Shestakov Date: Sat, 9 Jul 2016 21:55:37 +0800 Subject: mod_http_files: send valid ETag header RFC 2616 section 14 (header field definitions) shows that ETag header content should be wrapped in double quotes. --- plugins/mod_http_files.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index 3b602495..40f46c9c 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -109,7 +109,7 @@ function serve(opts) local last_modified = os_date('!%a, %d %b %Y %H:%M:%S GMT', attr.modification); response_headers.last_modified = last_modified; - local etag = ("%02x-%x-%x-%x"):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0); + local etag = ('"%02x-%x-%x-%x"'):format(attr.dev or 0, attr.ino or 0, attr.size or 0, attr.modification or 0); response_headers.etag = etag; local if_none_match = request_headers.if_none_match -- cgit v1.2.3 From 99ba4462fc442388fc425c00792b1207101ed5bb Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 Jul 2016 11:52:43 +0200 Subject: net.http.server: Add response method for reading response body from a file handle --- net/http/server.lua | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/net/http/server.lua b/net/http/server.lua index aeaa7416..bc39767f 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -13,10 +13,12 @@ local traceback = debug.traceback; local tostring = tostring; local cache = require "util.cache"; local codes = require "net.http.codes"; +local blocksize = require "socket".BLOCKSIZE or 2048; local _M = {}; local sessions = {}; +local incomplete = {}; local listener = {}; local hosts = {}; local default_host; @@ -140,17 +142,26 @@ function listener.ondisconnect(conn) open_response.finished = true; open_response:on_destroy(); end + incomplete[conn] = nil; sessions[conn] = nil; end function listener.ondetach(conn) sessions[conn] = nil; + incomplete[conn] = nil; end function listener.onincoming(conn, data) sessions[conn]:feed(data); end +function listener.ondrain(conn) + local response = incomplete[conn]; + if response and response._send_more then + response._send_more(); + end +end + local headerfix = setmetatable({}, { __index = function(t, k) local v = "\r\n"..k:gsub("_", "-"):gsub("%f[%w].", s_upper)..": "; @@ -190,6 +201,7 @@ function handle_request(conn, request, finish_cb) persistent = persistent; conn = conn; send = _M.send_response; + send_file = _M.send_file; done = _M.finish_response; finish_cb = finish_cb; }; @@ -272,6 +284,36 @@ function _M.send_response(response, body) response.conn:write(t_concat(output)); response:done(); end +function _M.send_file(response, f) + if response.finished then return; end + local chunked = not response.headers.content_length; + if chunked then response.headers.transfer_encoding = "chunked"; end + incomplete[response.conn] = response; + response._send_more = function () + if response.finished then + incomplete[response.conn] = nil; + return; + end + local chunk = f:read(blocksize); + if chunk then + if chunked then + chunk = ("%x\r\n%s\r\n"):format(#chunk, chunk); + end + -- io.write("."); io.flush(); + response.conn:write(chunk); + else + if chunked then + response.conn:write("0\r\n\r\n"); + end + -- io.write("\n"); + if f.close then f:close(); end + incomplete[response.conn] = nil; + return response:done(); + end + end + response.conn:write(t_concat(prepare_header(response))); + return true; +end function _M.finish_response(response) if response.finished then return; end response.finished = true; -- cgit v1.2.3 From 1d46e953aad489bcf2e718b7d140ab79d1879204 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 Jul 2016 12:17:59 +0200 Subject: mod_http_files: Switch to use util.cache for cache --- plugins/mod_http_files.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index 40f46c9c..a710679b 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -17,6 +17,7 @@ local build_path = require"socket.url".build_path; local path_sep = package.config:sub(1,1); local base_path = module:get_option_string("http_files_dir", module:get_option_string("http_path")); +local cache_size = module:get_option_number("http_files_cache_size", 128); local dir_indices = module:get_option("http_index_files", { "index.html", "index.htm" }); local directory_index = module:get_option_boolean("http_dir_listing"); @@ -81,7 +82,7 @@ function sanitize_path(path) return "/"..table.concat(out, "/"); end -local cache = setmetatable({}, { __mode = "kv" }); -- Let the garbage collector have it if it wants to. +local cache = require "util.cache".new(cache_size); function serve(opts) if type(opts) ~= "table" then -- assume path string @@ -119,7 +120,7 @@ function serve(opts) return 304; end - local data = cache[orig_path]; + local data = cache:get(orig_path); if data and data.etag == etag then response_headers.content_type = data.content_type; data = data.data; @@ -157,7 +158,7 @@ function serve(opts) end local ext = full_path:match("%.([^./]+)$"); local content_type = ext and mime_map[ext]; - cache[orig_path] = { data = data; content_type = content_type; etag = etag }; + cache:set(orig_path, { data = data; content_type = content_type; etag = etag }); response_headers.content_type = content_type; end -- cgit v1.2.3 From 2d847c082f71f7a0e80d9c18f9ca5fec1096541a Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Mon, 11 Jul 2016 12:20:25 +0200 Subject: mod_http_files: Send larger files using new file handle API --- plugins/mod_http_files.lua | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/plugins/mod_http_files.lua b/plugins/mod_http_files.lua index a710679b..ab2f3966 100644 --- a/plugins/mod_http_files.lua +++ b/plugins/mod_http_files.lua @@ -18,6 +18,7 @@ local path_sep = package.config:sub(1,1); local base_path = module:get_option_string("http_files_dir", module:get_option_string("http_path")); local cache_size = module:get_option_number("http_files_cache_size", 128); +local cache_max_file_size = module:get_option_number("http_files_cache_max_file_size", 4096); local dir_indices = module:get_option("http_index_files", { "index.html", "index.htm" }); local directory_index = module:get_option_boolean("http_dir_listing"); @@ -148,18 +149,22 @@ function serve(opts) else local f, err = open(full_path, "rb"); - if f then - data, err = f:read("*a"); - f:close(); - end - if not data then - module:log("debug", "Could not open or read %s. Error was %s", full_path, err); + if not f then + module:log("debug", "Could not open %s. Error was %s", full_path, err); return 403; end local ext = full_path:match("%.([^./]+)$"); local content_type = ext and mime_map[ext]; - cache:set(orig_path, { data = data; content_type = content_type; etag = etag }); response_headers.content_type = content_type; + if attr.size > cache_max_file_size then + response_headers.content_length = attr.size; + module:log("debug", "%d > cache_max_file_size", attr.size); + return response:send_file(f); + else + data = f:read("*a"); + f:close(); + end + cache:set(orig_path, { data = data; content_type = content_type; etag = etag }); end return response:send(data); -- cgit v1.2.3 From 135071b7364ef0a93be023c38060e07a73923ad9 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 12 Jul 2016 10:39:04 +0200 Subject: mod_http_errors: Add a newline after end of HTML --- plugins/mod_http_errors.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/mod_http_errors.lua b/plugins/mod_http_errors.lua index 0c37e104..17d357e5 100644 --- a/plugins/mod_http_errors.lua +++ b/plugins/mod_http_errors.lua @@ -43,7 +43,8 @@ local html = [[

$message

$extra

-]]; + +]]; html = html:gsub("%s%s+", ""); local entities = { -- cgit v1.2.3 From a8523999b65f39d8a8a242f38bc825a5a6accd4d Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 12 Jul 2016 13:59:02 +0200 Subject: tests: Add basic test for net.http.parser --- tests/test.lua | 1 + tests/test_net_http_parser.lua | 47 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 tests/test_net_http_parser.lua diff --git a/tests/test.lua b/tests/test.lua index 9ab2cad8..78eb0134 100644 --- a/tests/test.lua +++ b/tests/test.lua @@ -27,6 +27,7 @@ function run_all_tests() dotest "util.random" dotest "util.xml" dotest "util.xmppstream" + dotest "net.http.parser" dosingletest("test_sasl.lua", "latin1toutf8"); dosingletest("test_utf8.lua", "valid"); diff --git a/tests/test_net_http_parser.lua b/tests/test_net_http_parser.lua new file mode 100644 index 00000000..1157b5ac --- /dev/null +++ b/tests/test_net_http_parser.lua @@ -0,0 +1,47 @@ +local httpstreams = { [[ +GET / HTTP/1.1 +Host: example.com + +]], [[ +HTTP/1.1 200 OK +Content-Length: 0 + +]], [[ +HTTP/1.1 200 OK +Content-Length: 7 + +Hello +HTTP/1.1 200 OK +Transfer-Encoding: chunked + +1 +H +1 +e +2 +ll +1 +o +0 + + +]] +} + +function new(new) + + for _, stream in ipairs(httpstreams) do + local success; + local function success_cb(packet) + success = true; + end + stream = stream:gsub("\n", "\r\n"); + local parser = new(success_cb, error, stream:sub(1,4) == "HTTP" and "client" or "server") + for chunk in stream:gmatch("..?.?") do + parser:feed(chunk); + end + + assert_is(success); + end + +end -- cgit v1.2.3