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]