HTTPS request using Net::HTTP's block form -- is it possible? - ruby

To do a Net::HTTP https request without the block form you can do this:
...
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
...
But is there a way to tell Net::HTTP to use https when doing the block form?
u = URI.parse(url)
Net::HTTP.start(u.host, u.port) do |http|
# if I put http.use_ssl = true here, ruby complains that this can't
# be done becuase the sesion has already started
resp = http.get(u.request_uri)
end
I'm on ruby 1.8.7

See the documentation for Net::HTTP.start which takes an optional hash. From the documentation:
opt sets following values by its accessor. The keys are ca_file, ca_path, cert, cert_store, ciphers, close_on_empty_response, key, open_timeout, read_timeout, ssl_timeout, ssl_version, use_ssl, verify_callback, verify_depth and verify_mode. If you set :use_ssl as true, you can use https and default value of verify_mode is set as OpenSSL::SSL::VERIFY_PEER.
Net::HTTP.start(url.host, url.port, :use_ssl => true)

Related

unsupported proxy in HTTPClient

I want to use Ruby httpclient to make requests. I tried to implement this code:
def submit!
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = HTTPClient.new(url)
request.basic_auth('username', 'pass')
request['content-type'] = 'application/xml'
request['cache-control'] = 'no-cache'
request.body = request_body
response = http.request(request).body
response = Response.new(response)
check_for_approved_response(response)
response
end
But I get error:
unsupported proxy https://staging.gate.some_address.net/process/3ab20f2ddbe78ab8be9f5a9645c1010330dc868f
Can you recommend some solution how to fix it?
make sure ruby can see and read /etc/resolv.conf and that you don't have HTTP_PROXY env variable set. Also check that your ssl isn't using a non-standard ssl port.
Run echo $HTTP_PROXY on your terminal. If you see any value, its not good. You'll have to unset that variable.
See - https://github.com/savonrb/savon/issues/123#issuecomment-620825
https://www.rubydoc.info/gems/httpclient/2.1.5.2/HTTPClient
Accessing resources through HTTP proxy. You can use environment variable 'http_proxy' or 'HTTP_PROXY' instead.
clnt = HTTPClient.new('http://myproxy:8080')
So in your code request = HTTPClient.new(url) is putting target url as proxy of HTTPClient. (It is indeed a little confusing when you come from net/http)

Net::HTTP failing on a head request

I'm trying to make an HTTP Head request using Net::HTTP.
require 'net/http'
uri = URI("https://github.com/rails/rails")
http = Net::HTTP.new(uri.host, uri.port)
request = http.head(uri)
puts request
fails.
AFAICT, this is because Net::HTTP is waiting on a response body which will never come. How do I ask Net::HTTP to make a request and not wait on the response body?
If you follow the documentation properly, it works just fine. The library implementation probably has some assumptions on the usage when it determines whether to read the payload.
response = nil
Net::HTTP.start('github.com', :use_ssl => true) do |http|
response = http.head('/rails/rails')
end
response.each { |k, v| [k, v] }

Streaming binary data to server using Net::HTTP in ruby

Using Ruby, I just try to parse the bitstream file to the server, I have a problem with badrequst HTTP. Could anybody help me with sending the data to the server by using Net::HTTP.
def addbitstream(url, path, file_bitstream)
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, 443)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(path)
f = File.new(file_bitstream)
file = File.open(f)
n = 6
offset = 0
request.body = ""
while (offset < File.size(file))
buffer = readfileAsbitstream(file, offset, n)
request.body = buffer
response = Net::HTTP.start(uri.host, 443) {|http| http.request(request) }
offset += n
end
end
Although I have not done file streaming, the first problem you will have with this code is that HTTP.start closes the connection after executing a block, when it is passed one. Maybe changing the order of your nesting here will help.
I would recommend using a gem to wrap HTTP requests anyway such as REST-client, which I think streams file uploads by default.
Here is how to use Net::HTTP:
url ="www.yoururl.com"
uri = URI.parse(url)
http = Net::HTTP.new(uri.host, uri.port)
request = Net::HTTP::Post.new(uri.request_uri)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.request(request)

How to do basic authentication over HTTPs in Ruby?

