lib/itrigga/net_helper.rb in itrigga-net_helper-0.2.0 vs lib/itrigga/net_helper.rb in itrigga-net_helper-0.3.0
- old
+ new
@@ -1,5 +1,9 @@
+require 'rest-client'
+require 'itrigga/core_ext'
+Dir[File.join(File.expand_path(File.dirname(__FILE__)),"net_helper","*.rb")].each{|f| require f}
+
require 'uri'
require 'hpricot'
require 'json'
require 'cgi'
require 'timeout'
@@ -8,174 +12,77 @@
module Itrigga
module NetHelper
module_function
- def typhoeus_present?
- if defined?(Typhoeus)
- true
- else
- false
- end
+ # gets a list of engines available (each is a different class in this module that implements 'get' method)
+ def available_http_engines
+ Itrigga::NetHelper.constants
end
-
- def do_get(url, time_out=5, retries_on_timeout=5, max_redirects = 3)
- retrycount = 0
- resp = nil
- begin
- resp = get_with_timeout( url, time_out )
-
- handle_response( url, resp, retries_on_timeout, max_redirects )
- rescue Timeout::Error
- if(retrycount.to_i < retries_on_timeout.to_i)
- retrycount+=1
- retry
- else
- raise IOError.new( "HTTP request timed out #{retrycount} times" )
- end
- end
-
+ def default_http_engine
+ "RestClient"
end
- def typhoeus_request( opts={} )
- opts[:timeout] ||= 30
- opts[:timeout] *= 1000 # Typhoeus does its timeouts in ms
- opts[:follow_location] ||= true
- opts[:disable_ssl_peer_verification] = true if opts[:disable_ssl_peer_verification].nil?
-
- request = Typhoeus::Request.new(opts[:url], opts)
-
- request.on_complete do |response|
- if response.success?
- return response.body
- elsif response.timed_out?
- # aw hell no
- raise IOError.new("Timed out request to #{opts[:url]} after #{opts[:timeout]}ms")
- elsif response.code == 0
- # Could not get an http response, something's wrong.
- raise IOError.new(response.curl_error_message)
- else
- # Received a non-successful http response.
- raise IOError.new("HTTP request failed: " + response.code.to_s)
- end
- end
-
- hydra = Typhoeus::Hydra.new
- hydra.queue(request)
- hydra.run
- end
- def get_response( url, timeout=nil )
- if typhoeus_present?
- typhoeus_request( :url=>url, :timeout=>timeout )
- else
- Net::HTTP.get_response(URI.parse(url))
- end
+ # wrapper method for backwards compat.
+ def do_get(url, timeout=5, retries_on_timeout=5, max_redirects = 3)
+ get :url => url, :timeout => timeout, :retries_on_timeout => retries_on_timeout, :max_redirects => max_redirects
end
-
- def get_with_timeout( url, time_out)
- resp = nil
- if defined?(SystemTimer)
- resp = SystemTimer.timeout_after(time_out) do
- get_response(url, time_out)
- end
- else
- resp = timeout(time_out) do
- get_response(url, time_out)
- end
- end
- resp
- end
+
+
+ def get(options = {})
+ opts = { :timeout => 5, :retries_on_timeout => 5, :max_redirects => 3, :headers => {} }.merge(options)
+ raise ArgumentError.new(":url is required" ) unless opts[:url]
-
-
- def handle_response( url, resp, retries_on_timeout=5, max_redirects = 3 )
- if resp.is_a? Net::HTTPSuccess then resp.body
- elsif resp.is_a? String then resp
- elsif resp.is_a? Net::HTTPRedirection
- if max_redirects > 0
- do_get( URI.parse(url).merge(resp['location']).to_s, retries_on_timeout, max_redirects - 1 )
- else
- raise IOError.new("too many redirects!")
- end
- else
- resp.error!
- end
+ engine_klass = get_engine opts
+ with_timeout(opts) { engine_klass.get(opts) }
end
-
-
- def get( options = {} )
- opts = {:timeout=>5, :retries_on_timeout=>5, :max_redirects => 3, :headers=>{} }.merge(options)
- raise ArgumentError.new(":url is required" ) unless opts[:url]
- if (opts[:username] || opts[:headers]).to_s.empty?
- do_get(opts[:url], opts[:timeout], opts[:retries_on_timeout], opts[:max_redirects])
- else
-
- retrycount = 0
- resp = begin
- if defined?(SystemTimer)
- SystemTimer.timeout_after(opts[:timeout]) do
- raw_get(opts)
- end
- else
- timeout( opts[:timeout] ) do
- raw_get(opts)
- end
+
+
+ def with_timeout(opts, &block)
+ retrycount = 0
+ resp = begin
+ if defined?(SystemTimer)
+ SystemTimer.timeout_after(opts[:timeout]) do
+ yield
end
- rescue TimeoutError
- if(retrycount < opts[:retries_on_timeout])
- retrycount+=1
- retry
- else
- raise IOError.new( "HTTP request timed out #{retrycount} times" )
+ else
+ timeout( opts[:timeout] ) do
+ yield
end
end
- resp
+ rescue ::TimeoutError, ::RestClient::RequestTimeout
+ if(retrycount < opts[:retries_on_timeout])
+ retrycount+=1
+ retry
+ else
+ raise IOError.new( "HTTP request timed out #{retrycount} times" )
+ end
end
+ resp
end
-
- def raw_get(opts)
+
+
+
+ def get_engine(opts = {})
+ # default to rest_client if not given an engine
+ opts[:http_engine] ||= ( defined?(ITNH_HTTP_ENGINE) ? ITNH_HTTP_ENGINE : default_http_engine )
- if typhoeus_present?
- return typhoeus_request(opts)
- end
+ # only use typhoeus if it is actually been required
+ opts[:http_engine] = default_http_engine if opts[:http_engine] == "Typhoeus" && defined?(::Typhoeus) == nil
- resp = nil
- establish_session_if_needed(opts)
-
- if opts[:username]
- resp = get_with_auth(opts)
- retries = 0
- while resp.is_a? Net::HTTPRedirection do
- retries += 1
- raise IOError.new( "HTTP request timed out #{retries} times" ) if retries > (opts[:max_redirects] || 3)
-
- resp = get_with_auth(opts.merge(:parsed_url=>URI.parse(resp['location'])))
- end
-
- resp.body
-
+ if available_http_engines.include?(opts[:http_engine])
+ Itrigga::NetHelper.const_get opts[:http_engine]
else
- response = opts[:http_session].request_get(opts[:parsed_url].path, opts[:headers])
- response.body
+ puts "[NetHelper] Could not find http_engine '#{opts[:http_engine]}'. Available engines are: #{available_http_engines.join(',')}. Defaulting to Net::HTTP"
+ Itrigga::NetHelper.const_get default_http_engine
end
+
end
-
- def get_with_auth( opts )
- establish_session_if_needed(opts)
- req = Net::HTTP::Get.new(opts[:parsed_url].path)
- req.basic_auth( opts[:username], opts[:password] ) if opts[:username]
- resp = opts[:http_session].request(req, opts[:headers])
- end
-
- def establish_session_if_needed(opts)
- opts[:parsed_url] ||= URI.parse(opts[:url])
- opts[:http_session] ||= Net::HTTP.new(opts[:parsed_url].host, opts[:parsed_url].port)
- opts[:http_session].use_ssl = true if opts[:parsed_url].scheme == 'https'
- end
+
def query_string( h, opts={:encode_values=>false, :skip_empty=>false} )
params = []
h.each{ |k,v|
params << "#{k.to_s}=#{ opts[:encode_values] ? url_encode(v) : v }" unless v.to_s.empty? && opts[:skip_empty]