I have a web server that i need to get some data from. I want to reuse the connection, that's why i chose HTTP.new
require "net/http"
require "openssl"
uri = URI.parse("https://example.com")
path = "/index.html"
http = Net::HTTP.new(uri.host, uri.port,
:use_ssl => uri.scheme == 'https')
request = Net::HTTP::Get.new "/index.html"
response = http.request(request)
When issuing the request (response = http.request(request)) ruby throws a TypeError:
TypeError: no implicit conversion of Hash into String
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `initialize'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `open'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:879:in `block in connect'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/timeout.rb:74:in `timeout'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:878:in `connect'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:852:in `start'
from /usr/local/Cellar/ruby/2.2.2/lib/ruby/2.2.0/net/http.rb:1375:in `request'
from (irb):14
from /usr/local/bin/irb:11:in `<main>'
The same request works when i use http
I'm not sure you aren't overcomplicating the invocation. Why not just use:
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
I'm basing this on the assumption that you already know whether or not your target server requires HTTPS or not.
Related
I've been looking around on how to make HTTPS requests using the Shoes GUI builder and I'm getting the SSL_connnect connect error and I'm unsure of what to do about it.
I made a test app in this Gist
Here's the Error:
SSL_connect returned=1 errno=0 state=error: certificate verify failed
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:923:in `connect'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:923:in `block in connect'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/timeout.rb:73:in `timeout'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:923:in `connect'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:863:in `do_start'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:852:in `start'
/Applications/Shoes.app/Contents/MacOS/lib/ruby/2.2.0/net/http.rb:1375:in `request'
shoes.rb:17:in `request'
shoes.rb:54:in `block (3 levels) in <main>'
-e:1:in `call'
I figured it out. Updating the request to strip the token and setting the verify_mode to OpenSSL::SSL::VERIFY_NONE fixed the problem.
token = Base64.encode64("#{user}:#{pass}").strip
uri = URI("https://example.com/")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri.request_uri)
request["authorization"] = "Bearer #{token}"
request["Content-Type"] = "application/json"
response = http.request(request)
info(response.body)
response
Here's my code:
#!/usr/bin/env ruby
require 'net/http'
uri = URI.parse('https://api.lendingclub.com/api/investor/v1/loans/listing')
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Get.new(uri.request_uri)
request.initialize_http_header({'Authorization' => 'exampleQd0ddDKREKgdpeDOKsdfs3434aA='})
request.initialize_http_header({'Accept' => 'application/json'})
request.initialize_http_header({'Content-Type' => 'application/json'})
response = http.request(request)
Here's where I end up:
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:153:in `read_nonblock': end of file reached (EOFError)
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:153:in `rbuf_fill'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:134:in `readuntil'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:144:in `readline'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http/response.rb:39:in `read_status_line'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http/response.rb:28:in `read_new'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1406:in `block in transport_request'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1403:in `catch'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1403:in `transport_request'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1376:in `request'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1369:in `block in request'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:852:in `start'
from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1367:in `request'
from /Users/jeff/Documents/My Synched Cloud Files/Documents/My Scripts/Python/Development/Lending Club/ruby/LC_get_notes_new.rb:12:in `<main>'
Not sure why all the errors are from Frameworks/Ruby. I am just trying to run this from a file (it's a script), not as any part of a website. Bonus points if you can then tell me how to save the response to a file once I get this part of the code working. By the way, I have all this working fine in Python but I am trying to port this to Ruby (which is new for me). Thanks!
Here an example how to do that with a POST
require 'net/http'
http = Net::HTTP.new('nl3.forgeofempires.com')
path = '/game/json?h=c29e13c18d3'
data = [
%{5a6029226f[{"clientIdentification":{"requiredBackendVersion":"1.17","appType":null,"deviceId":null,"registrationId":null,"platform":"bro","androidDeviceId":null,"platformVersion":"web","clientVersionNumber":"1.17","__class__":"ClientIdentification"}, etc...}]}
]
headers = {
'Cookie' => cookie,
"Content-Length" => l,
'Connection' => 'keep-alive',
"Origin" => "http://cdn.nl.forgeofempires.com",
'Referer' => "http://cdn.nl.forgeofempires.com/swf/Preloader.swf?1389689898",
'Content-Type' => 'application/x-www-form-urlencoded'
}
resp = http.post(path, data, headers)
File.write('response.json', resp.body)
Try with this:
#!/usr/bin/env ruby
require 'net/http'
uri = URI.parse('https://api.lendingclub.com/api/investor/v1/loans/listing')
request = Net::HTTP::Get.new uri.request_uri
res = Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https') {|http| http.request request}
request.initialize_http_header({'Authorization' => 'exampleQd0ddDKREKgdpeDOKsdfs3434aA='})
request.initialize_http_header({'Accept' => 'application/json'})
request.initialize_http_header({'Content-Type' => 'application/json'})
response = res.request(request)
If you want to write the response into a file
File.write('filename', response)
I'm trying to replicate the curl request on this page using Ruby. When I run the curl request from my system it works fine, but Ruby gives me an error. I've tried a few different ways of doing Ruby posts but none of them work. Here's my code:
hr_args = { 'type' => 'todo',
'text' => 'tyy'
}
hr_hd = {"Content-Type"=>"application/json",
'x-api-user'=> habit_user,
'x-api-key' => habit_token
}
url = URI.parse('https://habitrpg.com:443/api/v2/user/tasks')
http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.request_uri, hr_hd)
request.body = hr_args.to_json
response = http.request(request)
This is the error I get:
/usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/protocol.rb:153:in `read_nonblock': end of file reached (EOFError)
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/protocol.rb:153:in `rbuf_fill'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/protocol.rb:134:in `readuntil'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/protocol.rb:144:in `readline'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:39:in `read_status_line'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http/response.rb:28:in `read_new'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1408:in `block in transport_request'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1405:in `catch'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1405:in `transport_request'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1378:in `request'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1371:in `block in request'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:853:in `start'
from /usr/local/rvm/rubies/ruby-2.1.1/lib/ruby/2.1.0/net/http.rb:1369:in `request'
from todo.rb:38:in `<main>'
What am I doing wrong?
The problem was that I needed to set http.use_ssl = true.
try this
...
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
...
...
The following code fails to execute:
require 'net/http'
uri = URI('https://example.com:8443')
http = Net::HTTP.new(uri.host, uri.port)
# Enable SSL/TLS ?
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = File.join(File.dirname(__FILE__), "ca-rsa-cert.pem")
end
http.start {
http.request(uri)
}
The error is:
$ ./TestCert.rb
/usr/lib/ruby/1.9.1/net/http.rb:1292:in `request': undefined method `set_body_internal'
for #<URI::HTTPS:0x00000001a47fd0 URL:https://example.com:8443> (NoMethodError)
from ./TestCert.rb:16:in `block in <main>'
from /usr/lib/ruby/1.9.1/net/http.rb:745:in `start'
from ./TestCert.rb:15:in `<main>'
Unlike Ruby NoMethodError (undefined method `set_body_internal') with HTTP get, I'm using HTTPS and I don't care about a response. I simply need Ruby to make the connection to test the SSL/TLS server.
I did try to capture a response per the related question, but that had the same error:
http.start {
response = http.request uri
}
And this had the same error:
response = http.start {
http.request uri
}
And http.get failed too (but with a different error - undefined method 'empty?'):
response = http.start {
http.get uri
}
And another failure (but with a different error - undefined method 'empty?'):
http.start {
response = http.get uri
}
If it matters, this is a Debian 7.3 (x64) system running Ruby 1.9.3p194.
How do I make a HTTP request over SSL/TLS using Ruby?
I think your call http.request(uri) is wrong, you should pass a kind of request object like Net::HTTP::Get instead of the uri. Try with the following code:
require 'net/http'
uri = URI('https://example.com:8443')
http = Net::HTTP.new(uri.host, uri.port)
# Enable SSL/TLS ?
if uri.scheme == "https"
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.ca_file = File.join(File.dirname(__FILE__), "ca-rsa-cert.pem")
end
req = Net::HTTP::Get.new('/')
http.request(req)
Or call directly request_get('/'). That method will create the Get object for you, like the documentation explain:
def request_get(path, initheader = nil, &block) # :yield: +response+
request(Get.new(path, initheader), &block)
end
i have the following Ruby Code, for a tracking website in sandbox mode:
require "net/http"
require "net/https"
require "uri"
xml = <<XML
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><data appname="dhl_entwicklerportal" language-code="de" password="Dhl_123!" request="get-status-for-public-user"><data piece-code="00340433836536550280"></data></data>
XML
uri = URI('https://cig.dhl.de/services/sandbox/rest/sendungsverfolgung')
nhttp = Net::HTTP.new(uri.host, uri.port)
nhttp.use_ssl=true
nhttp.verify_mode=OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Get.new(uri)
request.basic_auth 'xpackageWP', 'hidden'
response = nhttp.start {|http|
http.request(request, xml:xml)
}
puts response.body
I always get the error :
d:/Ruby200/lib/ruby/2.0.0/net/http/generic_request.rb:179:in `send_request_with_body' undefined method `bytesize' for #<Hash:0x2954fe8> (NoMethodError)
from d:/Ruby200/lib/ruby/2.0.0/net/http/generic_request.rb:130:in `exec'
from d:/Ruby200/lib/ruby/2.0.0/net/http.rb:1404:in `block in transport_request'
from d:/Ruby200/lib/ruby/2.0.0/net/http.rb:1403:in `catch'
from d:/Ruby200/lib/ruby/2.0.0/net/http.rb:1403:in `transport_request'
from d:/Ruby200/lib/ruby/2.0.0/net/http.rb:1376:in `request'
from D:/Dropbox_5BHIF/Dropbox/TempDHL/Main.rb:17:in `block in <main>'
from d:/Ruby200/lib/ruby/2.0.0/net/http.rb:852:in `start'
from D:/Dropbox_5BHIF/Dropbox/TempDHL/Main.rb:16:in `<main>'
I tried really hard to solve this, but i cannot think of any problem.
When i test it in the Browser with the Link and then a ?xml= it works perfectly, so it seems to be a problem with my Ruby Code.
You're sending post data as a hash. You should encode it as string.
For example Using URI::encode_www_form:
request = Net::HTTP::Post.new(uri)
...
response = nhttp.start do |http|
post_data = URI.encode_www_form({xml: xml})
http.request(request, post_data)
end
UPDATE If you want GET request, append the query string to the url.
post_data = URI.encode_www_form({xml: xml})
uri = URI('https://cig.dhl.de/services/sandbox/rest/sendungsverfolgung?' +
post_data)
...
response = nhttp.start do |http|
http.request(request)
end
request expects a string for its second argument, on which it invokes bytesize. You're giving it a hash, which doesn't respond to bytesize.
Use POST and not GET request
xml = <<XML
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?><data
appname="dhl_entwicklerportal" language-code="de" password="Dhl_123!" request="get-status-for-public-user"><data piece-code="00340433836536550280"></data></data>
XML
uri = URI('https://cig.dhl.de/services/sandbox/rest/sendungsverfolgung')
nhttp = Net::HTTP.new(uri.host, uri.port)
nhttp.use_ssl=true
nhttp.verify_mode=OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(uri)
request.body = xml
request.basic_auth 'xpackageWP', 'hidden'
response = nhttp.start {|http|
http.request(request)
}
I solved by using .to_s, it returns a 200.
#client.job.create_or_update(job_name, job_xml.get_xml.to_s)
This is Jenkins API client what I'm currently using:
https://github.com/arangamani/jenkins_api_client