2017-08-22 58 views
1

以下代碼按預期工作,但只能使用一次。Openresty Lua腳本只能使用一次

require("loadCheckfile") 
require("checkValPairs") 
local checklist = loadCheckfile("/home/myname/code/workbench/src/check.lst") 

local keyList = {} 
local valList = {} 

-- Load GET arguments into tables 
local args = ngx.req.get_uri_args() 
for key, val in pairs(args) do 
    table.insert(keyList, key) 
    table.insert(valList, val) 
end 

-- show values in table (just for testing) 
ngx.say(unpack(keyList)) 
ngx.say(unpack(valList)) 


local key1 

-- search for keywords and look them up in the checklist 
for i = 1, table.maxn(keyList) do 
    if keyList[i] == "user" then 
     key1 = i 
     for j = 1, table.maxn(keyList) do 
      if keyList[j] == "pass" then 
       doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j]) 
      end 
     end 
    end 
end 

-- Show wether the combination fits or not 
ngx.say(doesFit) 

在第二輪,甚至從一個新的瀏覽器窗口,我得到以下錯誤:

*1 lua entry thread aborted: runtime error: /home/myname/code/workbench/src/handler.lua:3: attempt to call global 'loadCheckfile' (a nil value)

nginx.conf(僅用於研究與開發,而不是最後一個):

user root; 

worker_processes 1; 
daemon off; 
error_log /dev/stdout warn; 

events { 
    worker_connections 32; 
} 

http { 
    default_type text/html; 
    access_log off; 

    lua_package_path '/home/myname/code/workbench/src/?.lua;;'; 
    server { 
     listen 80; 

     location/{ 
      content_by_lua_file /home/myname/code/workbench/src/handler.lua; 
     } 
    } 
} 

loadCheckfile.lua:

local function fillChecklistTable(checklist, valueLine) 
    repeat 
     firstValLength = string.find(valueLine,"=") 
     firstVal = string.sub(valueLine, 1, firstValLength-1) 

     valueLine = string.sub(valueLine, firstValLength+1) 

     secondValLength = string.find(valueLine, ",") 

     if secondValLength ~= nil then 
      secondVal = string.sub(valueLine, 1, secondValLength-1) 
     else 
      secondVal = valueLine 
     end 

     if checklist[firstVal] == nil then 
      checklist[firstVal] = {secondVal} 
     else 
      table.insert(checklist[firstVal], secondVal) 
     end 

     if secondValLength ~= nil then 
      valueLine = string.sub(valueLine, secondValLength+1) 
     else 
      valueLine = nil 
     end 

    until valueLine == nil 
end 

checklist = {} 

function loadCheckfile(checkfile) 
    local values = io.open(checkfile) 
    local valueLine = values:read() 

    while valueLine ~= nil do 
     fillChecklistTable(checklist, valueLine) 
     valueLine = values:read() 
    end 
    return checklist 
end 

任何人都知道這個小菜再次做錯了什麼?提前致謝!

更新:

handler.lua

checklist = {} 

local checkFile = require("loadCheckfile") 
local checkPairs = require("checkValPairs") 

local checklist = checkFile.loadCheckfile("/home/myname/code/workbench/src/pw_list.txt") 

local keyList = {} 
local valList = {} 

local args = ngx.req.get_uri_args() 
for key, val in pairs(args) do 
    table.insert(keyList, key) 
    table.insert(valList, val) 
end 


ngx.say(unpack(keyList)) 
ngx.say(unpack(valList)) 


local key1 

for i = 1, table.maxn(keyList) do 
    if keyList[i] == "user" then 
     key1 = i 
     for j = 1, table.maxn(keyList) do 
      if keyList[j] == "pass" then 
       doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j]) 
      end 
     end 
    end 
end 

ngx.say(doesFit) 

loadCheckfile.lua

module("loadCheckfile", package.seeall) 

local function fillChecklistTable(checklist, valueLine) 
    repeat 
     firstValLength = string.find(valueLine,"=") 
     firstVal = string.sub(valueLine, 1, firstValLength-1) 

     valueLine = string.sub(valueLine, firstValLength+1) 

     secondValLength = string.find(valueLine, ",") 

     if secondValLength ~= nil then 
      secondVal = string.sub(valueLine, 1, secondValLength-1) 
     else 
      secondVal = valueLine 
     end 

     if checklist[firstVal] == nil then 
      checklist[firstVal] = {secondVal} 
     else 
      table.insert(checklist[firstVal], secondVal) 
     end 

     if secondValLength ~= nil then 
      valueLine = string.sub(valueLine, secondValLength+1) 
     else 
      valueLine = nil 
     end 

    until valueLine == nil 
end 

checklist = {} 

function loadCheckfile.loadCheckfile(checkfile) 
    local values = io.open(checkfile) 
    local valueLine = values:read() 

    while valueLine ~= nil do 
     fillChecklistTable(checklist, valueLine) 
     valueLine = values:read() 
    end 
    return checklist 
