Uploading an image using LuaSocket - lua

I'm trying to upload an image using luaSocket.
Here is my Lua code:
function uploadFile(dir)
local resp = {}
local body,code,headers,status = http.request{
url = "my_url",
method = "POST",
headers = {
["Content-Type"] = "application/x-www-form-urlencoded",
["Content-Length"] = file_size
},
source = ltn12.source.file(io.open(dir),"rb"),
sink = ltn12.sink.table(resp)
}
print(body,code,status)
if headers then for k,v in pairs(headers) do print(k,v) end end end
My php code is:
<?php
copy("php://input","test");
echo("OK");
?>
When I try to upload the image I don't get any error but body and status are nil, but code is "timeout".
But the script works fine if I try to upload a text file.
Any help is appreciated. Thanks.

You are passing "rb" as parameter to ltn12.sink.file instead of io.open. Change the statement to:
source = ltn12.source.file( io.open(dir,"rb") ),

Related

wrk with lua script - generating multiple POST requests with different body

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

How to return file object from google drive download

I'm new to Rails.
I have a method that downloads a file from google drive and saves it in the local disc. When the file is downloaded, the console returns nil, but the file is in the folder.
I need to use this file in my controller, but if the download method is returning nil I can't pass it around as an object.
download method:
def download
found = google_files.select { |f| f.id == file_id }
file_title = found.first.title
file = session.file_by_title(file_title)
path = File.join(Backup.base_directory, file_title)
file.download_to_file("#{path}")
end
Controller:
def create
# file_id = params.fetch(:file_id)
file_id = "0Byyflt8z3jarbm5DZGNNVXZSWjg"
#backup = DiscourseDownloadFromDrive::DriveDownloader.new(file_id).download
end
console output after executing the download method:
[...]
Writing chunk (1397 bytes)
Writing chunk (1397 bytes)
Writing chunk (1397 bytes)
Writing chunk (619 bytes)
Success - nil
=> nil
[4] pry(main)>
Logger:
Rails.logger.debug(">>> #BACKUP >>>: #{#backup.inspect}")
D, [2017-09-07T20:21:24.835450 #7755] DEBUG -- : >>> #BACKUP >>>: nil
Any hint on how to proceed with this would be very much appreciated!
Your download method always returns nothing but nil. That's because the gem's download_to_file always returns nil.
You shoud change your download method for it to return something, that you can use to get the file. I think this method should return the path to the downloaded file.
def download
found = google_files.select { |f| f.id == file_id }
file_title = found.first.title
file = session.file_by_title(file_title)
path = File.join(Backup.base_directory, file_title)
file.download_to_file("#{path}")
path
end
Now you can use it in the controller:
def create
# file_id = params.fetch(:file_id)
file_id = "0Byyflt8z3jarbm5DZGNNVXZSWjg"
file_path = DiscourseDownloadFromDrive::DriveDownloader.new(file_id).download
#backup = File.open(file_path) # do whatever you want with the file, since now you know how to get it
end

why I use AsyncHTTPClient timeout?

#tornado.web.authenticated
#tornado.web.asynchronous
#tornado.gen.coroutine
def post(self):
try:
files_body = self.request.files['file']
except:
error_msg = u"failed to upload file"
error_msg = self.handle_error(error_msg)
self.finish(dict(is_succ=False, error_msg=error_msg))
return
file_ = files_body[0]
filename = file_['filename']
# asynchronous request, obtain OCR info
files = [('image', filename, file_['body'])]
fields = (('api_key', config.OCR_API_KEY), ('api_secret', config.OCR_API_SECRET))
content_type, body = encode_multipart_formdata(fields, files)
headers = {"Content-Type": content_type, 'content-length': str(len(body))}
request = tornado.httpclient.HTTPRequest(config.OCR_HOST, method="POST", headers=headers, body=body,
validate_cert=False, request_timeout = 30)
try:
response = yield tornado.httpclient.AsyncHTTPClient().fetch(request)
except Exception, e:
logging.error(u'orc timeout {}'.format(e))
error_msg = u"OCR timeout"
error_msg = self.handle_error(error_msg)
self.finish(dict(is_succ=False, error_msg=error_msg))
return
if not response.error and response.body:
data = json.loads(response.body)
self.extra_info(data)
result = dict(is_succ=True, error_msg=u"", data=data)
else:
result = dict(is_succ=False, error_msg=u"request timeout", data={})
self.finish(result)
as the code shown, I want to write an api to handle id-card picture upload, and post a request to third part interface for getting the information of id-card.
This api can run well on my PC,however it timeouts on Testing Server. I cannot figure out where the problem is.

Convert image into base64 using capybara

I'm currently using capybara to run some scrapping tasks as well as site testing. I have been having difficulties in downloading images/files using capybara. All the documentations I found only guides on simple buttons,forms, links interaction.
Would really appreciate it if someone knows how to download/convert images on a webpage into base64 format.
This example extracts an image from a web page with Capybara / Selenium :
require 'capybara'
JS_GET_IMAGE = "
var ele = arguments[0], callback = arguments[1], img = new Image();
img.crossOrigin = 'Anonymous';
img.onload = function(){
var cnv = document.createElement('CANVAS');
cnv.width = this.width;
cnv.height = this.height;
cnv.getContext('2d').drawImage(this, 0, 0);
var type = this.src.endsWith('png') ? 'png' : 'jpeg';
callback(cnv.toDataURL('image/' + type).substring(22));
};
var src = ele.src || window.getComputedStyle(ele).backgroundImage;
img.src = /https?:/.test(src) ? src.match(/https?:[^\"')]+/)[0] : callback(''); "
session = Capybara::Session.new(:selenium)
driver = session.driver.browser
driver.manage.timeouts.script_timeout = 5000
# navigate to google
session.visit "https://www.google.co.uk/"
# get the logo element
ele = session.find(:css, '#hplogo img:nth-child(1)')
# get the logo as base64 string
imgBase64 = driver.execute_async_script(JS_GET_IMAGE, ele.native)
# save to a file
file = File.new("C:\\temp\\image." + (imgBase64[0] == 'i' ? 'png' : 'jpg'), 'wb')
file.write(Base64.decode64(imgBase64))
file.close
Just looked through the capybara gem and found a .render_base64 and save_screenshot method which could save the image into png or jpg file and after that i could crop the part i wanted. Method can be found here: https://github.com/teampoltergeist/poltergeist

How to create a request object?

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

Resources