webmcp

changeset 317:732c4d53a823

Invoke Moonbridge's listen function without delay (requires passing http_options as argument); Code cleanup
author jbe
date Mon Mar 23 19:05:32 2015 +0100 (2015-03-23)
parents a2c733535b8e
children f5660406ad3b
files framework/bin/mcp.lua framework/env/request/__init.lua framework/env/request/get_http_options.lua framework/env/request/set_http_options.lua
line diff
     1.1 --- a/framework/bin/mcp.lua	Mon Mar 23 16:05:56 2015 +0100
     1.2 +++ b/framework/bin/mcp.lua	Mon Mar 23 19:05:32 2015 +0100
     1.3 @@ -8,7 +8,16 @@
     1.4  WEBMCP_VERSION = "2.0.0"
     1.5  --//--
     1.6  
     1.7 --- allow control of global environment
     1.8 +--[[--
     1.9 +_G
    1.10 +
    1.11 +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.
    1.12 +
    1.13 +The only exception is the <framework>/env/__init.lua file and the <application>/env/__init.lua file, in which global variables may be set without using the _G reference.
    1.14 +
    1.15 +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.
    1.16 +
    1.17 +--]]--
    1.18  local _G = _G
    1.19  local allowed_globals = {}
    1.20  local global_metatable = {
    1.21 @@ -17,7 +26,23 @@
    1.22      _G[key] = value
    1.23    end
    1.24  }
    1.25 -_ENV = setmetatable({}, global_metatable)
    1.26 +_ENV = setmetatable(
    1.27 +  {},  -- proxy environment used within mcp.lua and by all chunks loaded through loadcached(...)
    1.28 +  global_metatable
    1.29 +) 
    1.30 +local function protect_globals()  -- called before first configuration file is loaded
    1.31 +  function global_metatable.__newindex(self, key, value)
    1.32 +    if allowed_globals[key] then
    1.33 +      _G[key] = value
    1.34 +    else
    1.35 +      if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then
    1.36 +        error('Attempt to set global variable "' .. key .. '" (hint: use _G.' .. key .. '=<value> to override protection mechnamism)', 2)
    1.37 +      else
    1.38 +        error('Attempt to set global variable', 2)
    1.39 +      end
    1.40 +    end
    1.41 +  end
    1.42 +end
    1.43  
    1.44  --[[--
    1.45  lua_func =   -- compiled Lua function
    1.46 @@ -57,7 +82,6 @@
    1.47  
    1.48  A constant set to "listen" in case of a network request, or set to "interactive" in case of interactive mode.
    1.49  --]]--
    1.50 --- check if interactive mode
    1.51  if listen then  -- defined by moonbridge
    1.52    WEBMCP_MODE = "listen"
    1.53  else
    1.54 @@ -169,6 +193,7 @@
    1.55  -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/",
    1.56  -- application environment extensions "$WEBMCP_BASE_PATH/env/"
    1.57  -- and models "$WEBMCP_BASE_PATH/model/"
    1.58 +local root_init  -- function which executes the __init.lua file in the environment's root
    1.59  do
    1.60    local weakkey_mt = { __mode = "k" }
    1.61    local autoloader_category = setmetatable({}, weakkey_mt)
    1.62 @@ -253,75 +278,74 @@
    1.63      return rawget(self, key)
    1.64    end
    1.65    install_autoloader(_G, nil, "")
    1.66 -  try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
    1.67 -  try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
    1.68 -end
    1.69 -
    1.70 --- replace Moonbridge listen function
    1.71 -local moonbridge_listen = listen
    1.72 -local listeners = {}
    1.73 -function listen(args)
    1.74 -  listeners[#listeners+1] = args
    1.75 +  function root_init()  -- upvalue
    1.76 +    try_exec(WEBMCP_FRAMEWORK_PATH .. "env/__init.lua")
    1.77 +    try_exec(WEBMCP_BASE_PATH .. "env/__init.lua")
    1.78 +  end
    1.79  end
    1.80  
    1.81 --- prohibit (unintended) definition of new global variables
    1.82 -function global_metatable.__newindex(self, key, value)
    1.83 -  if not allowed_globals[key] then
    1.84 -    error("Setting of global variable prohibited", 2)
    1.85 -  end
    1.86 -  _G[key] = value
    1.87 -end
    1.88 -
    1.89 --- execute configurations and pre-fork initializers
    1.90 -for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
    1.91 -  execute.config(config_name)
    1.92 -end
    1.93 -execute.prefork_initializers()
    1.94 -
    1.95  -- define post-fork initialization function (including loading of "multirand" library)
    1.96  local function postfork_init()
    1.97    _G.multirand = require "multirand"
    1.98    execute.postfork_initializers()
    1.99  end
   1.100  
   1.101 --- interactive console mode
   1.102 +-- prepare for interactive or listen mode
   1.103  if WEBMCP_MODE == "interactive" then
   1.104 -  postfork_init()
   1.105 -  trace.disable()  -- avoids memory leakage
   1.106 -end
   1.107 -
   1.108 --- invoke moonbridge
   1.109 -if WEBMCP_MODE == "listen" then
   1.110 -  local http_options = request.get_http_options()
   1.111 -  local min_requests_per_fork  = http_options.min_requests_per_fork or 50
   1.112 -  local max_requests_per_fork  = http_options.max_requests_per_fork or 100
   1.113 +  function listen()  -- overwrite Moonbridge's listen function
   1.114 +    -- ignore listen function calls for interactive mode
   1.115 +  end
   1.116 +  trace.disable()  -- avoids memory leakage when scripts are running endlessly
   1.117 +else
   1.118 +  local moonbridge_listen = listen
   1.119    local http = require("moonbridge_http")
   1.120 -  for i, listener in ipairs(listeners) do
   1.121 +  function listen(args)  -- overwrite Moonbridge's listen function
   1.122 +    local http_options = args.http_options or {}
   1.123 +    local min_requests_per_fork = http_options.min_requests_per_fork or 50
   1.124 +    local max_requests_per_fork = http_options.max_requests_per_fork or 100
   1.125      local interval_handlers = {}
   1.126 -    for j, entry in ipairs(listener) do
   1.127 -      if entry.proto == "interval" then
   1.128 -        local name = entry.name or "Unnamed interval #" .. #interval_handlers+1
   1.129 -        interval_handlers[name] = entry.handler
   1.130 -        entry.name = name
   1.131 +    for j, listener in ipairs(args) do
   1.132 +      if listener.proto == "interval" then
   1.133 +        local name = listener.name or "Unnamed interval #" .. #interval_handlers+1
   1.134 +        interval_handlers[name] = listener.handler
   1.135 +        listener.name = name
   1.136        end
   1.137      end
   1.138      local request_count = 0
   1.139      local function inner_handler(http_request)
   1.140 +      request.initialize()
   1.141        request.handler(http_request, request_count >= max_requests_per_fork)
   1.142      end
   1.143      local outer_handler = http.generate_handler(inner_handler, http_options)
   1.144 -    listener.prepare = postfork_init
   1.145 -    listener.connect = function(socket)
   1.146 +    args.prepare = postfork_init
   1.147 +    args.connect = function(socket)
   1.148        request_count = request_count + 1
   1.149 -      request.initialize()
   1.150        if socket.interval then
   1.151 +        request.initialize()
   1.152          interval_handlers[socket.interval]()
   1.153        else
   1.154          outer_handler(socket)
   1.155        end
   1.156        return request_count < min_requests_per_fork
   1.157      end
   1.158 -    listener.finish = execute.finalizers
   1.159 -    moonbridge_listen(listener)
   1.160 +    args.finish = execute.finalizers
   1.161 +    moonbridge_listen(args)
   1.162    end
   1.163  end
   1.164 +
   1.165 +-- execute the __init.lua file in the environment's root
   1.166 +root_init()
   1.167 +
   1.168 +-- prohibit (unintended) definition of new global variables
   1.169 +protect_globals()
   1.170 +
   1.171 +-- execute configurations and pre-fork initializers
   1.172 +for i, config_name in ipairs(WEBMCP_CONFIG_NAMES) do
   1.173 +  execute.config(config_name)
   1.174 +end
   1.175 +execute.prefork_initializers()
   1.176 +
   1.177 +-- perform post-fork initializations in case of interactive mode
   1.178 +if WEBMCP_MODE == "interactive" then
   1.179 +  postfork_init()
   1.180 +end
     2.1 --- a/framework/env/request/__init.lua	Mon Mar 23 16:05:56 2015 +0100
     2.2 +++ b/framework/env/request/__init.lua	Mon Mar 23 19:05:32 2015 +0100
     2.3 @@ -1,7 +1,6 @@
     2.4  request._initializers = {}
     2.5  request._in_progress = false
     2.6  
     2.7 --- initialize once
     2.8  request._mime_types = {
     2.9    "html", "text/html",
    2.10    "css", "text/css",
    2.11 @@ -14,12 +13,10 @@
    2.12    "pdf", "application/pdf",
    2.13    "txt", "text/plain"
    2.14  }
    2.15 -request._absolute_baseurl = nil
    2.16 -request._http_options = {}
    2.17  
    2.18  request.for_each(function()
    2.19  
    2.20 -  -- configurable
    2.21 +  request._absolute_baseurl = nil
    2.22    request._response_headers = {}
    2.23    request._force_absolute_baseurl = false
    2.24    request._perm_params = {}
    2.25 @@ -27,8 +24,6 @@
    2.26    request._cache = false
    2.27    request._cache_manual = false
    2.28    request._cache_time = 3600
    2.29 -
    2.30 -  -- non-configurable
    2.31    request._relative_baseurl = nil
    2.32    request._http_request = nil
    2.33    request._status = nil
     3.1 --- a/framework/env/request/get_http_options.lua	Mon Mar 23 16:05:56 2015 +0100
     3.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.3 @@ -1,10 +0,0 @@
     3.4 ---[[--
     3.5 -request.get_http_options()
     3.6 -
     3.7 -Returns the table filled by request.set_http_options(). The return value can be passed to Moonbridge's HTTP request handler generator.
     3.8 -
     3.9 ---]]--
    3.10 -
    3.11 -function request.get_http_options()
    3.12 -  return request._http_options
    3.13 -end
     4.1 --- a/framework/env/request/set_http_options.lua	Mon Mar 23 16:05:56 2015 +0100
     4.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.3 @@ -1,14 +0,0 @@
     4.4 ---[[--
     4.5 -request.set_http_options{
     4.6 -  ...
     4.7 -}
     4.8 -
     4.9 -To be called in a configuration file to set parameters for the Moonbridge HTTP module.
    4.10 -
    4.11 ---]]--
    4.12 -
    4.13 -function request.set_http_options(args)
    4.14 -  for key, value in pairs(args) do
    4.15 -    request._http_options[key] = value
    4.16 -  end
    4.17 -end

Impressum / About Us