Lua socket example, trying different sites - lua

I am using this example. It prints the text based on this site http://www.google.com/robots.txt
local socket = require("socket")
client = socket.connect("google.com", 80)
client:send("GET /robots.txt HTTP/1.0\r\n\r\n")
while true do
s, status, partial = client:receive(1024)
print(s or partial)
if status == "closed" then
break
end
end
client:close()
I use:
local socket = require("socket")
client = socket.connect("www.lua.org", 80)
client:send("GET /pil/9.4.html HTTP/1.0\r\n\r\n")
while true do
s, status, partial = client:receive(1024)
print(s or partial)
if status == "closed" then
break
end
end
client:close()
But, as above, I try with this link, http://www.lua.org/pil/9.4.html and it doesn't work, saying "HTTP/1.0 302 Moved temporarily". Did same on many other sites, got similar results. Why is that so? Thanks a lot

You're receiving a redirect (HTTP 302 code) which should be handled by issuing a new request to the specified Location.
Rather than using raw sockets, you could use the high level HTTP module from the socket library, which provides a request method able to authomatically follow redirects.

Related

Ruby 2.3 - Adding Timeout error and notification to net:http request

I have a working system to produce errors and send them to be used by Active Admin.
For example in Active admin, for a specific page of our CMS, the page might execute :
url_must_be_accessible("http://www.exmaple.com", field_url_partner, "URL for the partner")
And this uses the code below to send to the Active Admin Editor different type of errors notifications:
module UrlHttpResponseHelper
def url_must_be_accessible(url, target_field, field_name)
if url
url_response_code = get_url_http_response(url).code.to_i
case url_response_code
when -1
# DNS issue; website does not exist;
errors.add(target_field,
"#{field_name}: DNS Problem -> #{url} website does not exist")
when 200
return
when 304
return
else
errors.add(target_field,
"#{field_name}: #{url} sends #{url_response_code} response code")
end
end
end
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Net::HTTP.get_response(uri)
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
end
end
In local mode, this worked great! But in production, we're on Heroku and when a request pn Heroku goes beyond 30 seconds like if you try on this link "http://www.exmaple.com", the app crashes with a "H12 error".
I'd like to add to the code above two things
- timeouts: i think i need both read_timeout and open_timeout and that the read_timeout + open_timeout should be < to 30 seconds, with let's take some security , better < 25seconds
if the request is still "going" after 25 seconds, then avoid reaching 30seconds by giving up/dropping the request
and catch this "we dropped the request intentionnally because risk of timeout" by sending a notification to the user. I'd like to use my current system with somehting along the lines of:
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -7) # = some random number
end
case url_response_code
when -7
errors.add(target_field,
"#{field_name}: We tried to reach #{url} but this takes too long and risks crashing the app. please check the url and try again.")
How can I create a code like -1 but another one to rescue this "timeout"/"drop the request attempt" that I myself enforce.
Tried but nothing works. I don't manage to create the code for catch and drop this request if reaches 25 seconds...
That's not very beautiful solution (see: https://medium.com/#adamhooper/in-ruby-dont-use-timeout-77d9d4e5a001), but I believe you still can use it here, because you only have one thing happening inside opposite to the example in the link, where multiple actions could cause non-obvious behavior:
def get_url_http_response(url)
uri = URI.parse(URI.encode(url))
request = Timeout.timeout(25) { Net::HTTP.get_response(uri) }
return request
rescue Errno::ECONNREFUSED, SocketError => e
OpenStruct.new(code: -1)
rescue Timeout::Error
# return here anything you want
end

How to read POST requests in Lua?

I have this Telegram bot written in Lua that I am doing as a hobby for a language network. And I have been reading new messages via the getUpdates API call all the time. Now I want to rewrite it to use webhooks, but I have no experience with that whatsoever. I have googled but didn't find anything certain. I kinda feel that WSAPI is the library to use, but I am not sure. Moreover, I am not really sure I need any special library just for reading POST requests (which is all that the Telegram bot API uses). I tried using sockets:
socket = require 'socket'
server = assert(socket.bind("*", 9000))
function read(client, pattern, prefix)
local data, emsg, partial = client:receive(pattern, prefix)
if data then
return data
end
if partial and #partial > 0 then
return partial
end
return nil, emsg
end
while true do
local client = server:accept()
client:settimeout(3)
local msg, err = read(client, '*a')
if not err then
print(msg)
client:close()
end
end
The print(msg) here gives me the full POST request including headers, which I am probably able to parse (the body is supposed to always be a JSON). I am not really that familiar with HTTP requests though and I'm not sure I can just throw away everything that goes before the first {.
My setup is Lua 5.2, Ubuntu x64 16.04 and Nginx. What I need to do is to receive and read POST requests, nothing more.
TL;DR: is it okay to parse the POST request I receive from the code above or am I missing something, like a library that'd make my life easier?
Thanks!

