# HG changeset patch # User jbe # Date 1427133932 -3600 # Node ID 732c4d53a82339f465d66a3c22c5f6cd3946118a # Parent a2c733535b8ea565993d0580579d7742f83ca09a Invoke Moonbridge's listen function without delay (requires passing http_options as argument); Code cleanup diff -r a2c733535b8e -r 732c4d53a823 framework/bin/mcp.lua --- a/framework/bin/mcp.lua Mon Mar 23 16:05:56 2015 +0100 +++ b/framework/bin/mcp.lua Mon Mar 23 19:05:32 2015 +0100 @@ -8,7 +8,16 @@ WEBMCP_VERSION = "2.0.0" --//-- --- allow control of global environment +--[[-- +_G + +A reference to the global namespace. To avoid accidental programming errors, global variables cannot be set directly, but they must be set through the _G reference, e.g. use _G.foo = true to set the variable "foo" to a value of true. + +The only exception is the /env/__init.lua file and the /env/__init.lua file, in which global variables may be set without using the _G reference. + +Note that the global namespace may or may not be shared between requests (Moonbridge creates multiple forks of the Lua machine). To set variables that are to be cleared after the request has been finished, an application may use the "app" table, e.g. app.foo = true to set the variable app.foo to a value of true, which will be cleared automatically when the request has ended. + +--]]-- local _G = _G local allowed_globals = {} local global_metatable = { @@ -17,7 +26,23 @@ _G[key] = value end } -_ENV = setmetatable({}, global_metatable) +_ENV = setmetatable( + {}, -- proxy environment used within mcp.lua and by all chunks loaded through loadcached(...) + global_metatable +) +local function protect_globals() -- called before first configuration file is loaded + function global_metatable.__newindex(self, key, value) + if allowed_globals[key] then + _G[key] = value + else + if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then + error('Attempt to set global variable "' .. key .. '" (hint: use _G.' .. key .. '= to override protection mechnamism)', 2) + else + error('Attempt to set global variable', 2) + end + end + end +end --[[-- lua_func = -- compiled Lua function @@ -57,7 +82,6 @@ A constant set to "listen" in case of a network request, or set to "interactive" in case of interactive mode. --]]-- --- check if interactive mode if listen then -- defined by moonbridge WEBMCP_MODE = "listen" else @@ -169,6 +193,7 @@ -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/", -- application environment extensions "$WEBMCP_BASE_PATH/env/" -- and models "$WEBMCP_BASE_PATH/model/" +local root_init -- function which executes the __init.lua file in the environment's root do local weakkey_mt = { __mode = "k" } local autoloader_category = setmetatable({}, weakkey_mt) @@ -253,75 +278,74 @@ return rawget(self, key) end install_autoloader(_G, nil, "") - try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua") - try_exec(WEBMCP_BASE_PATH .. "env/__init.lua") -end - --- replace Moonbridge listen function -local moonbridge_listen = listen -local listeners = {} -function listen(args) - listeners[#listeners+1] = args + function root_init() -- upvalue + try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua") + try_exec(WEBMCP_BASE_PATH .. "env/__init.lua") + end end --- prohibit (unintended) definition of new global variables -function global_metatable.__newindex(self, key, value) - if not allowed_globals[key] then - error("Setting of global variable prohibited", 2) - end - _G[key] = value -end - --- execute configurations and pre-fork initializers -for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do - execute.config(config_name) -end -execute.prefork_initializers() - -- define post-fork initialization function (including loading of "multirand" library) local function postfork_init() _G.multirand = require "multirand" execute.postfork_initializers() end --- interactive console mode +-- prepare for interactive or listen mode if WEBMCP_MODE == "interactive" then - postfork_init() - trace.disable() -- avoids memory leakage -end - --- invoke moonbridge -if WEBMCP_MODE == "listen" then - local http_options = request.get_http_options() - local min_requests_per_fork = http_options.min_requests_per_fork or 50 - local max_requests_per_fork = http_options.max_requests_per_fork or 100 + function listen() -- overwrite Moonbridge's listen function + -- ignore listen function calls for interactive mode + end + trace.disable() -- avoids memory leakage when scripts are running endlessly +else + local moonbridge_listen = listen local http = require("moonbridge_http") - for i, listener in ipairs(listeners) do + function listen(args) -- overwrite Moonbridge's listen function + local http_options = args.http_options or {} + local min_requests_per_fork = http_options.min_requests_per_fork or 50 + local max_requests_per_fork = http_options.max_requests_per_fork or 100 local interval_handlers = {} - for j, entry in ipairs(listener) do - if entry.proto == "interval" then - local name = entry.name or "Unnamed interval #" .. #interval_handlers+1 - interval_handlers[name] = entry.handler - entry.name = name + for j, listener in ipairs(args) do + if listener.proto == "interval" then + local name = listener.name or "Unnamed interval #" .. #interval_handlers+1 + interval_handlers[name] = listener.handler + listener.name = name end end local request_count = 0 local function inner_handler(http_request) + request.initialize() request.handler(http_request, request_count >= max_requests_per_fork) end local outer_handler = http.generate_handler(inner_handler, http_options) - listener.prepare = postfork_init - listener.connect = function(socket) + args.prepare = postfork_init + args.connect = function(socket) request_count = request_count + 1 - request.initialize() if socket.interval then + request.initialize() interval_handlers[socket.interval]() else outer_handler(socket) end return request_count < min_requests_per_fork end - listener.finish = execute.finalizers - moonbridge_listen(listener) + args.finish = execute.finalizers + moonbridge_listen(args) end end + +-- execute the __init.lua file in the environment's root +root_init() + +-- prohibit (unintended) definition of new global variables +protect_globals() + +-- execute configurations and pre-fork initializers +for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do + execute.config(config_name) +end +execute.prefork_initializers() + +-- perform post-fork initializations in case of interactive mode +if WEBMCP_MODE == "interactive" then + postfork_init() +end diff -r a2c733535b8e -r 732c4d53a823 framework/env/request/__init.lua --- a/framework/env/request/__init.lua Mon Mar 23 16:05:56 2015 +0100 +++ b/framework/env/request/__init.lua Mon Mar 23 19:05:32 2015 +0100 @@ -1,7 +1,6 @@ request._initializers = {} request._in_progress = false --- initialize once request._mime_types = { "html", "text/html", "css", "text/css", @@ -14,12 +13,10 @@ "pdf", "application/pdf", "txt", "text/plain" } -request._absolute_baseurl = nil -request._http_options = {} request.for_each(function() - -- configurable + request._absolute_baseurl = nil request._response_headers = {} request._force_absolute_baseurl = false request._perm_params = {} @@ -27,8 +24,6 @@ request._cache = false request._cache_manual = false request._cache_time = 3600 - - -- non-configurable request._relative_baseurl = nil request._http_request = nil request._status = nil diff -r a2c733535b8e -r 732c4d53a823 framework/env/request/get_http_options.lua --- a/framework/env/request/get_http_options.lua Mon Mar 23 16:05:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,10 +0,0 @@ ---[[-- -request.get_http_options() - -Returns the table filled by request.set_http_options(). The return value can be passed to Moonbridge's HTTP request handler generator. - ---]]-- - -function request.get_http_options() - return request._http_options -end diff -r a2c733535b8e -r 732c4d53a823 framework/env/request/set_http_options.lua --- a/framework/env/request/set_http_options.lua Mon Mar 23 16:05:56 2015 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ ---[[-- -request.set_http_options{ - ... -} - -To be called in a configuration file to set parameters for the Moonbridge HTTP module. - ---]]-- - -function request.set_http_options(args) - for key, value in pairs(args) do - request._http_options[key] = value - end -end