end 

根據this source我已經把模塊只進loadCheckfile.lua和checkValPairs。 LUA。然而,即使將它放入 handler.lua也不起作用(只需嘗試)。

+0

發佈nginx配置也loadCheckfile –

+0

將lua_code_cache關閉添加到nginx.conf中解決了這個問題。但我非常懷疑這是對工作環境的渴望。 – Mathias

回答

0

使用lua_code_cache off是一個很大的性能問題,因爲它要一次又一次地執行代碼。試試這個

local checkFile = require("loadCheckfile") 
local checkPairs = require("checkValPairs") 
local checklist = checkFile.loadCheckfile("/home/myname/code/workbench/src/check.lst") 

讓我知道這是否正常工作,我會添加一個解釋

+0

我得到一行'local checklist = checkFile.loadCheckfile(「/ home/myname/code/workbench/src/check.lst」)'錯誤'陳述_attempt索引本地'checkFile'(一個布爾值)_ – Mathias

+0

Add這對你的文件'模塊(「loadCheckfile」,package.seeall)「的頂部,改變其他文件的名稱,看看它是否工作 –

+0

它仍然試圖索引本地'checkFile'(一個布爾值)._ – Mathias

0

注意

請不要使用此解決方案。雖然它的確行得通但並不好。 我會在這裏留下來理解其中的一個答案。

原來的答覆:

解決我的問題是使通過nginx.conf全球模塊。

因此,我在配置中插入了一個init_by_lua_file,調用一個預加載lua文件,該文件包含我需要的所有函數,並在全局級別上提供此函數。

的.conf文件:

user root; 

worker_processes 1; 
daemon off; #used for developing purpose 
error_log /dev/stdout warn; #as well for developing 

events { 
    worker_connections 32; 
} 


http { 
    default_type text/html; 
    access_log off; 

    lua_package_path '/home/myname/code/workbench/src/?.lua;;'; 

    init_by_lua_file '/home/myname/code/workbench/src/preLoader.lua'; 

    server { 
     listen 80; 

     location/{ 
      content_by_lua_file /home/myname/code/workbench/src/handler.lua; 
     } 
    } 
} 

新preLoader.lua:

require("loadCheckfile") 
require("checkValPairs") 
checklist = loadCheckfile("/home/myname/code/workbench/src/check.list") 

最後的handler.lua:

local keyList = {} 
local valList = {} 

-- Load GET arguments into tables 
local args = ngx.req.get_uri_args() 
for key, val in pairs(args) do 
    table.insert(keyList, key) 
    table.insert(valList, val) 
end 

-- show values in table (just for testing) 
ngx.say(unpack(keyList)) 
ngx.say(unpack(valList)) 


local key1 

-- search for keywords and look them up in the checklist 
for i = 1, table.maxn(keyList) do 
    if keyList[i] == "user" then 
     key1 = i 
     for j = 1, table.maxn(keyList) do 
      if keyList[j] == "pass" then 
       doesFit = checkValPairs(checklist, keyList[key1], valList[key1], keyList[j], valList[j]) 
      end 
     end 
    end 
end 

-- Show wether the combination fits or not 
ngx.say(doesFit) 
1

您的解決方案應該可行,但有要知道的東西。

OpenResty爲每個請求創建一個新的全局環境的協程(Lua綠色線程),但是require()只加載一次模塊,從此再也不執行main chunk。因此,您在這些模塊中設置的所有全局變量僅在第一次請求期間存在。此外,如果您的處理程序進行I/O操作,則會出現第二個請求到達並竊取其全部內容的窗口,因此不會完成請求。準確的解決方案是從來沒有全局在你的模塊OpenResty(和普通的Lua也因爲破壞_G是一般一個壞主意),但遵循標準模塊語言,而不是:

-- mymod.lua 

local M = { } 

local function private() -- for internal use 
    ... 
end 

function M.public() -- to be 'exported' 
    ... 
end 

return M -- this will be returned from require 


-- uses_mymod.lua 

local mymod = require 'mymod' -- mymod is M from above 

mymod.public() 

這樣模塊創建一個具有函數的表格,而不是將它們設置爲全局變量並將其返回至require()。每次調用require()都會返回它。

當你厭倦了當地功能的可見性規則時,引入另一個local m = { }或任何你喜歡的名字來命名它,並將所有私人存儲在那裏。之後,在你的眼睛變得醜陋,去高級主題,如Lua環境(setfenv(),setmetatable())。如果你不想去的細節,把此行local M = { }之前到每個模塊:

setfenv(1, setmetatable({ }, { __index = getfenv(0) })) 

你所有的全局變量將是局部的模塊,這樣就可以避免m(但不M,仍然需要'出口')。

+0

謝謝。你的回答幫助我理解了我原來的問題中的錯誤。我從來沒有在模塊末尾返回函數,只是函數本身的表。 – Mathias