# HG changeset patch # User jbe # Date 1421023691 -3600 # Node ID ba3dd4a17e3d7c2bbaddb40d596a716cfa413c60 # Parent 6ac7133bb58e94480a9b9d6f32e8421e1cc77fa7 Some code cleanup/rearrangement for request handling diff -r 6ac7133bb58e -r ba3dd4a17e3d framework/bin/mcp.lua --- a/framework/bin/mcp.lua Sat Jan 10 10:44:17 2015 +0100 +++ b/framework/bin/mcp.lua Mon Jan 12 01:48:11 2015 +0100 @@ -188,10 +188,12 @@ -- execute configurations for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do execute.config(config_name) + execute.prefork_initializers() end -- interactive console mode if WEBMCP_MODE == "interactive" then + execute.postfork_initializers() trace.disable() -- avoids memory leakage (TODO: needs general solution for moonbridge?) end @@ -199,13 +201,10 @@ if WEBMCP_MODE == "listen" then local http = require("moonbridge_http") for i, listener in ipairs(listeners) do - listener.prepare = execute.prefork_initializers + listener.prepare = execute.postfork_initializers listener.connect = http.generate_handler( - request.get_http_options(), - function(http_request) - execute.postfork_initializers() - request.handler(http_request) - end + request.handler, + request.get_http_options() ) listener.finish = execute.finalizers moonbridge_listen(listener) diff -r 6ac7133bb58e -r ba3dd4a17e3d framework/env/request/__init.lua --- a/framework/env/request/__init.lua Sat Jan 10 10:44:17 2015 +0100 +++ b/framework/env/request/__init.lua Mon Jan 12 01:48:11 2015 +0100 @@ -14,82 +14,6 @@ request._json_requests_allowed = false request._params = {} -local depth -if cgi then -- if-clause to support interactive mode - if cgi.params._webmcp_404 then - request.force_absolute_baseurl() - request._is_404 = true - end - for key, value in pairs(cgi.params) do - if not string.match(key, "^_webmcp_") then - request._params[key] = value - end - end - local path = cgi.params._webmcp_path - if path then - local function parse() - local module, action, view, suffix, id - if path == "" then - request._module = "index" - request._view = "index" - return - end - module = string.match(path, "^([^/]+)/$") - if module then - request._module = module - request._view = "index" - return - end - module, action = string.match(path, "^([^/]+)/([^/.]+)$") - if module then - request._module = module - request._action = action - return - end - module, view, suffix = string.match(path, "^([^/]+)/([^/.]+)%.([^/]+)$") - if module then - request._module = module - request._view = view - request._suffix = suffix - return - end - module, view, id, suffix = string.match(path, "^([^/]+)/([^/]+)/([^/.]+)%.([^/]+)$") - if module then - request._module = module - request._view = view - request._id = id - request._suffix = suffix - return - end - request._is_404 = true - end - parse() - -- allow id to also be set by "_webmcp_id" parameter - if cgi.params._webmcp_id ~= nil then - request._id = cgi.params._webmcp_id - end - depth = 0 - for match in string.gmatch(path, "/") do - depth = depth + 1 - end - else - request._module = cgi.params._webmcp_module - request._action = cgi.params._webmcp_action - request._view = cgi.params._webmcp_view - request._suffix = cgi.params._webmcp_suffix - request._id = cgi.params._webmcp_id - depth = tonumber(cgi.params._webmcp_urldepth) - end -end -if depth and depth > 0 then - local elements = {} - for i = 1, depth do - elements[#elements+1] = "../" - end - request._relative_baseurl = table.concat(elements) -else - request._relative_baseurl = "./" -end request._app_basepath = assert( os.getenv("WEBMCP_APP_BASEPATH"), diff -r 6ac7133bb58e -r ba3dd4a17e3d framework/env/request/default_router.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/framework/env/request/default_router.lua Mon Jan 12 01:48:11 2015 +0100 @@ -0,0 +1,267 @@ +-- TODO: function incomplete yet + +local function file_exists(filename) + local file = io.open(filename, "r") + if file then + io.close(file) + return true + else + return false + end +end + +function request.default_router(path) + request._http_request = http_request + local path = http_request.path + local function parse_path() + if not path then + return + end + if path == "/" then + return {module = "index", view = "index"} + end + module = string.match(path, "^/([^/]+)/$") + if module then + return {module = module, view = "index"} + end + module, action = string.match(path, "^/([^/]+)/([^/.]+)$") + if module then + return {module = module, action = action} + end + module, view, suffix = string.match(path, "^/([^/]+)/([^/.]+)%.([^/]+)$") + if module then + return {module = module, view = view, suffix = suffix} + end + module, view, id, suffix = string.match(path, "^/([^/]+)/([^/]+)/([^/.]+)%.([^/]+)$") + if module then + return {module = module, view = view, id = id, suffix = suffix} + end + end + request._data = parse_path() + if path then + local elements = {} + for match in string.gmatch(path, "/") do + elements[#elements+1] = "../" + end + elements[#elements] = nil + if #elements > 0 then + request._relative_baseurl = table.concat(elements) + else + request._relative_baseurl = "./" + end + end + local success, error_info = xpcall( + function() + + -- restore slots if coming from http redirect + local tempstore_value = request.get_param{method = "GET", name = "_tempstore"} + if tempstore_value then + trace.restore_slots{} + local blob = tempstore.pop(tempstore_value) + if blob then slot.restore_all(blob) end + end + + + if request.is_404() then + request.set_status("404 Not Found") + if request.get_404_route() then + request.forward(request.get_404_route()) + else + error("No 404 page set.") + end + elseif request.get_action() then + trace.request{ + module = request.get_module(), + action = request.get_action() + } + if + request.get_404_route() and + not file_exists( + encode.action_file_path{ + module = request.get_module(), + action = request.get_action() + } + ) + then + request.set_status("404 Not Found") + request.forward(request.get_404_route()) + else + if cgi.method ~= "POST" then + request.set_status("405 Method Not Allowed") + cgi.add_header("Allow: POST") + error("Tried to invoke an action with a GET request.") + end + local action_status = execute.filtered_action{ + module = request.get_module(), + action = request.get_action(), + } + if not request.is_rerouted() then + local routing_mode, routing_module, routing_view + routing_mode = cgi.params["_webmcp_routing." .. action_status .. ".mode"] + routing_module = cgi.params["_webmcp_routing." .. action_status .. ".module"] + routing_view = cgi.params["_webmcp_routing." .. action_status .. ".view"] + routing_anchor = cgi.params["_webmcp_routing." .. action_status .. ".anchor"] + if not (routing_mode or routing_module or routing_view) then + action_status = "default" + routing_mode = cgi.params["_webmcp_routing.default.mode"] + routing_module = cgi.params["_webmcp_routing.default.module"] + routing_view = cgi.params["_webmcp_routing.default.view"] + routing_anchor = cgi.params["_webmcp_routing.default.anchor"] + end + assert(routing_module, "Routing information has no module.") + assert(routing_view, "Routing information has no view.") + if routing_mode == "redirect" then + local routing_params = {} + for key, value in pairs(cgi.params) do + local status, stripped_key = string.match( + key, "^_webmcp_routing%.([^%.]*)%.params%.(.*)$" + ) + if status == action_status then + routing_params[stripped_key] = value + end + end + request.redirect{ + module = routing_module, + view = routing_view, + id = cgi.params["_webmcp_routing." .. action_status .. ".id"], + params = routing_params, + anchor = routing_anchor + } + elseif routing_mode == "forward" then + request.forward{ module = routing_module, view = routing_view } + else + error("Missing or unknown routing mode in request parameters.") + end + end + end + else + -- no action + trace.request{ + module = request.get_module(), + view = request.get_view() + } + if + request.get_404_route() and + not file_exists( + encode.view_file_path{ + module = request.get_module(), + view = request.get_view() + } + ) + then + request.set_status("404 Not Found") + request.forward(request.get_404_route()) + end + end + + if not request.get_redirect_data() then + request.process_forward() + local view = request.get_view() + if string.find(view, "^_") then + error("Tried to call a private view (prefixed with underscore).") + end + execute.filtered_view{ + module = request.get_module(), + view = view, + } + end + + -- force error due to missing absolute base URL until its too late to display error message + --if request.get_redirect_data() then + -- request.get_absolute_baseurl() + --end + + end, + + function(errobj) + return { + errobj = errobj, + stacktrace = string.gsub( + debug.traceback('', 2), + "^\r?\n?stack traceback:\r?\n?", "" + ) + } + end + ) + + if not success then trace.error{} end + + -- laufzeitermittlung + trace.exectime{ real = extos.monotonic_hires_time(), cpu = os.clock() } + + slot.select('trace', trace.render) -- render trace information + + local redirect_data = request.get_redirect_data() + + -- log error and switch to error layout, unless success + if not success then + local errobj = error_info.errobj + local stacktrace = error_info.stacktrace + if not request.get_status() and not request.get_json_request_slots() then + request.set_status("500 Internal Server Error") + end + slot.set_layout('system_error') + slot.select('system_error', function() + if getmetatable(errobj) == mondelefant.errorobject_metatable then + slot.put( + "
Database error of class ",
+ encode.html(errobj.code),
+ " occured:
",
+ encode.html(errobj.message),
+ "
", encode.html(tostring(errobj)), "
") + end + slot.put("Stack trace follows:
")
+ slot.put(encode.html_newlines(encode.html(stacktrace)))
+ slot.put("
Database error of class ",
- encode.html(errobj.code),
- " occured:
",
- encode.html(errobj.message),
- "
", encode.html(tostring(errobj)), "
") - end - slot.put("Stack trace follows:
")
- slot.put(encode.html_newlines(encode.html(stacktrace)))
- slot.put("