# HG changeset patch # User Matthew Wild # Date 1687465654 -3600 # Node ID dfa7cb60647ef52212932f6bcc597779c27a1118 # Parent 635b385df3a2be660d80a5e89111f112c686207c http: Handler logic improvements (affects auth, config, templates) diff -r 635b385df3a2 -r dfa7cb60647e src/http.lua --- a/src/http.lua Thu Jun 22 21:25:35 2023 +0100 +++ b/src/http.lua Thu Jun 22 21:27:34 2023 +0100 @@ -15,19 +15,6 @@ local log = require "util.logger".init("web"); -local usercookie = require"util.usercookie"; -local secret = uuid.generate(); - -local check_auth = require "app.auth".check_auth; - -local function set_auth_cookie(username, response) - local expires = config.cookie_ttl or 604800; - local cookie = usercookie.generate(username, os.time()+expires, secret); - cookie = "remember=".. cookie .. "; Path="..config.base_path - .."; Max-Age="..tostring(expires).."; HttpOnly"; - return web.set_cookie(response.headers, cookie); -end - local csrf_token_len = #uuid.generate(); local function check_csrf(event, viewdata) @@ -44,30 +31,44 @@ end end -local function wrap_handler(f, t, path_prefix_len) +local function wrap_handler(f, default_tpl, path_prefix_len, check_auth) return function (event) log("debug", "Check auth..."); - local authed = check_auth(event.request, config); + local request = event.request; + local authed, handler_override = check_auth(request, config); + if authed and not request.authenticated then + request.authenticated = authed; + end log("debug", "Checked, %s", authed); event.config = config; local sub_path = nil; if path_prefix_len then sub_path = event.request.path:sub(path_prefix_len+2); end - local p = f(event, sub_path); - return promise.resolve(p):next(function (resp) - if type(resp) == "table" then + + local h = handler_override or f; + + local p, custom_tpl; + if web.is_response(h) then + p = h; + else + p, custom_tpl = (handler_override or f)(event, sub_path); + end + + -- Process response (may be promises) + return promise.join(function (resp, tpl) + if type(resp) == "table" and not web.is_response(resp) then local headers = event.response.headers; local accept = event.request.headers.accept or ""; web.add_header(headers, "vary", "Accept, Cookie"); if accept:find"application/json" then headers.content_type = "application/json"; return json.encode(resp); - elseif t then + elseif tpl then if authed or event.needs_csrf then check_csrf(event, resp); end resp.authenticated = event.request.authenticated; resp.config = config; - resp = render(t, resp); + resp = render(tpl, resp); if not headers.content_type then headers.content_type = "text/html; charset=utf-8"; end @@ -76,7 +77,7 @@ end end return resp; - end):catch(function (err) + end, p, custom_tpl or default_tpl):catch(function (err) log("error", "Failed inside handler wrapper: %s", json.encode(err)); return promise.reject(errors.wrap(err)); end); @@ -133,10 +134,10 @@ end end -local function register_handlers(handlers, event_base, path_prefix) +local function register_handlers(handlers, event_base, path_prefix, check_auth) for method_path, handler in pairs(handlers) do if type(handler) == "table" then - register_handlers(handler, event_base, (path_prefix and (path_prefix.."/") or "")..method_path); + register_handlers(handler, event_base, (path_prefix and (path_prefix.."/") or "")..method_path, check_auth); else local method, path, wildcard = method_path:match"^(%w+)_(.-)(_?)$"; method = method:upper(); @@ -161,7 +162,7 @@ path_prefix_len = #path+1; end - handler = wrap_handler(handler, templates[template_name], path_prefix_len); + handler = wrap_handler(handler, templates[template_name], path_prefix_len, check_auth); local head_event = event_base:format("HEAD", path, wildcard); http_server.add_handler(head_event, head_handler(handler)); @@ -181,11 +182,14 @@ local base_path = url.parse_path(config.base_path or base_url.path or "/"); base_path.is_directory = true; base_url.path = url.build_path(base_path); + config.templates = templates; config.base_host = base_url.host; config.base_path = base_url.path; config.base_url = url.build(base_url); local event_base = ("%%s %s%s%%s%%s"):format(base_url.host, base_url.path); + _G.CONFIG = config; + local check_auth = require "app.auth".check_auth; local handlers = require "app.routes"; handlers.get_static_ = files.serve { path = "./static", http_base = base_url.path.."static" }; @@ -196,7 +200,7 @@ return handle_error(error, config) end); - register_handlers(handlers, event_base); + register_handlers(handlers, event_base, nil, check_auth); local listen_port = config.listen_port or 8007; local listen_interface = config.listen_interface or "*"; @@ -207,4 +211,6 @@ return { init = init; render = render; + set_auth_cookie = set_auth_cookie; + get_auth_cookie = get_auth_cookie; }