After looking a lot, I've found some solutions that seem working, but not for me...
For example, I have this script:
require 'net/http'
require "net/https"
#http=Net::HTTP.new('www.xxxxxxx.net', 443)
#http.use_ssl = true
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#http.start() {|http|
req = Net::HTTP::Get.new('/gb/PastSetupsXLS.asp?SR=31,6')
req.basic_auth 'my_user', 'my_password'
response = http.request(req)
print response.body
}
When I run it, it gives me a page that requests for authentication, but if I write the following URL in the browser, I get into the website without problems:
https://my_user:my_password#www.xxxxxxx.net/gb/PastSetupsXLS.asp?SR=31,6
I have also tried with open-uri:
module OpenSSL
module SSL
remove_const :VERIFY_PEER
end
end
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
def download(full_url, to_here)
writeOut = open(to_here, "wb")
writeOut.write(open(full_url, :http_basic_authentication=>["my_user", "my_password"]).read)
writeOut.close
end
download('https://www.xxxxxxx.net/gb/PastSetupsXLS.asp?SR=31,6', "target_file.html")
But the result is the same, the site is asking for user authentication.
Any tips of what am I doing wrong?. Must I encode the password in Base 64?
I wrote a piece of code based on examples given in the Net::HTTP docs and tested it on my local WAMP server - it works fine. Here's what I have:
require 'net/http'
require 'openssl'
uri = URI('https://localhost/')
Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https',
:verify_mode => OpenSSL::SSL::VERIFY_NONE) do |http|
request = Net::HTTP::Get.new uri.request_uri
request.basic_auth 'matt', 'secret'
response = http.request request # Net::HTTPResponse object
puts response
puts response.body
end
And my .htaccess file looks like this:
AuthName "Authorization required"
AuthUserFile c:/wamp/www/ssl/.htpasswd
AuthType basic
Require valid-user
My .htpasswd is just a one liner generated with htpasswd -c .htpasswd matt for password "secret". When I run my code I get "200 OK" and contents of index.html. If I remove the request.basic_auth line, I get 401 error.
UPDATE:
As indicated by #stereoscott in the comments, the :verify_mode value I used in the example (OpenSSL::SSL::VERIFY_NONE) is not safe for production.
All available options listed in the OpenSSL::SSL::SSLContext docs are: VERIFY_NONE, VERIFY_PEER, VERIFY_CLIENT_ONCE, VERIFY_FAIL_IF_NO_PEER_CERT, out of which (according to the OpenSSL docs) only the first two ones are used in the client mode.
So VERIFY_PEER should be used on production, which is the default btw, so you can skip it entirely.
The following is what ended up working for me:
require "uri"
require "net/http"
url = URI("https://localhost/")
https = Net::HTTP.new(url.host, url.port)
https.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = "Basic " + Base64::encode64("my_user:my_password")
response = https.request(request)
puts response.read_body
I came up with this by building a new HTTP Request in Postman, specifying the URL, choosing an Authorization Type of "Basic Auth," and inputting the credentials.
Clicking the Code icon (</>) and selecting "Ruby - Net::HTTP" will then generate a code snippet, giving you the output above.
Postman took care of encoding the credentials, but this answer helped me to dynamically set these values. You also can likely omit the "cookie" key as part of the request.

Using Net::HTTP.get for an https url

I'm trying to use Net::HTTP.get() for an https URL:
#data = Net::HTTP.get(uri, Net::HTTP.https_default_port())
However, I get the following result when I try to print the results:
can't convert URI::HTTPS into String
What's the deal? I'm using Ruby 1.8.7 (OS X)
Original answer:
uri = URI.parse("https://example.com/some/path")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
#data = http.get(uri.request_uri)
As pointed out in the comments, this is more elegant:
require "open-uri"
#data = URI.parse("https://example.com/some/path").read
EDIT: My approach works, but #jason-yeo's approach is far easier.
It appears as of 2.1.2 the preferred a documented method is as follows (directly quoting the documentation):
HTTPS is enabled for an HTTP connection by #use_ssl=.
uri = URI('https://secure.example.com/some_path?query=string')
Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new uri
response = http.request request # Net::HTTPResponse object
end
In previous versions of Ruby you would need to require ‘net/https’ to use
HTTPS. This is no longer true.
In Ruby 2.0.0 and above, simply passing in an uri object with a https url is sufficient to do a HTTPS get request.
uri = URI('https://encrypted.google.com')
Net::HTTP.get(uri)
You may verify this by performing a get request on a domain with an expired certificate.
uri = URI('https://expired.badssl.com/')
Net::HTTP.get(uri)
# OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=error: certificate verify failed
It was introduced by this commit in Ruby 2.0.0.
The get_response method, which is called by the Net::HTTP.get method, sets :use_ssl to true when the uri.scheme is "https".
Disclaimer: I understand that the question is for Ruby 1.8.7, but since this is one of the top few search results when one searches for "https ruby", I've decided to answer anyway.
this should look as:
uri.port = Net::HTTP.https_default_port()
#data = Net::HTTP.get(uri)

Resources