Ruby making a web request - ruby

Hi this is my very first Ruby program.
I'm trying to write a simple ruby app to make a request to a URL and see if it's available. If it is, it'll print OK and else it'll print false.
This is what I've got so far, can you please assist, do I need to import any libs?
class WebRequest
def initialize(name)
#name = name.capitalize
end
def makeRequest
puts "Hello #{#name}!"
#uri = URI.parse("https://example.com/some/path")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE # read into this
#data = http.get(uri.request_uri)
end
end
req = WebRequest.new("Archie")
req.makeRequest

Here is sample code to do any request:
require 'net/http'
require 'uri'
url = URI.parse('http://www.example.com/index.html')
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) do |http|
http.request(req)
end
puts res.body

gem install httparty
then
require 'httparty'
response = HTTParty.get('https://example.com/some/pathm')
puts response.body

Something simpler:
[1] pry(main)> require 'open-uri'
=> true
[2] pry(main)> payload = open('http://www.google.com')
=> #<File:/var/folders/2p/24pztc5s63d69hhx81002bq80000gn/T/open-uri20131217-84948-ttwnho>
[3] pry(main)> payload.inspect
=> "#<Tempfile:/var/folders/2p/24pztc5s63d69hhx81002bq80000gn/T/open-uri20131217-84948-ttwnho>"
[4] pry(main)> payload.read
payload.read would return the response body and you can easy use payload as File object since it is an instance of Tempfile

