Custom ruby gem loads forever when sending first POST request - ruby-on-rails

I wrote a custom ruby gem that makes simple HTTP requests using the following code:
request = Net::HTTP::Post.new(path, initheader = {'Content-Type' =>'application/json'})
request.body = body
response = Net::HTTP.new(myhost, myport)
response.ssl_version = :TLSv1
response.use_ssl = true
response.verify_mode = ::OpenSSL::SSL::VERIFY_NONE
response.start {|http| #res = http.request(request) }
When I try to call it from my Rails app, it loads/does nothing for about 10 seconds before making the actual POST request. Calling it again after that is almost instant thought, so I assumed the dependencies are loaded in this time.
The gem requires:
require 'net/http'
require 'json'
require 'openssl'
so I simply declared 'json' and 'openssl' as runtime requirements in the gemspec. After running
bundle install
they get installed but the 10 seconds loading time is still there.
I am calling a different method before the one above and that works perfectly fine so the gem is loaded properly.
Does anyone know what might cause this?

Related

How to check for successful response from API in rails by just using status code?

I am consuming an API using a gem in Ruby on Rails. The gem makes the API call for me and returns the status code as an integer (for example 200, 201 e.t.c.) and the data response from the API.
def get_cars
status_code, data = MyGem::Cars.get_cars
if status_code in SUCCESSFUL_RESPONSE_CODES
# Perform data manipulation
else
raise "There was an error processing the request. Status code #{status_code}"
end
end
Now I have manually initialised SUCCESSFUL_RESPONSE_CODES as a list containing integers of successful codes I found here.
Is this list defined somewhere in Ruby/RoR to avoid manually defining it?
I would expect any widely supported gem to use standard HTTP response codes to determine if the HTTP response was a success. For example:
require 'open-uri' # Rails loads this by default.
res = open('http://example.com')
res.status
=> ["200","OK"]
status.include?'OK'
=>true
status.include?'200'
=> true
So long as you trust the gem code making your request to handle standard HTTP response codes, you should be ok. Here's another example using HTTParty gem
require 'HTTParty'
res = HTTParty.get('https://example.com')
res.success?
=> true

Ruby Net::HTTP using SSL

I have a very simple API, that I would like to make a POST to using ruby and NOT using a GEM just the built in libraries net/http, uri, and openssl if needed.
Anyway, I am using the code below to make a very simple POST request but am getting some VERY strange results and was hoping someone else has seen this.
I have also tested the same request below in POSTMAN and NodeJS and BOTH work as expected, the only one I can not get to work is Ruby.
require 'uri'
require 'net/http'
require 'openssl'
url = URI("https://somesite.dev/devices")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
request = Net::HTTP::Post.new(url)
request["key"] = '1234567'
response = http.request(request)
puts response.read_body
The result is something I have not seen before: I am getting the header key twice... So the log to the API shows a query like this:
SELECT * FROM device where key = '1234567, 1234567' LIMIT ...
As stated above I can make the same request via POSTMAN or NodeJS and get the correct result.
NOTE: Because I have a local copy of the API I can test locally BUT it's not SSL it's all over http. When making the request locally it works just fine. So from what I can tell this issue only presents it self when SSL is introduced.
Any help would be amazing! Thanks!!
Ruby Version 2.2.1
The issue was with something I did not list in my initial question. The API was using AWS API Gateway, and HTTP_PROXY was enabled on the method causing this strange issue. After I removed HTTP_PROXY the issue cleared up and the above code worked!

undefined method `use_ssl' for #<Net::HTTP 127.0.0.1:8080 open=false>

I'm using the ruby-fedora gem to fetch information from my database
Fedora::Repository.instance.fetch_content
I'm positive my code works, because there were no problems before I updated to Ruby 2.1.1. When I execute the code to fetch data, the code from the gem itself (bundle/ruby/2.1.0/gems/ruby-fedora-1.0.5/lib/fedora/connection.rb) produces following error:
undefined method `use_ssl' for #<Net::HTTP 127.0.0.1:8080 open=false>
bundle/ruby/2.1.0/gems/ruby-fedora-1.0.5/lib/fedora/connection.rb:191:in `http'
bundle/ruby/2.1.0/gems/ruby-fedora-1.0.5/lib/fedora/connection.rb:152:in `request'
Anyone encountered something like this before? Could it be due to gem incompatibility?
EDIT: I edited the gem code and the line where the problem occurs is:
# Creates new Net::HTTP instance for communication with
# remote service and resources.
def http
http = Net::HTTP.new(#site.host, #site.port)
http.use_ssl = #site.is_a?(URI::HTTPS)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl <--- THIS LINE
http
end
When I replace the function with the following one, everything works fine (as I don't use HTTPS)
# Creates new Net::HTTP instance for communication with
# remote service and resources.
def http
http = Net::HTTP.new(#site.host, #site.port)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if #site.is_a?(URI::HTTPS)
http
end
It looks like the problem is that ruby-fedora is no longer actively maintained, it seems that the last release was in 2009. Now I'm sure your fix will work but if you require extra help going forward you'll need to hack everything yourself. They don't even appear to have a github page anymore!!
ActiveFedora seems to be an actively maintained project that should suit your needs. Here it is on ruby-gems, the last release was 7 days ago (which IMO beats 5 years ago!!).

koala response times. 20 seconds waiting response

I'm new with Rubyonrails and Koala gem and I'm sure I'm doing something wrong. I've been tuning my code to the minimun expression but the problem persist. Then I tried to do the same without koala gem, but the problem persisted.
This is the code:
require 'koala'
require 'open-uri'
puts Time.now
#graph = Koala::Facebook::API.new
resp = #graph.graph_call("cocacola", {}, "get", {})
puts resp
puts Time.now
coke_url = "https://graph.facebook.com/cocacola"
response = open coke_url
response = JSON.parse response.read
puts response.inspect
puts Time.now
I have to wait always 21 seconds the Facebook's response. If I put the https://graph.facebook.com/cocacola on my browser, the response is instantaneous ¿is not the same?
thanks
I'm using Koala in my application and did not have such experience. The only difference is that I don't use it anonymously. Instead I created an app and I'm using an access token to access the Facebook API. This might be the root cause, as I've found this post that also seems relates.
Finally, it was a DNS problem (thanks jpgeek).
When I did just a GET request to any website, the response was after 21 seconds, but using the IP of the same website, the response was instantaneously.
I found on google the solution: http://www.mikeperham.com/2010/02/10/asynchronous-dns-resolution/
I have use this personal solution in Gemfile (I'm not sure if it's the best):
group :development do
require 'resolv'
require 'resolv-replace'
end
Now it's working fine!

Writing Mock RSpec

I have code in my Ruby on rails project as follows, to get HTTP response from non rails API
app/model/rest_api.rb
require "uri"
require "net/https"
require "net/http"
require "active_support"
class RestApi
# the URL for the Twitter Trends endpoint
#url = 'http://api.twitter.com/1/trends.json'
def self.sampleRes
uri = URI.parse( #url)
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
return response
end
end
I have just started learning Ruby on Rails and RSPEC. Can someone please help that how can I write RSpec for HTTP request without actually making request to actual API URL(need some mock)
You can mock out the request part and make expectations about what should be called etc.
mock_req = double("http request")
mock_req.should_receive(:request)
Net::HTTP::Get.should_receive(:new).and_return(mock_req)
Your code could also be simplified to:
open('http://api.twitter.com/1/trends.json').read
You aren't doing any error handling, status checking etc. (maybe this is example code?) but, whatever you expect your request to return you should mock/stub out those expectations.

Resources