From 89a6f8d8c108bdf633d7d6589c260de833c56bf5 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 12 Oct 2019 18:27:02 +0200 Subject: net.http.server: Ensure HEAD requests are sent with empty body --- net/http/server.lua | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 9b63d516..47680455 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -194,8 +194,11 @@ function handle_request(conn, request, finish_cb) response_conn_header = httpversion == "1.1" and "close" or nil end + local is_head_request = request.method == "HEAD"; + local response = { request = request; + is_head_request = is_head_request; status_code = 200; headers = { date = date_header, connection = response_conn_header }; persistent = persistent; @@ -291,16 +294,29 @@ local function prepare_header(response) return output; end _M.prepare_header = prepare_header; +function _M.send_head_response(response) + if response.finished then return; end + local output = prepare_header(response); + response.conn:write(t_concat(output)); + response:done(); +end function _M.send_response(response, body) if response.finished then return; end body = body or response.body or ""; response.headers.content_length = #body; + if response.is_head_request then + return _M.send_head_response(response) + end local output = prepare_header(response); t_insert(output, body); response.conn:write(t_concat(output)); response:done(); end function _M.send_file(response, f) + if response.is_head_request then + if f.close then f:close(); end + return _M.send_head_response(response); + end if response.finished then return; end local chunked = not response.headers.content_length; if chunked then response.headers.transfer_encoding = "chunked"; end -- cgit v1.2.3 From 8e485ec3200359adcc00731a371b4455d24bb562 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 12 Oct 2019 18:27:54 +0200 Subject: net.http.server: Re-fire unhandled HEAD requsts as GET events (fixes #1447) BC: This overloads the GET event. Previous commit ensures HEAD requests are sent without a body. --- net/http/server.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 47680455..b649ff5f 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -229,6 +229,11 @@ function handle_request(conn, request, finish_cb) local payload = { request = request, response = response }; log("debug", "Firing event: %s", global_event); local result = events.fire_event(global_event, payload); + if result == nil and is_head_request then + local global_head_event = "GET "..request.path:match("[^?]*"); + log("debug", "Firing event: %s", global_head_event); + result = events.fire_event(global_head_event, payload); + end if result == nil then if not hosts[host] then if hosts[default_host] then @@ -249,6 +254,12 @@ function handle_request(conn, request, finish_cb) local host_event = request.method.." "..host..request.path:match("[^?]*"); log("debug", "Firing event: %s", host_event); result = events.fire_event(host_event, payload); + + if result == nil and is_head_request then + local host_head_event = "GET "..host..request.path:match("[^?]*"); + log("debug", "Firing event: %s", host_head_event); + result = events.fire_event(host_head_event, payload); + end end if result ~= nil then if result ~= true then -- cgit v1.2.3 From 30a72c72a392fdbee1e91946c9a72ed88a20b232 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 12 Oct 2019 19:30:29 +0200 Subject: net.http.server: Explicitly convert number to string, avoiding implicit coercion --- net/http/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index b649ff5f..bf24c97e 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -314,7 +314,7 @@ end function _M.send_response(response, body) if response.finished then return; end body = body or response.body or ""; - response.headers.content_length = #body; + response.headers.content_length = ("%d"):format(#body); if response.is_head_request then return _M.send_head_response(response) end -- cgit v1.2.3 From 6a73014b9acdf69a7c415ac8f5fa173f83a68362 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 1 Nov 2019 22:25:54 +0100 Subject: net.http.server: Factor out handling of event response for easier reuse --- net/http/server.lua | 65 ++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 31 deletions(-) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index bf24c97e..991ef970 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -170,6 +170,38 @@ local headerfix = setmetatable({}, { end }); +local function handle_result(request, response, result) + if result == nil then + result = 404; + end + + if result == true then + return; + end + + local body; + local result_type = type(result); + if result_type == "number" then + response.status_code = result; + if result >= 400 then + body = events.fire_event("http-error", { request = request, response = response, code = result }); + end + elseif result_type == "string" then + body = result; + elseif result_type == "table" then + for k, v in pairs(result) do + if k ~= "headers" then + response[k] = v; + else + for header_name, header_value in pairs(v) do + response.headers[header_name] = header_value; + end + end + end + end + response:send(body); +end + function _M.hijack_response(response, listener) -- luacheck: ignore error("TODO"); end @@ -261,39 +293,10 @@ function handle_request(conn, request, finish_cb) result = events.fire_event(host_head_event, payload); end end - if result ~= nil then - if result ~= true then - local body; - local result_type = type(result); - if result_type == "number" then - response.status_code = result; - if result >= 400 then - payload.code = result; - body = events.fire_event("http-error", payload); - end - elseif result_type == "string" then - body = result; - elseif result_type == "table" then - for k, v in pairs(result) do - if k ~= "headers" then - response[k] = v; - else - for header_name, header_value in pairs(v) do - response.headers[header_name] = header_value; - end - end - end - end - response:send(body); - end - return; - end - -- if handler not called, return 404 - response.status_code = 404; - payload.code = 404; - response:send(events.fire_event("http-error", payload)); + return handle_result(request, response, result); end + local function prepare_header(response) local status_line = "HTTP/"..response.request.httpversion.." "..(response.status or codes[response.status_code]); local headers = response.headers; -- cgit v1.2.3 From fbab8ed06ac738e6aec96db67141f987b9d3c058 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 1 Nov 2019 22:28:39 +0100 Subject: net.http.server: Tail call because tail call! --- net/http/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 991ef970..0682d6ed 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -199,7 +199,7 @@ local function handle_result(request, response, result) end end end - response:send(body); + return response:send(body); end function _M.hijack_response(response, listener) -- luacheck: ignore -- cgit v1.2.3 From fdfe1e0b2bf8cea4e2e512fa8e25bface008a59b Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 1 Nov 2019 22:30:35 +0100 Subject: net.http.server: Handle util.error objects from http handlers --- net/http/server.lua | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 0682d6ed..0d49dbce 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -13,6 +13,7 @@ local traceback = debug.traceback; local tostring = tostring; local cache = require "util.cache"; local codes = require "net.http.codes"; +local errors = require "util.error"; local blocksize = 2^16; local _M = {}; @@ -188,6 +189,8 @@ local function handle_result(request, response, result) end elseif result_type == "string" then body = result; + elseif errors.is_err(result) then + body = events.fire_event("http-error", { request = request, response = response, code = result.code, error = result }); elseif result_type == "table" then for k, v in pairs(result) do if k ~= "headers" then -- cgit v1.2.3 From 5cac177270b40336e9820619e9c6ab3973ad95b4 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Fri, 1 Nov 2019 22:31:15 +0100 Subject: net.http.server: Handle promises from http handlers --- net/http/server.lua | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 0d49dbce..dc64728f 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -13,6 +13,7 @@ local traceback = debug.traceback; local tostring = tostring; local cache = require "util.cache"; local codes = require "net.http.codes"; +local promise = require "util.promise"; local errors = require "util.error"; local blocksize = 2^16; @@ -191,6 +192,13 @@ local function handle_result(request, response, result) body = result; elseif errors.is_err(result) then body = events.fire_event("http-error", { request = request, response = response, code = result.code, error = result }); + elseif promise.is_promise(result) then + result:next(function (ret) + handle_result(request, response, ret); + end, function (err) + handle_result(request, response, err); + end); + return true; elseif result_type == "table" then for k, v in pairs(result) do if k ~= "headers" then -- cgit v1.2.3 From 58990598f283f24f99dd5899669acc310b5437b1 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Tue, 5 Nov 2019 01:34:13 +0100 Subject: net.http.server: Treat promise rejection without value as a HTTP 500 error --- net/http/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index dc64728f..47f064a5 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -196,7 +196,7 @@ local function handle_result(request, response, result) result:next(function (ret) handle_result(request, response, ret); end, function (err) - handle_result(request, response, err); + handle_result(request, response, err or 500); end); return true; elseif result_type == "table" then -- cgit v1.2.3 From 87d0125802ce38410e5d429c90760802dec0397c Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sat, 14 Dec 2019 20:28:44 +0100 Subject: util.error: Move default for numeric error code to net.http.server Stanza errors can also have numbers but these are a legacy thing and rarely used, except in MUC. HTTP errors on the other hand always have a number. --- net/http/server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index 47f064a5..f4f67d18 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -191,7 +191,7 @@ local function handle_result(request, response, result) elseif result_type == "string" then body = result; elseif errors.is_err(result) then - body = events.fire_event("http-error", { request = request, response = response, code = result.code, error = result }); + body = events.fire_event("http-error", { request = request, response = response, code = result.code or 500, error = result }); elseif promise.is_promise(result) then result:next(function (ret) handle_result(request, response, ret); -- cgit v1.2.3 From 4f2548e8efbb5659ed723cb4e802ef66328ada29 Mon Sep 17 00:00:00 2001 From: Kim Alvefur Date: Sun, 12 Apr 2020 22:57:14 +0200 Subject: net.http.server: Use error code from util.error (fixes #1502) Oversight in 955e54e451dc when this was added. --- net/http/server.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index f4f67d18..c59479cd 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -191,6 +191,7 @@ local function handle_result(request, response, result) elseif result_type == "string" then body = result; elseif errors.is_err(result) then + response.status_code = result.code or 500; body = events.fire_event("http-error", { request = request, response = response, code = result.code or 500, error = result }); elseif promise.is_promise(result) then result:next(function (ret) -- cgit v1.2.3 From 9229c7a57188168e992145e4f3be6fd381ffe90c Mon Sep 17 00:00:00 2001 From: Matthew Wild Date: Mon, 28 Sep 2020 16:21:41 +0100 Subject: net.http.server: Default to HTTP result code 500 when promise is rejected --- net/http/server.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'net/http/server.lua') diff --git a/net/http/server.lua b/net/http/server.lua index f563d330..0070367a 100644 --- a/net/http/server.lua +++ b/net/http/server.lua @@ -197,6 +197,7 @@ local function handle_result(request, response, result) result:next(function (ret) handle_result(request, response, ret); end, function (err) + response.status_code = 500; handle_result(request, response, err or 500); end); return true; -- cgit v1.2.3