This is what I've ended up with
require 'net/http'
class WebRequest
def initialize()
#url_addr = 'http://www.google.com/'
end
def makeRequest
puts ""
begin
url = URI.parse(#url_addr)
req = Net::HTTP::Get.new(url.path)
res = Net::HTTP.start(url.host, url.port) {|http|
http.request(req)
}
puts "OK Connected to #{#url_addr} with status code #{res.code}"
rescue
puts "Failed to connect to #{#url_addr}"
end
end
end
req = WebRequest.new()
req.makeRequest

Related

undefined local variable or method `http' for main:Object (NameError)

File: nethttp.rb
require 'uri'
require 'net/http'
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
uri = URI('http://localhost/events',:headers => headers)
res = Net::HTTP.get_response(uri)
puts res.body if res.is_a?(Net::HTTPSuccess)
I'm receiving the error:
undefined local variable or method `http' for main:Object (NameError)
You're using the local variable http which is not declared anywhere in the code. If you want to create an instance of Net::HTTP you need to use the "new" method:
require 'uri'
require 'net/http'
# URI only takes one argument!
uri = URI('http://localhost/events')
http = Net::HTTP.new(uri)
# not sure what this is supposed to do since you're requesting a
# HTTP uri and not HTTPS
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
# ...
But you might want to consider using Net::HTTP.start which opens a connection and yields it to the block:
require 'uri'
require 'net/http'
uri = URI('http://localhost/events')
# Opens a persisent connection to the host
Net::HTTP.start(uri.host, uri.port, verify_mode: OpenSSL::SSL::VERIFY_NONE) do |http|
headers = { "X-FOO" => "Bar" }
request = http.get(uri)
headers.each do |key, value|
request[key] = value
end
response = http.request(request)
# consider using a case statement
if response.is_a?(Net::HTTPSuccess)
puts response.body
else
# handle errors
end
end

How To change a URI object's path attribute?

I want to call an API using only slightly different URIs. This code snippet does what I want, but I want to know if there is a more efficient way to do it.
require 'net/http'
require 'json'
# These URIs differ only in the path
orders = URI('https://hft-api.lykke.com/api/Orders?orderType=Unknown')
asset_pairs = URI('https://hft-api.lykke.com/api/AssetPairs')
lykke_req = Net::HTTP::Get.new(orders)
lykke_req['User-Agent'] = 'curl/7.67.0'
lykke_req['api-key'] = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
lykke_req['Accept'] = 'application/json'
response = Net::HTTP.start(orders.hostname,
orders.port,
:use_ssl => true) {|http| http.request(lykke_req)}
puts JSON.parse(response.body)
lykke_req = Net::HTTP::Get.new(asset_pairs)
lykke_req['User-Agent'] = 'curl/7.67.0'
lykke_req['Accept'] = 'application/json'
response = Net::HTTP.start(asset_pairs.hostname,
asset_pairs.port,
:use_ssl => true) {|http| http.request(lykke_req)}
puts JSON.parse(response.body)
All I do is to reuse the same code but with a slightly different URI.
For my lykke_req objects, I can write
puts lykke_req
puts lykke_req.path
which gives me
#<Net::HTTP::Get:0x00007f947f1fdce8>
/api/Orders?orderType=Unknown
So it seems to me all i have to do is change the value of lykke_req.path. But I can't work out how to do it. I am looking for something like this
lykke_req.path = "/api/AssetPairs"
which fails with
undefined method `path=' for #<Net::HTTP::Get GET> (NoMethodError)
I found this on the official documentation page, but I can't find out what [R] means. Does it mean read only? Do I really have to go through the hassle of creating a new URI object, then creating a new Net::HTTP::Get object each time?
path [R]
The problem here is that you're trying to alter the net request object instead of the uri object:
irb(main):001:0> uri = URI('https://hft-api.lykke.com/api/Orders?orderType=Unknown')
=> #<URI::HTTPS https://hft-api.lykke.com/api/Orders?orderType=Unknown>
irb(main):002:0> uri.path = '/foo'
=> "/foo"
irb(main):003:0> uri.to_s
=> "https://hft-api.lykke.com/foo?orderType=Unknown"
But I would really just wrap this in a class so that you can encapsulate and structure your code and avoid duplication:
class LykkeAPIClient
BASE_URI = URI('https://hft-api.lykke.com/api')
def initalize(api_key:)
#api_key = api_key
end
def get_orders
get '/Orders?orderType=Unknown'
end
def get_asset_pairs
get '/AssetPairs'
end
def get(path)
req = Net::HTTP::Get.new(BASE_URI.join(path))
req['User-Agent'] = 'curl/7.67.0'
req['Accept'] = 'application/json'
req['api-key'] = #api_key
response = Net::HTTP.start(req.hostname, req.port, use_ssl: true) do |http|
http.request(uri)
end
# #todo check response status!
JSON.parse(response.body)
end
end
#client = LykkeAPIClient.new(api_key: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
#orders = #client.get_orders
Insstead of lykke_req.path= do lykke_req.uri.path=
https://ruby-doc.org/stdlib-2.6.5/libdoc/net/http/rdoc/Net/HTTPGenericRequest.html

Why am I getting undefined method error ruby?

require "rubygems"
require "json"
require "net/http"
require "uri"
uri = URI.parse("https://api.website.com/top/inside/end")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
http.use_ssl = true
response = http.request(request)
if response.code == "200"
result = JSON.parse(response.body)
names = Array.new
i = 0
result.each do |doc|
names.insert(i, doc.name)
puts doc["id"] #reference properties like this
puts doc # this is the result in object form
puts ""
puts ""
end
puts names
else
puts "ERROR!!!"
end
Why am I getting undefined method error on variable names inside the for each loop? I cannot understand why
script.rb:18:in `block in ': undefined method `name' for #<Hash:0x0000000002e04c08> (NoMethodError)
line 18,
names.insert(i, doc.name)
doc is a Hash, doc['name'] should works.
in javascript, you can do
doc.name

Convert HTTP response to JSON in Ruby

I'm doing a GET request and getting this response:
"oauth_token=USYS96A708CACBDA9C74322DAB41A53CA_idses-int02.a.fsglobal.net&oauth_token_secret=09c8b05b874fac29b4e542c388cb3f&oauth_callback_confirmed=true"
How can I convert this to JSON in Ruby?
Step 1: Parse the GET response:
require 'cgi'
CGI::parse(MYSTRING)
Returns: {"param1"=>["value1"], "param2"=>["value2"], "param3"=>["value3"]}
Step 2. Convert to JSON:
require 'json'
myObject.to_json
Alternatively, look at this snippet:
https://gist.github.com/timsavery/1657351
require "rubygems"
require "json"
require "net/http"
require "uri"
uri = URI.parse("http://api.sejmometr.pl/posiedzenia/BZfWZ/projekty")
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
if response.code == "200"
result = JSON.parse(response.body)
result.each do |doc|
puts doc["id"] #reference properties like this
puts doc # this is the result in object form
puts ""
puts ""
end
else
puts "ERROR!!!"
end

Net::HTTP follow maximum of three redirects?

I have this method in my class:
def self.get(url)
#TODO We could test with https too
if url.match(/^http/)
correct_url = url
else
correct_url = "http://#{url}"
end
uri = URI.parse(correct_url)
if uri.respond_to? 'request_uri'
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
http.request(request)
else
puts "Incorrect URI"
end
end
Unfortunately it's not following the redirects.
Can someone tell me how to make this method allow a maximum of three redirects?
Try this:
def self.get(url)
# TODO: test with https too
url = "http://#{url}" unless url.match(/^http/)
3.times do
uri = URI.parse(url)
if uri.respond_to?(:request_uri)
response = Net::HTTP.get_response(uri)
case response.code
when '301', '302'
url = response.header['location']
else
return response
end
end
end
end

Resources