webmcp

changeset 352:2b5bdf9028fb

Code cleanup and performance improvements regarding 404 check; Deprecated encode.action_file_path{...} and encode.view_file_path{...}
author jbe
date Thu Mar 26 16:40:04 2015 +0100 (2015-03-26)
parents b1748c6c3c89
children f28b3c671378
files framework/bin/mcp.lua framework/env/__init.lua framework/env/encode/action_file_path.lua framework/env/encode/view_file_path.lua framework/env/execute/action.lua framework/env/execute/file_path.lua framework/env/execute/view.lua framework/env/request/handler.lua
line diff
     1.1 --- a/framework/bin/mcp.lua	Thu Mar 26 16:38:30 2015 +0100
     1.2 +++ b/framework/bin/mcp.lua	Thu Mar 26 16:40:04 2015 +0100
     1.3 @@ -9,68 +9,6 @@
     1.4  --//--
     1.5  
     1.6  --[[--
     1.7 -_G
     1.8 -
     1.9 -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.10 -
    1.11 -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.12 -
    1.13 ---]]--
    1.14 -local _G = _G
    1.15 -local allowed_globals = {}
    1.16 -local protected_environment = setmetatable(
    1.17 -  {},  -- proxy environment used all chunks loaded through loadcached(...)
    1.18 -  {
    1.19 -    __index = _G,
    1.20 -    __newindex = function(self, key, value)
    1.21 -      if allowed_globals[key] then
    1.22 -        _G[key] = value
    1.23 -      else
    1.24 -        if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then
    1.25 -          error('Attempt to set global variable "' .. key .. '" (Hint: missing local statement? Use _G.' .. key .. '=<value> to really set global variable.)', 2)
    1.26 -        else
    1.27 -          error('Attempt to set global variable', 2)
    1.28 -        end
    1.29 -      end
    1.30 -    end
    1.31 -  }
    1.32 -)
    1.33 ---//--
    1.34 -
    1.35 ---[[--
    1.36 -lua_func =   -- compiled Lua function
    1.37 -loadcached(
    1.38 -  filename   -- path to a Lua source or byte-code file
    1.39 -)
    1.40 -
    1.41 -Loads, compiles and caches a Lua chunk. If the file does not exist, nil and an error string are returned. Otherwise the file is loaded, compiled, and cached. The cached value (i.e. the compiled function) is returned. An error is raised if the compilation was not successful.
    1.42 -
    1.43 ---]]--
    1.44 -do
    1.45 -  local cache = {}
    1.46 -  function loadcached(filename)
    1.47 -    local cached_func = cache[filename]
    1.48 -    if cached_func then
    1.49 -      return cached_func
    1.50 -    end
    1.51 -    local file, read_error = io.open(filename, "r")
    1.52 -    if file then
    1.53 -      local filedata = assert(file:read("*a"))
    1.54 -      assert(file:close())
    1.55 -      local func, compile_error = load(filedata, "=" .. filename, nil, protected_environment)
    1.56 -      if func then
    1.57 -        cache[filename] = func
    1.58 -        return func
    1.59 -      end
    1.60 -      error(compile_error, 0)
    1.61 -    else
    1.62 -      return nil, read_error
    1.63 -    end
    1.64 -  end
    1.65 -end
    1.66 ---//--
    1.67 -
    1.68 ---[[--
    1.69  WEBMCP_MODE
    1.70  
    1.71  A constant set to "listen" in case of a network request, or set to "interactive" in case of interactive mode.
    1.72 @@ -145,19 +83,6 @@
    1.73    WEBMCP_APP_NAME       = arg3
    1.74  end
    1.75  
    1.76 --- check if framework path is correct
    1.77 -do
    1.78 -  local file, errmsg = io.open(WEBMCP_FRAMEWORK_PATH .. "webmcp_version", "r")
    1.79 -  if not file then
    1.80 -    error('Could not find "webmcp_version" file: ' .. errmsg, 0)
    1.81 -  end
    1.82 -  local version = assert(file:read())
    1.83 -  assert(file:close())
    1.84 -  if version ~= WEBMCP_VERSION then
    1.85 -    error('Version mismatch in file "' .. WEBMCP_FRAMEWORK_PATH .. 'webmcp_version"')
    1.86 -  end
    1.87 -end
    1.88 -
    1.89  -- setup search paths for libraries
    1.90  do
    1.91    if string.match(package.path, "^[^;]") then
    1.92 @@ -183,6 +108,88 @@
    1.93    package.cpath = table.concat(paths, ";")
    1.94  end
    1.95  
    1.96 +-- load "extos" library (needed by function "loadcached")
    1.97 +_G.extos = require "extos"
    1.98 +
    1.99 +--[[--
   1.100 +_G
   1.101 +
   1.102 +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.103 +
   1.104 +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.105 +
   1.106 +--]]--
   1.107 +local _G = _G
   1.108 +local allowed_globals = {}
   1.109 +local protected_environment = setmetatable(
   1.110 +  {},  -- proxy environment used all chunks loaded through loadcached(...)
   1.111 +  {
   1.112 +    __index = _G,
   1.113 +    __newindex = function(self, key, value)
   1.114 +      if allowed_globals[key] then
   1.115 +        _G[key] = value
   1.116 +      else
   1.117 +        if type(key) == "string" and string.match(key, "^[A-Za-z_][A-Za-z_0-9]*$") then
   1.118 +          error('Attempt to set global variable "' .. key .. '" (Hint: missing local statement? Use _G.' .. key .. '=<value> to really set global variable.)', 2)
   1.119 +        else
   1.120 +          error('Attempt to set global variable', 2)
   1.121 +        end
   1.122 +      end
   1.123 +    end
   1.124 +  }
   1.125 +)
   1.126 +--//--
   1.127 +
   1.128 +--[[--
   1.129 +lua_func =   -- compiled Lua function, nil if the file does not exist
   1.130 +errmsg       -- error message (only for non-existing file, other errors are thrown)
   1.131 +loadcached(
   1.132 +  filename   -- path to a Lua source or byte-code file
   1.133 +)
   1.134 +
   1.135 +Loads, compiles and caches a Lua chunk. The cached value (i.e. the compiled function) is returned. If the file does not exist, nil and an error string are returned. Any other errors are thrown using error(...). Unsuccessful attempts are not cached (to prohibit cache pollution).
   1.136 +
   1.137 +--]]--
   1.138 +do
   1.139 +  local cache = {}
   1.140 +  function loadcached(filename)
   1.141 +    local cached_func = cache[filename]
   1.142 +    if cached_func then
   1.143 +      return cached_func
   1.144 +    end
   1.145 +    local stat, errmsg = extos.stat(filename)
   1.146 +    if stat == nil then
   1.147 +      error(errmsg)
   1.148 +    elseif stat == false then
   1.149 +      return nil, 'File "' .. filename .. '" does not exist'
   1.150 +    elseif stat.isdir then
   1.151 +      error('File "' .. filename .. '" is a directory')
   1.152 +    elseif not stat.isreg then
   1.153 +      error('File "' .. filename .. '" is not a regular file')
   1.154 +    end
   1.155 +    local func, compile_error = loadfile(filename, nil, protected_environment)
   1.156 +    if func then
   1.157 +      cache[filename] = func
   1.158 +      return func
   1.159 +    end
   1.160 +    error(compile_error, 0)
   1.161 +  end
   1.162 +end
   1.163 +--//--
   1.164 +
   1.165 +-- check if framework path is correct
   1.166 +do
   1.167 +  local file, errmsg = io.open(WEBMCP_FRAMEWORK_PATH .. "webmcp_version", "r")
   1.168 +  if not file then
   1.169 +    error('Could not find "webmcp_version" file: ' .. errmsg, 0)
   1.170 +  end
   1.171 +  local version = assert(file:read())
   1.172 +  assert(file:close())
   1.173 +  if version ~= WEBMCP_VERSION then
   1.174 +    error('Version mismatch in file "' .. WEBMCP_FRAMEWORK_PATH .. 'webmcp_version"')
   1.175 +  end
   1.176 +end
   1.177 +
   1.178  -- autoloader system for WebMCP environment "$WEBMCP_FRAMEWORK_PATH/env/",
   1.179  -- application environment extensions "$WEBMCP_BASE_PATH/env/"
   1.180  -- and models "$WEBMCP_BASE_PATH/model/"
     2.1 --- a/framework/env/__init.lua	Thu Mar 26 16:38:30 2015 +0100
     2.2 +++ b/framework/env/__init.lua	Thu Mar 26 16:40:04 2015 +0100
     2.3 @@ -54,8 +54,8 @@
     2.4  end
     2.5  --//--
     2.6  
     2.7 --- load libraries (except "multirand", which must be loaded after forking)
     2.8 -_G.extos       = require 'extos'
     2.9 +-- load libraries
    2.10 +-- (except "extos", which has to be loaded earlier, and "multirand", which must be loaded after forking)
    2.11  _G.nihil       = require 'nihil'
    2.12  _G.mondelefant = require 'mondelefant'
    2.13  _G.atom        = require 'atom'
     3.1 --- a/framework/env/encode/action_file_path.lua	Thu Mar 26 16:38:30 2015 +0100
     3.2 +++ b/framework/env/encode/action_file_path.lua	Thu Mar 26 16:40:04 2015 +0100
     3.3 @@ -7,8 +7,12 @@
     3.4  
     3.5  This function returns the file path of an action with a given module name and action name. Both module name and action name are mandatory arguments.
     3.6  
     3.7 +This function has been DEPRECATED and will be removed. To test whether an action exists, use execute.action{ test_existence=true, ... }.
     3.8 +
     3.9  --]]--
    3.10  
    3.11 +-- TODO: remove deprecated function
    3.12 +
    3.13  function encode.action_file_path(args)
    3.14    return (encode.file_path(
    3.15      WEBMCP_BASE_PATH,
     4.1 --- a/framework/env/encode/view_file_path.lua	Thu Mar 26 16:38:30 2015 +0100
     4.2 +++ b/framework/env/encode/view_file_path.lua	Thu Mar 26 16:40:04 2015 +0100
     4.3 @@ -7,8 +7,12 @@
     4.4  
     4.5  This function returns the file path of a view with a given module name and view name. Both module name and view name are mandatory arguments.
     4.6  
     4.7 +This function has been DEPRECATED and will be removed. To test whether a view exists, use execute.view{ test_existence=true, ... }.
     4.8 +
     4.9  --]]--
    4.10  
    4.11 +-- TODO: remove deprecated function
    4.12 +
    4.13  function encode.view_file_path(args)
    4.14    return (encode.file_path(
    4.15      WEBMCP_BASE_PATH, 'app', WEBMCP_APP_NAME, args.module, args.view .. '.lua'
     5.1 --- a/framework/env/execute/action.lua	Thu Mar 26 16:38:30 2015 +0100
     5.2 +++ b/framework/env/execute/action.lua	Thu Mar 26 16:40:04 2015 +0100
     5.3 @@ -1,10 +1,11 @@
     5.4  --[[--
     5.5 -action_status =     -- status code returned by the action (a string)
     5.6 +action_status =     -- status code returned by the action (a string), or, if "test_existence" == true, a boolean
     5.7  execute.action{
     5.8 -  module = module,  -- module name of the action to be executed
     5.9 -  action = action,  -- name of the action to be executed
    5.10 -  id     = id,      -- id to be returned by param.get_id(...) during execution
    5.11 -  params = params   -- parameters to be returned by param.get(...) during execution
    5.12 +  module         = module,         -- module name of the action to be executed
    5.13 +  action         = action,         -- name of the action to be executed
    5.14 +  id             = id,             -- id to be returned by param.get_id(...) during execution
    5.15 +  params         = params,         -- parameters to be returned by param.get(...) during execution
    5.16 +  test_existence = test_existence  -- do not execute action but only check if it exists
    5.17  }
    5.18  
    5.19  Executes an action without associated filters.
    5.20 @@ -14,14 +15,20 @@
    5.21  function execute.action(args)
    5.22    local module = args.module
    5.23    local action = args.action
    5.24 -  trace.enter_action{ module = module, action = action }
    5.25 +  local test   = args.test_existence
    5.26 +  if not test then
    5.27 +    trace.enter_action{ module = module, action = action }
    5.28 +  end
    5.29    local action_status = execute.file_path{
    5.30      file_path = encode.file_path(
    5.31        WEBMCP_BASE_PATH, 'app', WEBMCP_APP_NAME, module, '_action', action .. '.lua'
    5.32      ),
    5.33      id     = args.id,
    5.34 -    params = args.params
    5.35 +    params = args.params,
    5.36 +    test_existence = test
    5.37    }
    5.38 -  trace.execution_return{ status = action_status }
    5.39 +  if not test then
    5.40 +    trace.execution_return{ status = action_status }
    5.41 +  end
    5.42    return action_status
    5.43  end
     6.1 --- a/framework/env/execute/file_path.lua	Thu Mar 26 16:38:30 2015 +0100
     6.2 +++ b/framework/env/execute/file_path.lua	Thu Mar 26 16:40:04 2015 +0100
     6.3 @@ -1,20 +1,29 @@
     6.4  --[[--
     6.5 -status_code =             -- status code returned by the executed lua file (a string)
     6.6 +status_code =                      -- status code returned by the executed lua file (a string)
     6.7  execute.file_path{
     6.8 -  file_path = file_path,  -- path to a Lua source or byte-code file
     6.9 -  id        = id,         -- id to be returned by param.get_id(...) during execution
    6.10 -  params    = params      -- parameters to be returned by param.get(...) during execution
    6.11 +  file_path      = file_path,      -- path to a Lua source or byte-code file
    6.12 +  id             = id,             -- id to be returned by param.get_id(...) during execution
    6.13 +  params         = params,         -- parameters to be returned by param.get(...) during execution
    6.14 +  test_existence = test_existence  -- do not execute view or action but only check if it exists
    6.15  }
    6.16  
    6.17 -This function loads and executes a lua file specified by a given path. If an "id" or "params" are provided, the param.get_id(...) and/or param.get(...) functions will return the provided values during execution. The lua routine must return true, false, nil or a string. In case of true or nil, this function returns the string "ok", in case of false, this function returns "error", otherwise the string returned by the lua routine will be returned by this function as well.
    6.18 +This function loads and executes a Lua file specified by a given path. If an "id" or "params" are provided, the param.get_id(...) and/or param.get(...) functions will return the provided values during execution. The Lua routine must return true, false, nil or a string. In case of true or nil, this function returns the string "ok", in case of false, this function returns "error", otherwise the string returned by the lua routine will be returned by this function as well.
    6.19  
    6.20  --]]--
    6.21  
    6.22  function execute.file_path(args)
    6.23    local file_path = args.file_path
    6.24 -  local id        = args.id
    6.25 -  local params    = args.params
    6.26 -  local func, load_errmsg = assert(loadcached(file_path))
    6.27 +  local test = args.test_existence
    6.28 +  if test then
    6.29 +    if loadcached(file_path) then
    6.30 +      return true
    6.31 +    else
    6.32 +      return false
    6.33 +    end
    6.34 +  end
    6.35 +  local id     = args.id
    6.36 +  local params = args.params
    6.37 +  local func = assert(loadcached(file_path))
    6.38    if id or params then
    6.39      param.exchange(id, params)
    6.40    end
     7.1 --- a/framework/env/execute/view.lua	Thu Mar 26 16:38:30 2015 +0100
     7.2 +++ b/framework/env/execute/view.lua	Thu Mar 26 16:40:04 2015 +0100
     7.3 @@ -1,9 +1,11 @@
     7.4  --[[--
     7.5 +view_exists =       -- boolean returned if "test_existence" is set to true, otherwise no value returned
     7.6  execute.view{
     7.7    module = module,  -- module name of the view to be executed
     7.8    view   = view,    -- name of the view to be executed
     7.9    id     = id,      -- id to be returned by param.get_id(...) during execution
    7.10 -  params = params   -- parameters to be returned by param.get(...) during execution
    7.11 +  params = params,   -- parameters to be returned by param.get(...) during execution
    7.12 +  test_existence = test_existence  -- do not execute view but only check if it exists
    7.13  }
    7.14  
    7.15  Executes a view directly (without associated filters).
    7.16 @@ -12,14 +14,23 @@
    7.17  
    7.18  function execute.view(args)
    7.19    local module = args.module
    7.20 -  local view = args.view
    7.21 -  trace.enter_view{ module = module, view = view }
    7.22 -  execute.file_path{
    7.23 +  local view   = args.view
    7.24 +  local test   = args.test_existence
    7.25 +  if not test then
    7.26 +    trace.enter_view{ module = module, view = view }
    7.27 +  end
    7.28 +  local result = execute.file_path{
    7.29      file_path = encode.file_path(
    7.30        WEBMCP_BASE_PATH, 'app', WEBMCP_APP_NAME, module, view .. '.lua'
    7.31      ),
    7.32      id     = args.id,
    7.33 -    params = args.params
    7.34 +    params = args.params,
    7.35 +    test_existence = test
    7.36    }
    7.37 -  trace.execution_return()
    7.38 +  if not test then
    7.39 +    trace.execution_return()
    7.40 +  end
    7.41 +  if test then
    7.42 +    return result
    7.43 +  end
    7.44  end
     8.1 --- a/framework/env/request/handler.lua	Thu Mar 26 16:38:30 2015 +0100
     8.2 +++ b/framework/env/request/handler.lua	Thu Mar 26 16:40:04 2015 +0100
     8.3 @@ -8,16 +8,6 @@
     8.4  
     8.5  --]]--
     8.6  
     8.7 -local function file_exists(filename)
     8.8 -  local file = io.open(filename, "r")
     8.9 -  if file then
    8.10 -    io.close(file)
    8.11 -    return true
    8.12 -  else
    8.13 -    return false
    8.14 -  end
    8.15 -end
    8.16 -
    8.17  function request.handler(http_request)
    8.18    request._http_request = http_request
    8.19    local path = http_request.path
    8.20 @@ -105,12 +95,11 @@
    8.21          }
    8.22          if
    8.23            request.get_404_route() and
    8.24 -          not file_exists(
    8.25 -            encode.action_file_path{
    8.26 -              module = request.get_module(),
    8.27 -              action = request.get_action()
    8.28 -            }
    8.29 -          )
    8.30 +          not execute.action{
    8.31 +            module = request.get_module(),
    8.32 +            action = request.get_action(),
    8.33 +            test_existence = true
    8.34 +          }
    8.35          then
    8.36            request.set_status("404 Not Found")
    8.37            request.forward(request.get_404_route())
    8.38 @@ -171,12 +160,11 @@
    8.39          }
    8.40          if
    8.41            request.get_404_route() and
    8.42 -          not file_exists(
    8.43 -            encode.view_file_path{
    8.44 -              module = request.get_module(),
    8.45 -              view   = request.get_view()
    8.46 -            }
    8.47 -          )
    8.48 +          not execute.view{
    8.49 +            module = request.get_module(),
    8.50 +            view   = request.get_view(),
    8.51 +            test_existence = true
    8.52 +          }
    8.53          then
    8.54            request.set_status("404 Not Found")
    8.55            request.forward(request.get_404_route())

Impressum / About Us