running a link through localhost on a live page

I have an external program running a local API that is set up to play wav files when an endpoint is hit.
In my development environment, it works fine, but when I push to live environment it doesn't work any longer.
Am i missing something?
thanks!
JqueryController
def playfile
require 'json'
HTTParty.get("http://192.168.1.161:5000/play/98")
response = HTTParty.get("http://192.168.1.161:5000/play/#{params[:id]}")
parsed = JSON.parse(response)
#message = params[:message]
Hint.first.update_attributes(message:#message)
if parsed['success'] == true
#success = "Success"
else
#success = "Failed"
end
end
The View
=form_tag("/jquery/playfile", method: 'post', remote:true) do
= label_tag 'hints on the tv!'
= hidden_field_tag :id , 39
=render 'layouts/play'
When I hit the endpoint .. googles inspector is showing a 'pending' request, which eventually dies, and returns an application error response (from heroku)
Im guessing it has something to do with not being allowed to hit a localhost address from a live site..is there a way to get around this?
You cannot access your LAN from the internet (heroku).
If you make a GET on http://192.168.1.161:5000/play/98heroku will search in its own network..
Solution 1:
make a link ().
If you then hit that link from your LAN this would work. (you can use redirect_back if you want to redirect to back to the production site).
Solution 2:
make a tunnel from your http://192.168.1.161:5000/play/98 device.
You can do this with ngrok for example.
Then you would be able to make a GET request with HTTP Party from heroku.
HTTParty.get("http://<ngrok-hash>.ngrok.com/play/98")
NOTE: you need to have a running server on http://192.168.1.161:5000/play/98 for both solutions

Rails HTTP Ping to unreliable Target

I would like to send an HTTP GET request to an ip address and port to determine if there is a device online that can respond at that address.
I want to have a relatively reasonable timeout so that my application does not hang while connecting, if there's no. I have been using Net::HTTP, but there does not seem to be a way to set a timeout when using an ip address.
res = Net::HTTP.get_response(ip_address, '/index.html', port)
Is there a best practice or better method to perform this request or a way to set a timeout in Net::HTTP when using an ip address rather than domain name?
I'm using Ruby 2.1.5 and Rails 4.1.0 with hosting on Heroku.
You can see about HTTParty gem. This gem provide many options and easy to use.
You set timeout for the request to return the response
response = HTTParty.get('https://www.google.co.in/', timeout: 60)
timeout is in seconds.
or in Net http you can set as,
uri = URI.parse(ip_address + '/index.html')
request = Net::HTTP::Get.new(uri.path)
begin
response = Net::HTTP.start(uri.host, uri.port) {|http|
http.read_timeout = 100 #Default is 60 seconds
http.request(request)
}
rescue Net::ReadTimeout => e
puts e.message
end
There's no major difference between requesting via an ip address or by dns name, in the latter case DNS query is made and usually a Host-header is set, after that request is done via the ip.
In Net::HTTP there's open_timeout setting that raises Net::OpenTimeout when set if connection cannot be established during that period. By default it's nil which means 'forever'
Not sure what you are looking for. In the Net::HTTP-class there is read_timeout-setter. See here: http://docs.ruby-lang.org/en/2.1.0/Net/HTTP.html#method-i-read_timeout-3D

Send Get to website with lua

i'm having a trouble with lua.
I need send a request to a website by GET and get the response from website.
Atm all i have is this:
local LuaSocket = require("socket")
client = LuaSocket.connect("example.com", 80)
client:send("GET /login.php?login=admin&pass=admin HTTP/1.0\r\n\r\n")
while true do
s, status, partial = client:receive('*a')
print(s or partial)
if status == "closed" then
break
end
end
client:close()
What should i do to get the response from server ?
I want to send some info to this website and get the result of page.
Any ideas ?
This probably won't work as *a will be reading until the connection is closed, but in this case the client doesn't know how much to read. What you need to do is to read line-by-line and parse the headers to find Content-Length and then after you see two line ends you read the specified number of bytes (as set in Content-Length).
Instead of doing it all yourself (reading and parsing headers, handling redirects, 100 continue, and all that), socket.http will take care of all that complexity for you. Try something like this:
local http = require("socket.http")
local body, code, headers, status = http.request("https://www.google.com")
print(code, status, #body)
I solved the problem passing the header
local LuaSocket = require("socket")
client = LuaSocket.connect("example.com", 80)
client:send("GET /login.php?login=admin&pass=admin HTTP/1.0\r\nHost: example.com\r\n\r\n")
while true do
s, status, partial = client:receive('*a')
print(s or partial)
if status == "closed" then
break
end
end
client:close()

Resources