Streaming binary data to server using Net::HTTP in ruby - 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)

Related

Fetch urls prefixed with username:password#

I am using net-http-persistent gem to fetch pages. It works perfectly fine for most of the cases. But, recently I noted that it returns 401 for urls prefixed with username:password# e.g. https://username:password#somesite.com. If i try other options like excon/curl they fetch such pages without problem. I saw the logs of the requests made by Net::HTTP::Persistent and found out net::http totally discards the username:password part while connecting to the server.
Can anybody help me how to make Net::HTTP::Persistent make use of username:password# part.
----------------------EDITED--------------------
Sample code:
url = "https://user:pass#example.com/feed"
uri = URI(url)
http = Net::HTTP::Persistent.new
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.request uri
http.shutdown
response.code # yields 401 which it should not as url has username and password.
#Incase of excon, if you do
response = Excon.get(url)
response.status # yields 200 as it is making use of username:password prefix
Based on this issue, try code like:
uri = URI("https://example.com/feed")
req = Net::HTTP::Get.new(uri.request_uri)
req.basic_auth 'user', 'pass'
http = Net::HTTP::Persistent.new
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
response = http.request uri, req
http.shutdown
puts response.code

InvalidURIError making request to Facebook Graph API with Ruby

I'm simply trying to get a response from the API that includes certain fields that I'm specifying in my uri string but I keep receiving an InvalidURIError. I've come here as a last resort, having spent hours trying to debug this.
I've already tried using the URI.encode() method on it as well, but only get the same error.
Here's my code:
url = params[:url]
uri = URI('https://graph.facebook.com/v2.3/?id=' + url + '&fields=share,og_object{id,url,engagement}&access_token=' + CONFIG['fb_access_token'])
req = Net::HTTP::Post.new(uri.path)
req.set_form_data('fields' => 'og_object[engagement]','access_token' => CONFIG['fb_access_token'])
res = Net::HTTP.new(uri.host, uri.port)
res.verify_mode = OpenSSL::SSL::VERIFY_NONE
res.use_ssl = true
response = nil
res.start do |http|
response = http.request(req)
end
response = http.request(req)
output = ""
output << "#{response.body} <br />"
return output
And the error I'm receiving:
URI::InvalidURIError - bad URI(is not URI?): https://graph.facebook.com/v2.3/?id=http://www.wikipedia.org&fields=share,og_object{id,url,engagement}&access_token=960606020650536|eJC0PoCARFaqKZWZHdwN5ogkhfs
I'm just exhausted at this point so if I left out any important information just let me know and I'll respond with it as soon as I can. Thank you!
The problem is you're just dumping strings into your URI without escaping them first.
Since you're using Sinatra you can use Rack::Utils.build_query to construct your URI's query component with the values correctly escaped:
uri = URI('https://graph.facebook.com/v2.3/')
uri.query = Rack::Utils.build_query(
id: url,
fields: 'share,og_object{id,url,engagement}',
access_token: CONFIG['fb_access_token']
)

Getting data out of JSON

I keep hitting an error.
The path to my data in JSON is
["data"][i]["ip"]
where iis the index.
I tried
json_obj.each do |obj|
list << obj["data"[i]["ip"]
end
in order to store the values inside a list array. I keep getting some conversion error. Is there a better way to do this?
uri = URI.parse("SITE")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Get.new(uri.request_uri)
req.basic_auth('USER', 'PASS')
res = http.request(req)
json_resp = JSON.parse(res.body)
list = []
json_resp.each do | obj |
print obj["data"][0]["fqdn"]
end
it should be json_obj["data"].each
json_obj is a hash (or hash like anyway) so you need to pass the key then you can access the array json_obj["data"] points to and use it's each method.
As #tadman says this error is from Array.each not liking a string index, and happens often to me...

Net::HTTP not sending request

I have the following method in our Ruby 1.8.7 project:
def self.ping_server
request_data = get_request_data
uri = 'another_server.our_company.com'
https = Net::HTTP.new(uri)
https.use_ssl = true
path = "/our_service"
data = request_data.to_json
response = https.post(path, data, {'Content-Type' => 'application/json'})
return response
end
Whenever I run this method, I get the following time out error:
Completed 500 Internal Server Error in 128936ms
Errno::ETIMEDOUT (Connection timed out - connect(2)):
lib/my_class.rb:51:in `ping_our_server'
I checked with a coworker who has access to the logs for another_server.our_company.com. My request isn't arriving at the other server.
What should I do to get my request to work?
EDIT: On further inspection, this is what I think is happening (but I'm not completely sure): Our other server will only accept HTTPS requests, but it looks like my request is being sent over HTTP for some reason. Is there something I need to add to make sure my request is sent over HTTPS?
According to this website, this is how you send an HTTPS request:
require "net/https"
require "uri"
uri = URI.parse("https://secure.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)
response = http.request(request)
response.body
response.status
response["header-here"] # All headers are lowercase
According to this website (which is linked from my first link), you should also do this to close up a vulnerability in the net/https library:
To get going, you need a local CA certificates bundle, the official
curl site maintains an up to date cacert.pem / ca-bundle.crt file
containing all of the major certificates if you need one.
Next, after a gem install always_verify_ssl_certificates, you can be
up and running with a test as simply as:
require 'always_verify_ssl_certificates'
AlwaysVerifySSLCertificates.ca_file = "/path/path/path/cacert.pem"
http= Net::HTTP.new('https://some.ssl.site', 443)
http.use_ssl = true
req = Net::HTTP::Get.new('/')
response = http.request(req)
If the site
has a bad certificate an error will be raised at this point. If not, a
legitimate HTTP response object will be returned.

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

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)

Resources