What causes OpenSSL::SSL::SSLErrorWaitReadable "read would block"? - ruby

What does the OpenSSL::SSL::SSLErrorWaitReadable "read would block" mean?
I am getting the error OpenSSL::SSL::SSLErrorWaitReadable with the message read would block. I think this is because of timeouts, but I can't find any documentation on the subject.
Can anyone help me figure out what is causing this? Also what I can do to prevent the issue?
The code that is producing this error every now and then:
data = {hello: "world"}
path = "https://example.com/api"
uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == "https")
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Post.new(uri.request_uri)
request.body = Oj.dump(data)
request["Content-Type"] = "application/json"
begin
response = http.request(request) #this line produces the error.
rescue
return nil
end
I am using ruby version 2.1.5p273 and openssl version 1.0.1i on osx 10.10.3.
Versions are found using the command ruby -v -ropenssl -rfiddle -e 'puts Fiddle::Function.new(Fiddle.dlopen(nil)["SSLeay_version"], [Fiddle::TYPE_INT], Fiddle::TYPE_VOIDP).call(0)'
Thanks to #bayendor

Couldn't reproduce in my local machine. It works. Here is my version, so could you confirm with your system? Or if your machine is Mac and you installed ruby with system openssl and readline, it may cause because it's old. Try to install new openssl and readline and build ruby, then execute the script again.
% brew install openssl readline
% RUBY_CONFIGURE_OPTS="--enable-shared --with-readline-dir=$(brew --prefix readline) --with-openssl-dir=$(brew --prefix openssl)" rbenv install 2.0.0-p598
OS: MaxOSX 10.10.2
ruby: 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin12.0]
oj (2.12.9)
% ruby test.rb
OK
% cat test.rb
require 'uri'
require 'net/http'
require 'openssl'
require 'oj'
data = {hello: "world"}
path = "https://example.com/api"
uri = URI.parse(path)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = (uri.scheme == "https")
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
request = Net::HTTP::Post.new(uri.request_uri)
request.body = Oj.dump(data)
request["Content-Type"] = "application/json"
begin
response = http.request(request) #this line produces the error.
puts('OK')
rescue
return nil
end

Related

Is there any way to directly run our ruby codes from puppet console?

