• xavante运行cgilua流程


    安装软件

    需要安装三个lua 库:  xavante wsapi cgilua

    luarocks install xavante

    http://keplerproject.github.io/xavante/manual.html#install

    Xavante is a Lua HTTP 1.1 Web server that uses a modular architecture based on URI mapped handlers. Xavante currently offers a file handler, a redirect handler and a WSAPI handler. Those are used for general files, URI remapping and WSAPI applications respectively.

    luarocks install wsapi-xavante

    http://keplerproject.github.io/wsapi/index.html

    WSAPI is an API that abstracts the web server from Lua web applications. By coding against WSAPI your application can run on any of the supported servers and interfaces (currently CGI, FastCGI and Xavante, on Windows and UNIX-based systems).

    https://github.com/keplerproject/wsapi

    cgilua

    luarocks install cgilua

    https://github.com/keplerproject/cgilua

    CGILua is a tool for creating dynamic Web pages and manipulating input data from Web forms. CGILua allows the separation of logic and data handling from the generation of pages, making it easy to develop web applications with Lua.

    运行脚本

    切换到cgilua样例目录

    root@fqs:/home/share/cgilua-master/cgilua-master/examples# lua xavante_cgilua.lua
    [2016-06-22 22:16:50] Xavante started on port(s) 8080

    脚本内容 laucher:

    xavante = require "xavante"
    xavante.filehandler = require "xavante.filehandler"
    xavante.cgiluahandler = require "xavante.cgiluahandler"
    xavante.redirecthandler = require "xavante.redirecthandler"

    -- Define here where Xavante HTTP documents scripts are located
    local webDir = "."

    local simplerules = {

       { -- URI remapping example
          match = "^[^%./]*/$",
          with = xavante.redirecthandler,
          params = {"index.lp"}
       },

       { -- cgiluahandler example
          match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
          with = xavante.cgiluahandler.makeHandler (webDir)
       },
       
       { -- filehandler example
          match = ".",
          with = xavante.filehandler,
          params = {baseDir = webDir}
       },
    }

    xavante.HTTP{
       server = {host = "*", port = 8080},
       
       defaultHost = {
          rules = simplerules
       },
    }


    -- Displays a message in the console with the used ports
    xavante.start_message(function (ports)
        local date = os.date("[%Y-%m-%d %H:%M:%S]")
        print(string.format("%s Xavante started on port(s) %s",
                    date, table.concat(ports, ", ")))
    end)

    xavante.start()

    WSAPI Xavante 安装后自带launcher

    http://keplerproject.github.io/wsapi/manual.html

    Xavante

    If you installed the wsapi-xavante package you already have a Xavante launcher with WSAPI support. Just run the wsapi script in the path you want as your document root, and point your browser either to the hello.lua or hello.ws script (both extensions are treated as WSAPI applications). See wsapi --help for the launcher's configuration options.

    launcher:

    root@fqs:/usr/local/bin# cat wsapi
    #!/bin/sh

    exec '/usr/bin/lua5.1' -e 'package.path="/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;"..package.path; package.cpath="/root/.luarocks/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so;"..package.cpath' -e 'local k,l,_=pcall(require,"luarocks.loader") _=k and l.add_context("wsapi-xavante","1.6.1-1")' '/usr/local/lib/luarocks/rocks/wsapi-xavante/1.6.1-1/bin/wsapi' "$@"


    root@fqs:/usr/local/bin#

    主要实现在 '/usr/local/lib/luarocks/rocks/wsapi/1.6.1-1/bin/wsapi'

    此内容,与运行脚本章节的 launcher 功能角色上相同, 但是其比较完善。

    root@fqs:/usr/local/bin# cat /usr/local/lib/luarocks/rocks/wsapi-xavante/1.6.1-1/bin/wsapi
    #!/usr/bin/env lua

    local lfs = require "lfs"
    local util = require "wsapi.util"
    local wsx = require "wsapi.xavante"
    local xavante = require "xavante"
    local filehandler = require "xavante.filehandler"
    local redirecthandler = require "xavante.redirecthandler"

    local usage = [[
    Usage: wsapi [options] [document root]

    Starts a Xavante instance to serve static files and WSAPI applications.
    Treats .lua and .ws files as WSAPI applications, and everything else as
    static (but see the --cgilua and --op options, below).

    The default document root is the current path.

    Options:

    -c<file>, --config=<file>   Runs the specified file for additional
                                configuration before starting the server
    -l<file>, --log=<file>      Logs all output to the file (default stdout
                                and stderr)
    -p<port>, --port=<port>     Binds to the specified port (default 8080)
    --cgilua                    Adds .lp and .cgi rules for CGILua pages and
                                scripts
    --op                        Adds an .op rule that for Orbit pages
    -r, --reload                Reloads applications on every request
    -h, --help                  Shows this help screen

    ]]

    local config = {}

    local opts, args = util.getopt({ ... }, "clp")

    if opts.h or opts.help then
      print(usage)
      os.exit()
    end

    local config = {
      docroot = args[1] or lfs.currentdir(),
      logfile = opts.l or opts.log,
      port = tonumber(opts.p or opts.port) or 8080,
      start_message = function (ports)
                         local date = os.date("[%Y-%m-%d %H:%M:%S]")
                         print(string.format("%s Xavante started on port(s) %s",
                                             date, table.concat(ports, ", ")))
                      end,
      rules = {},
      is_finished = function() return false end,
      reload = opts.r or opts.reload,
      isolated = true
    }

    local config_file = opts.c or opts.config

    if config_file then
      local f, err = util.loadfile(config_file, setmetatable(config, { __index = _G }))
      if not f then
        io.stderr:write("Cannot load config file " .. config_file .. ": " .. err .. " ")
        os.exit()
      end
      local res, err = pcall(f)
      if not res then
        io.stderr:write("Error in config file: " .. err .. " ")
        os.exit()
      end
      setmetatable(config, nil)
    end

    if config.logfile then
      local tostring = tostring
      local log = io.open(config.logfile, "a+")
      if not log then
        error("Could not open log file. Please check the write permissions for: " .. config.logfile)
      end
      io.stdout = log
      io.stderr = log
      print = function (...)
        local nargs = select('#', ...)
        for i = 1, nargs-1 do
          log:write(tostring((select(i, ...))))
          log:write(" ")
        end
        log:write(tostring(select(nargs, ...)))
        log:write(" ")
      end
    end

    local ONE_HOUR = 60 * 60
    local ONE_DAY = 24 * ONE_HOUR

    local launcher_params = {
      isolated = config.isolated,
      reload = config.reload,
      period = config.period or ONE_HOUR,
      ttl = config.ttl or ONE_DAY
    }

    config.rules = config.rules or {}

    local function addrule(rule)
      config.rules[#config.rules+1] = rule
    end

    addrule{ -- URI remapping example
      match = "^/$",
      with = redirecthandler,
      params = {"index.html"}
    }

    addrule{ -- wsapihandler example
      match = {"%.lua$", "%.lua/" },
      with = wsx.makeGenericHandler (config.docroot, launcher_params)
    }

    addrule{ -- wsapihandler example
      match = {"%.ws$", "%.ws/" },
      with = wsx.makeGenericHandler (config.docroot, launcher_params)
    }

    if opts.cgilua then
      local hcgi = require "xavante.cgiluahandler"
      addrule{
        match = {"%.lp$", "%.lp/.*$", "%.cgi$", "%.cgi/.*$" },
        with = hcgi.makeHandler (config.docroot, launcher_params)
      }
    end
    if opts.op then
      local hop = require "orbit.ophandler"
      addrule{
        match = {"%.op$", "%.op/.*$" },
        with = hop.makeHandler (config.docroot, launcher_params)
      }
    end

    addrule{ -- filehandler example
      match = ".",
      with = filehandler,
      params = { baseDir = config.docroot }
    }

    -- Displays a message in the console with the used ports
    xavante.start_message(config.start_message)

    io.stdout:write("[Xavante launcher] Starting Xavante... ")

    xavante.HTTP{
        server = {host = "*", port = config.port},

        defaultHost = {
            rules = config.rules
        },
    }

    res, err = pcall(xavante.start, function (...)
                                       io.stdout:flush()
                                       io.stderr:flush()
                                       return config.is_finished(...)
                                    end, config.timeout)
    if not res then
       io.stderr:write(err .. " ")
    else
       io.stderr:write("[Xavante launcher] Xavante stopped ")
    end
    root@fqs:/usr/local/bin#

    运行流程分析

    1、 xavante 负责服务器的启动, 并制定 cgilua 请求处理的handler注册

       { -- cgiluahandler example
          match = {"%.lp$", "%.lp/.*$", "%.lua$", "%.lua/.*$" },
          with = xavante.cgiluahandler.makeHandler (webDir)
       },

    2、xavante.cgiluahandler.makeHandler (webDir) , handler的构造

    -------------------------------------------------------------------------------
    -- Returns the CGILua handler
    -------------------------------------------------------------------------------
    function _M.makeHandler (diskpath, params)
       params = setmetatable(params or {}, { __index = { modname = "wsapi.sapi",
          bootstrap = bootstrap } })
       local sapi_loader = common.make_isolated_launcher(params)
       return xavante.makeHandler(sapi_loader, nil, diskpath)
    end

    其中,handler构造依赖了 xavante的wsapi, with的值可以是 function(req, res)

    local xavante = require "wsapi.xavante"  --- 专门针对  xavante写的wsapi的适配

    -- Makes a WSAPI handler for a single WSAPI application
    function _M.makeHandler (app_func, app_prefix, docroot, app_path, extra_vars)
      return function (req, res)
        return wsapihandler(req, res, app_func, app_prefix, docroot, app_path, extra_vars)
      end
    end

    wsapi.xavante中存在 构造 cgivars 表。

    make_handler 入参 wsapi_loader需要 wsapi.sapi文件支持

       params = setmetatable(params or {}, { __index = { modname = "wsapi.sapi",
          bootstrap = bootstrap } })
       local sapi_loader = common.make_isolated_launcher(params)

    此loader即加载 wsapi.sapi文件, 文件被rings包裹运行, 即 wsapi.sapi –> cgilua 都是在独立环境下运行

    前面 “wsapi.xavante中存在 构造 cgivars 表” 也会传入 独立的运行环境。

    wsapi.sapi 直接 调用 cgilua

      local cgilua = require "cgilua"
      cgilua.main()
      return res:finish()
    end

    WSAPI Xavante 安装后自带 wsapi.cgi 程序

    root@fqs:/usr/local/bin# ls
    cgilua.cgi  cgilua.fcgi  summary.lua  wsapi  wsapi.cgi
    root@fqs:/usr/local/bin#
    root@fqs:/usr/local/bin#
    root@fqs:/usr/local/bin# cat wsapi.cgi
    #!/bin/sh

    exec '/usr/bin/lua5.1' -e 'package.path="/root/.luarocks/share/lua/5.1/?.lua;/root/.luarocks/share/lua/5.1/?/init.lua;/usr/local/share/lua/5.1/?.lua;/usr/local/share/lua/5.1/?/init.lua;"..package.path; package.cpath="/root/.luarocks/lib/lua/5.1/?.so;/usr/local/lib/lua/5.1/?.so;"..package.cpath' -e 'local k,l,_=pcall(require,"luarocks.loader") _=k and l.add_context("wsapi","1.6.1-1")' '/usr/local/lib/luarocks/rocks/wsapi/1.6.1-1/bin/wsapi.cgi' "$@"
    root@fqs:/usr/local/bin#

    实现文件:

    root@fqs:/usr/local/bin# cat /usr/local/lib/luarocks/rocks/wsapi/1.6.1-1/bin/wsapi.cgi
    #!/usr/bin/lua

    -- Generic WSAPI CGI launcher, extracts application to launch
    -- either from the command line (use #!wsapi in the script)
    -- or from SCRIPT_FILENAME/PATH_TRANSLATED

    local wsapi = require "wsapi"
    local common = require "wsapi.common"
    local cgi = require "wsapi.cgi"

    local arg_filename = (...)

    local function wsapi_loader(wsapi_env)
      local path, file, modname, ext =
          common.find_module(wsapi_env, arg_filename, "wsapi.cgi", { "SCRIPT_FILENAME", "PATH_TRANSLATED" })
      if not path then
        error({ 404, "Resource " .. wsapi_env.SCRIPT_NAME .. " not found" })
      end
      wsapi.app_path = path
      local app = common.load_wsapi(path, file, modname, ext)
      wsapi_env.APP_PATH = path
      return app(wsapi_env)
    end

    cgi.run(wsapi_loader)
    root@fqs:/usr/local/bin#

    此cgi程序用于运行 满足 wsapi接口的应用脚本, 例如:

    http://keplerproject.github.io/wsapi/manual.html

    #!/usr/bin/env wsapi.cgi
    
    module(..., package.seeall)
    
    function run(wsapi_env)
      local headers = { ["Content-type"] = "text/html" }
    
      local function hello_text()
        coroutine.yield("<html><body>")
        coroutine.yield("<p>Hello Wsapi!</p>")
        coroutine.yield("<p>PATH_INFO: " .. wsapi_env.PATH_INFO .. "</p>")
        coroutine.yield("<p>SCRIPT_NAME: " .. wsapi_env.SCRIPT_NAME .. "</p>")
        coroutine.yield("</body></html>")
      end
    
      return 200, headers, coroutine.wrap(hello_text)
    end
  • 相关阅读:
    CF359B Permutation
    CF859C Pie Rules
    Contest 156
    Contest 155
    Range Module
    python-环境
    Git 使用
    Contest 154
    生命是一种长期而持续的累积过程
    Contest 153
  • 原文地址:https://www.cnblogs.com/lightsong/p/5608957.html
Copyright © 2020-2023  润新知