I'm learning web development with lua (wsapi and uWSGI).
I'm trying to create a request object (https://keplerproject.github.io/wsapi/libraries.html) to see what it look like (and how to use it). So I've set up a example code :
require "wsapi.cgi"
function run(wsapi_env)
local headers = { ["Content-type"] = "text/html" }
local function hello_text()
local result = "<html><body>\n"
result = result .. "<p> Hello Wsapi !</p>\n"
result = result .. "<p>PATH_INFO wsapi_env: " .. wsapi_env.PATH_INFO .. "</p>\n"
-- problematic code
local req = wsapi.request.new(wsapi_env)
if req
then
--condition to see if req was nill
result = result .. "<p>PATH INFO_POST : " .. req.POST .. "</p>\n"
result = result .. "<p>PATH INFO_GET : " .. req.GET .. "</p>\n"
else
result = result .. "<p> No request <\p>\n"
end
-- end of the problematic code
result = result .. "<p><form method=\"post\" action=\"hello.lua\">\n"
result = result .. "<textarea name=\"message\"> test </textarea>\n"
result = result .. "</form></p>\n"
result = result .. "</body></html>\n"
coroutine.yield(result)
end
return 200, headers, coroutine.wrap(hello_text)
end
return run
But when I use the request object, the client receive a blank page.
How can I create and use a request object ?
Thanks you for your answers !
Extra question : How do I redirect to another page ( to a static page on the same domain ) ?
Maybe this little code snippet will help:
local ws_request = require "wsapi.request"
function run(wsapi_env)
local qs = wsapi_env.QUERY_STRING
print("QUERY_STRING: " .. qs)
local req = ws_request.new(wsapi_env)
print(req.params.q)
end
Related
I wrote some lua script for wrk to generate multiple POST requests.
My problem is that my script is working only for the first request. All further generated requests are exactly the same as the first one. I would like that user variable will be new generated for each POST request:
lowerCase = "abcdefghijklmnopqrstuvwxyz"
characterSet = lowerCase
keyLength = 13
user = ""
math.randomseed(os.time())
for i = 1, keyLength do
rand = math.random(#characterSet)
user = user .. string.sub(characterSet, rand, rand )
end
wrk.path = "/somepath"
wrk.method = "POST"
wrk.body = [[{"username":"]].. user .. [[,"password":"somepassword"}]]
wrk.headers["Content-Type"] = "application/json"
Try something like this. It should execute request3 ~50% of the time, and the other two ~25% of the time. Cheers!
names = { "Maverick", "Goose", "Viper", "Iceman", "Merlin", "Sundown", "Cougar", "Hollywood", "Wolfman", "Jester" }
request1 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("POST", "/test1", headers, body)
end
request2 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("POST", "/test2", headers, body)
end
request3 = function()
headers = {}
headers["Content-Type"] = "application/json"
body = '{"name": ' .. names[math.random(#names)] .. '}'
return wrk.format("GET", "/test3", headers, body)
end
requests = {}
requests[0] = request1
requests[1] = request2
requests[2] = request3
requests[3] = request3
request = function()
return requests[math.random(0, 3)]()
end
response = function(status, headers, body)
if status ~= 200 then
io.write("------------------------------\n")
io.write("Response with status: ".. status .."\n")
io.write("------------------------------\n")
io.write("[response] Body:\n")
io.write(body .. "\n")
end
end
I'm not familiar with wrk.
I guess you're running that code multiple times within a second. As os.time has second accuracy you'll have the same randomseed and hence the same user name within that second.
From looking into the scripting examples I'd say the script is only evaluated once or maybe once per thread. Those examples implement functions that will be called by wrk. It wouldn't make sense to define those functions for every request.
Add a print to your script to make sure.
Here is an example that counts requests. You probably can put your code into that function
function request()
requests = requests + 1
return wrk.request()
end
in ZeroBrane Studio if I use "Project - complile (F7)" - what exactly does happen?
Will there be a standalone .exe created from my Lua code ?
And if so - in which directory ?
I use Windows 10.
(Couldn't find any information in the documention)
From what I see by a quick look into the source code it simply checks whether the code has any errors by loading it using loadstring which compiles the file.
There is no output file, just some text output about any errors.
But that's just an assumption. Feel free to check if this is actually the function called when you click that button.
https://github.com/pkulchenko/ZeroBraneStudio/blob/5daf55d79449431ca9794f6b8a65476dc203b780/src/editor
function CompileProgram(editor, params)
local params = {
jumponerror = (params or {}).jumponerror ~= false,
reportstats = (params or {}).reportstats ~= false,
keepoutput = (params or {}).keepoutput,
}
local doc = ide:GetDocument(editor)
local filePath = doc:GetFilePath() or doc:GetFileName()
local loadstring = loadstring or load
local func, err = loadstring(StripShebang(editor:GetTextDyn()), '#'..filePath)
local line = not func and tonumber(err:match(":(%d+)%s*:")) or nil
if not params.keepoutput then ClearOutput() end
compileTotal = compileTotal + 1
if func then
compileOk = compileOk + 1
if params.reportstats then
ide:Print(TR("Compilation successful; %.0f%% success rate (%d/%d).")
:format(compileOk/compileTotal*100, compileOk, compileTotal))
end
else
ide:GetOutput():Activate()
ide:Print(TR("Compilation error").." "..TR("on line %d"):format(line)..":")
ide:Print((err:gsub("\n$", "")))
-- check for escapes invalid in LuaJIT/Lua 5.2 that are allowed in Lua 5.1
if err:find('invalid escape sequence') then
local s = editor:GetLineDyn(line-1)
local cleaned = s
:gsub('\\[abfnrtv\\"\']', ' ')
:gsub('(\\x[0-9a-fA-F][0-9a-fA-F])', function(s) return string.rep(' ', #s) end)
:gsub('(\\%d%d?%d?)', function(s) return string.rep(' ', #s) end)
:gsub('(\\z%s*)', function(s) return string.rep(' ', #s) end)
local invalid = cleaned:find("\\")
if invalid then
ide:Print(TR("Consider removing backslash from escape sequence '%s'.")
:format(s:sub(invalid,invalid+1)))
end
end
if line and params.jumponerror and line-1 ~= editor:GetCurrentLine() then
editor:GotoLine(line-1)
end
end
return func ~= nil -- return true if it compiled ok
end
require 'nn'
criterion = nn.ClassNLLCriterion()
print(criterion)
this outputs
nn.ClassNLLCriterion
{
sizeAverage : true
output : 0
gradInput : DoubleTensor - empty
output_tensor : DoubleTensor - size: 1
target : LongTensor - size: 1
total_weight_tensor : DoubleTensor - size: 1
}
I would like to get this print output for logging purposes. Does anyone know how to do that?
Hmm I'm not sure how you get this output. When I run this code I get nn.ClassNLLCriterion. Maybe different Lua/Torch versions?
Anyway, if you want to have this info in a string, you might have to extract it yourself. This can easily be done doing a simple loop:
for k,v in pairs(criterion) do
print(k,v)
end
If you want the fancy print output then I suggest you look at TREPL's code (like #nobody suggested in the comments). It's all in Lua so it's very easy to replicate. More precisely, I recommend their sizestr(), print_new() and printvar() functions. Simply change them so instead of printing, they construct a string.
A quick example using their sizestr function:
-- Copy/Paste from trepl/init.lua
local function sizestr(x)
local strt = {}
if _G.torch.typename(x):find('torch.*Storage') then
return _G.torch.typename(x):match('torch%.(.+)') .. ' - size: ' .. x:size()
end
if x:nDimension() == 0 then
table.insert(strt, _G.torch.typename(x):match('torch%.(.+)') .. ' - empty')
else
table.insert(strt, _G.torch.typename(x):match('torch%.(.+)') .. ' - size: ')
for i=1,x:nDimension() do
table.insert(strt, x:size(i))
if i ~= x:nDimension() then
table.insert(strt, 'x')
end
end
end
return table.concat(strt)
end
local function sutoringu(elem)
local str = ''
if torch.isTensor(elem) then
str = sizestr(elem)
else
str = tostring(elem)
end
return str
end
local str = '{\n'
local tab = ' '
for k,v in pairs(criterion) do
str = str .. tab .. k .. ' : ' .. sutoringu(v) .. '\n'
end
str = str .. '}'
print(str)
This outputs the same thing as what you wished for, constructing a string in the process. It's far from optimal but it's a start.
Assuming I have a piece of code such as the following
aTable = {aValue=1}
aTable_mt = {}
print(aTable)
What must I do to make Lua print something like aTable current aValue = 1 as opposed to table: 0x01ab1d2.
So far I've tried setting the __tostring metamethod but that doesn't seem to be invoked by print. Is there some metamethod I've been missing or does the answer have nothing to do with metamethods?
__tostring works:
aTable = {aValue=1}
local mt = {__tostring = function(t)
local result = ''
for k, v in pairs(t) do
result = result .. tostring(k) .. ' ' .. tostring(v) .. ''
end
return result
end}
setmetatable(aTable, mt)
print(aTable)
This prints aValue 1 (with one extra whitespace, remove it in real code). The aTable part is not available, because aTable is a variable that references the table, not the content of the table itself.
I'm not sure how you set the metamethod, but the following code prints "stringified" for me:
local aTable = {a = 1, b = 2}
setmetatable(aTable, {__tostring = function() return "stringified" end})
print(aTable)
If you want lua to generally print all tables human readable, you could
hook up/overwrite the print function:
local orig_print = print
print = function(...)
local args = {...}
for i,arg in ipairs(args) do
if type(arg) == 'table' then
args[i] = serialize(arg)
end
end
orig_print(table.unpack(args))
end
serialize could be serpent or some other lib from here
Note that this must be done before any other module/script is loaded.
I'm trying to get the name of all the file saved in two folders, the name are saved as :
1.lua 2.lua 3.lua 4.lua and so on
the folders name are :
first folder : "/const/"
second folder: "/virt/"
what I'm trying to do is only get the number of the files and this works but not in the right order, when I get the 17 file for example I get the 17th delivered from the function before the 15 and this causes for me a problem here the code of the function that I'm using :
local virt_path = "/virt/"
local const_path = "/const"
local fs = require "lfs"
local const = {}
for num = 1, (numberoffile)do -- numberoffile is predfined and can't be change
const[num] = assert(
dofile (const_path .. mkfilename(num)),
"Failed to load constant ".. num ..".")
end
local function file_number() --this is the function that causes me a headach
local ci, co, num = ipairs(const)
local vi, vo, _ = fs.dir(virt_path)
local function vix(o)
local file = vi(o)
if file == nil then return nil end
local number = file:match("^(%d+).lua$")
if number == nil then return vix(o) end
return tonumber(number)
end
local function iter(o, num)
return ci(o.co, num) or vix(o.vo, num)
end
return iter, {co=co, vo=vo}, num
end
As I said the function delive the need return values but not the right Arithmetic order.
any idea what I'm doing wrong here ?
I use my path[1] library.
1 We fill table with filenames
local t = {}
for f in path.each("./*.lua", "n") do
t[#t + 1] = tonumber((path.splitext(f)))
end
table.sort(t)
for _, i in ipairs(t) do
-- do work
end
2 We check if files exists
for i = 1, math.huge do
local p = "./" .. i .. ".lua"
if not path.exists(p) then break end
-- do work
end
[1] https://github.com/moteus/lua-path