I am new to both Ruby Language and Puppet. I want to run a ruby code which is a converted form of a cURL, from my puppet console.
I am putting the cURL and the converted ruby below.
curl -k -u stg_admin:password -sS -X POST https://www.something.com
As you can see, this is a very basic cURL, and the converted ruby code is-
require 'net/http'
require 'uri'
require 'openssl'
uri = URI.parse("https://www.something.com")
request = Net::HTTP::Post.new(uri)
request.basic_auth("stg_admin", "password")
req_options = {
use_ssl: uri.scheme == "https",
verify_mode: OpenSSL::SSL::VERIFY_NONE,
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
# response.code
# response.body
I know how to exec cURL directly in my puppet class, but my question is "is there any way to call my ruby code directly in puppet's init.pp?"
I'll be greatfull for any suggestion.

Checking Facebook Status Using Ruby

I wanted to check facebook status of another page from ruby script. First of all is it possible. I have been doing the following:
I got developer account
I got app key and secret
I installed json_pure gem
Here is my code:
require 'rubygems'
require 'json/pure'
require 'net/http'
url ="https://graph.facebook.com/user_id/feed?access_token=app_id|app_secret"
uri = URI.parse(URI.encode(url.strip))
#to remove specia codes encode
#to remoce whitespace strip
req = Net::HTTP::Get.new(uri.to_s)
res = Net::HTTP.start(uri.host, uri.port) {|http|
http.request(req)
}
html = res.body
res = JSON.parse(html)
Here is the error:
C:/Ruby187/lib/ruby/1.8/net/protocol.rb:135:in `sysread': An existing connection
was forcibly closed by the remote host. (Errno::ECONNRESET)
I would recommend using the koala gem instead of Net::Http
#graph = Koala::Facebook::API.new(oauth_access_token)
status = #graph.get_connections("me", user_id, "status")

Executing requests in ruby using net/http

I am trying to use net/http to get a response for API call based on an old library I dug up https://github.com/jurisgalang/facebook/blob/master/lib/facebook/graph-object.rb#L22
require 'net/http'
API_HOST = "graph.facebook.com"
API_BASE_URL = "https://#{API_HOST}"
path = "/boo"
uri = URI.parse "#{API_BASE_URL}#{path}"
http = Net::HTTP.new(uri.host, uri.port)
res = http.get(uri.request_uri, nil)
The uri ends up as <URI::HTTPS:0x0000010091fc48 URL:https://graph.facebook.com/boo>
This results in
NoMethodError: undefined method `keys' for nil:NilClass
I assumed it is because dest argument is obsolete: http://ruby-doc.org/stdlib-1.9.3/libdoc/net/http/rdoc/Net/HTTP.html#method-i-get
So I did it without
res = http.get(uri.request_uri)
Which results in
NoMethodError: undefined method `empty?' for
#<URI::HTTPS:0x0000010091fc48 URL:https://graph.facebook.com/boo>
How can one request a response using net/http and http.get?
Just at a very quick glance of the documentation, the second argument to get is a hash, and you're passing nil, see:
http.get(uri.request_uri, nil)
Your second attempt should be OK, though I did find that with my setup (ruby 1.9.3 and MacPorts' openssl library) that Net::HTTP was rejecting Facebook's ssl certificate (I was getting "Connection reset by peer". The following code snippet worked for me:
require 'net/http'
API_HOST = "graph.facebook.com"
API_BASE_URL = "https://#{API_HOST}"
path = "/boo"
uri = URI.parse "#{API_BASE_URL}#{path}"
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
res = http.get(uri.request_uri)
puts res.body
Note that I'm not verifying the SSL certificate, which is a potential security problem. As a proof of concept, however, this snippet worked for me - so hopefully this will give you a good data point in your debugging effort.

Ruby HTTP POST - Errors

Can someone explain to me why I am getting this error when doing this POST? I pulled the snippet from the Ruby-docs page.
undefined method `hostname' for #URI::HTTP:0x10bd441d8 URL:http://ws.mittthetwitapp.com/ws.phpmywebservice (NoMethodError)
Perhaps I am missing a require or something?
require 'net/http'
uri= URI('http://ws.mywebservice.com/ws.php')
req = Net::HTTP::Post.new(uri.path)
req.set_form_data('xmlPayload' => '<TestRequest><Message>Hi Test</Message></TestRequest>')
res = Net::HTTP.start(uri.hostname, uri.port) do |http|
http.request(req)
end
case res
when Net::HTTPSuccess, Net::HTTPRedirection
# OK
else
res.value
end
If you're using a version of Ruby prior to 1.9.3, you should use uri.host.
URI#hostname was added in Ruby 1.9.3. It is different than URI#host in that it removes brackets from IPv6 hostnames. For non-IPv6 hostnames it should behave identically.
The implementation (from APIdock):
def hostname
v = self.host
/\A\[(.*)\]\z/ =~ v ? $1 : v
end

How to validate SSL certificate chain in ruby with net/http

How can I verify the certificates of a site like https://processing.ukash.com/ in ruby with net/http?
https = Net::HTTP.new('processing.ukash.com', 443)
https.use_ssl = true
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
Works so far, but how do I verify that it's the right cert now? I saved the certificate from within firefox, but the resulting .pem file has many certificates in it and net/http doesn't seem to like it.
From my code snippets collection:
#!/usr/bin/env ruby
# How to:
# =======
# Use Ruby's net/https library, to verify a SSL certificate.
# ==========================================================
# - Without verification the following code will lead to:
# warning: peer certificate won't be verified in this SSL session
#
# #------------------begin example-----------------------------
# require 'net/http'
# require 'net/https'
# require 'uri'
#
# url = URI.parse 'https://myname:mypass#mail.google.com/'
# http = Net::HTTP.new(url.host, url.port)
# http.use_ssl = (url.scheme == 'https')
# request = Net::HTTP::Get.new(url.path)
# request.basic_auth url.user, url.password
# response = http.request(request)
# #-------------------end example------------------------------
#
# To verify the ssl cert cosider adapting the following.
# Status: Untested
# =======
#
# References:
# ===========
# [1] http://mimori.org/%7Eh/tdiary/20080301.html#p03
# [2] http://redcorundum.blogspot.com/2008/03/ssl-certificates-and-nethttps.html
#
require 'net/http'
require 'net/https'
require 'uri'
RootCA = '/etc/ssl/certs'
url = URI.parse 'https://myname:mypass#mail.google.com/'
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = (url.scheme == 'https')
if (File.directory?(RootCA) && http.use_ssl?)
http.ca_path = RootCA
http.verify_mode = OpenSSL::SSL::VERIFY_PEER
http.verify_depth = 5
else
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
end
request = Net::HTTP::Get.new(url.path)
request.basic_auth url.user, url.password
response = http.request(request)
Hope this helps?
For the sake of completeness and for my future me, this is a small gem I made out of this: https://github.com/jarthod/ssl-test

Resources