This commit is contained in:
@@ -0,0 +1,223 @@
|
||||
require 'zlib'
|
||||
require 'digest/sha1'
|
||||
require 'typhoeus/request/actions'
|
||||
require 'typhoeus/request/before'
|
||||
require 'typhoeus/request/block_connection'
|
||||
require 'typhoeus/request/cacheable'
|
||||
require 'typhoeus/request/callbacks'
|
||||
require 'typhoeus/request/marshal'
|
||||
require 'typhoeus/request/memoizable'
|
||||
require 'typhoeus/request/operations'
|
||||
require 'typhoeus/request/responseable'
|
||||
require 'typhoeus/request/streamable'
|
||||
require 'typhoeus/request/stubbable'
|
||||
|
||||
module Typhoeus
|
||||
|
||||
# This class represents a request.
|
||||
#
|
||||
# @example (see #initialize)
|
||||
#
|
||||
# @example Make a request with the shortcut.
|
||||
# response = Typhoeus.get("www.example.com")
|
||||
#
|
||||
# @see (see #initialize)
|
||||
class Request
|
||||
extend Request::Actions
|
||||
include Request::Callbacks::Types
|
||||
include Request::Callbacks
|
||||
include Request::Streamable
|
||||
include Request::Marshal
|
||||
include Request::Operations
|
||||
include Request::Responseable
|
||||
include Request::Memoizable
|
||||
include Request::Cacheable
|
||||
include Request::BlockConnection
|
||||
include Request::Stubbable
|
||||
include Request::Before
|
||||
|
||||
# Returns the provided base url.
|
||||
#
|
||||
# @return [ String ]
|
||||
attr_accessor :base_url
|
||||
|
||||
# Returns options, which includes default parameters.
|
||||
#
|
||||
# @return [ Hash ]
|
||||
attr_accessor :options
|
||||
|
||||
# Returns the hydra in which the request ran, if any.
|
||||
#
|
||||
# @return [ Typhoeus::Hydra ]
|
||||
#
|
||||
# @api private
|
||||
attr_accessor :hydra
|
||||
|
||||
# Returns the original options provided.
|
||||
#
|
||||
# @return [ Hash ]
|
||||
#
|
||||
# @api private
|
||||
attr_accessor :original_options
|
||||
|
||||
# @return [ Boolean ]
|
||||
#
|
||||
# @api private
|
||||
attr_accessor :block_connection
|
||||
|
||||
# Creates a new request.
|
||||
#
|
||||
# @example Simplest request.
|
||||
# response = Typhoeus::Request.new("www.example.com").run
|
||||
#
|
||||
# @example Request with url parameters.
|
||||
# response = Typhoeus::Request.new(
|
||||
# "www.example.com",
|
||||
# params: {a: 1}
|
||||
# ).run
|
||||
#
|
||||
# @example Request with a body.
|
||||
# response = Typhoeus::Request.new(
|
||||
# "www.example.com",
|
||||
# body: {b: 2}
|
||||
# ).run
|
||||
#
|
||||
# @example Request with parameters and body.
|
||||
# response = Typhoeus::Request.new(
|
||||
# "www.example.com",
|
||||
# params: {a: 1},
|
||||
# body: {b: 2}
|
||||
# ).run
|
||||
#
|
||||
# @example Create a request and allow follow redirections.
|
||||
# response = Typhoeus::Request.new(
|
||||
# "www.example.com",
|
||||
# followlocation: true
|
||||
# ).run
|
||||
#
|
||||
# @param [ String ] base_url The url to request.
|
||||
# @param [ options ] options The options.
|
||||
#
|
||||
# @option options [ Hash ] :params Translated
|
||||
# into url parameters.
|
||||
# @option options [ Hash ] :body Translated
|
||||
# into HTTP POST request body.
|
||||
#
|
||||
# @return [ Typhoeus::Request ] The request.
|
||||
#
|
||||
# @note See {http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy/Options Ethon::Easy::Options} for more options.
|
||||
#
|
||||
# @see Typhoeus::Hydra
|
||||
# @see Typhoeus::Response
|
||||
# @see Typhoeus::Request::Actions
|
||||
def initialize(base_url, options = {})
|
||||
@base_url = base_url
|
||||
@original_options = options
|
||||
@options = options.dup
|
||||
|
||||
set_defaults
|
||||
end
|
||||
|
||||
# Return the url.
|
||||
# In contrast to base_url which returns the value you specified, url returns
|
||||
# the full url including the parameters.
|
||||
#
|
||||
# @example Get the url.
|
||||
# request.url
|
||||
#
|
||||
# @since 0.5.5
|
||||
def url
|
||||
easy = EasyFactory.new(self).get
|
||||
url = easy.url
|
||||
Typhoeus::Pool.release(easy)
|
||||
url
|
||||
end
|
||||
|
||||
# Returns whether other is equal to self.
|
||||
#
|
||||
# @example Are request equal?
|
||||
# request.eql?(other_request)
|
||||
#
|
||||
# @param [ Object ] other The object to check.
|
||||
#
|
||||
# @return [ Boolean ] Returns true if equal, else false.
|
||||
#
|
||||
# @api private
|
||||
def eql?(other)
|
||||
self.class == other.class &&
|
||||
self.base_url == other.base_url &&
|
||||
fuzzy_hash_eql?(self.options, other.options)
|
||||
end
|
||||
|
||||
# Overrides Object#hash.
|
||||
#
|
||||
# @return [ Integer ] The integer representing the request.
|
||||
#
|
||||
# @api private
|
||||
def hash
|
||||
Zlib.crc32 cache_key
|
||||
end
|
||||
|
||||
# Returns a cache key for use with caching methods that required a string
|
||||
# for a key. Will get used by ActiveSupport::Cache stores automatically.
|
||||
#
|
||||
# @return [ String ] The cache key.
|
||||
def cache_key
|
||||
Digest::SHA1.hexdigest "#{self.class.name}#{base_url}#{hashable_string_for(options)}"
|
||||
end
|
||||
|
||||
# Mimics libcurls POST body generation. This is not accurate, but good
|
||||
# enough for VCR.
|
||||
#
|
||||
# @return [ String ] The encoded body.
|
||||
# otherwise.
|
||||
#
|
||||
# @api private
|
||||
def encoded_body
|
||||
Ethon::Easy::Form.new(nil, options[:body]).to_s
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Checks if two hashes are equal or not, discarding
|
||||
# first-level hash order.
|
||||
#
|
||||
# @param [ Hash ] left
|
||||
# @param [ Hash ] right hash to check for equality
|
||||
#
|
||||
# @return [ Boolean ] Returns true if hashes have
|
||||
# same values for same keys and same length,
|
||||
# even if the keys are given in a different order.
|
||||
def fuzzy_hash_eql?(left, right)
|
||||
return true if (left == right)
|
||||
|
||||
(left.count == right.count) && left.inject(true) do |res, kvp|
|
||||
res && (kvp[1] == right[kvp[0]])
|
||||
end
|
||||
end
|
||||
|
||||
def hashable_string_for(obj)
|
||||
case obj
|
||||
when Hash
|
||||
hashable_string_for(obj.sort_by {|sub_obj| sub_obj.first.to_s})
|
||||
when Array
|
||||
obj.map {|sub_obj| hashable_string_for(sub_obj)}.to_s
|
||||
else
|
||||
obj.to_s
|
||||
end
|
||||
end
|
||||
|
||||
# Sets default header and verbose when turned on.
|
||||
def set_defaults
|
||||
default_user_agent = Config.user_agent || Typhoeus::USER_AGENT
|
||||
|
||||
options[:headers] = {'User-Agent' => default_user_agent}.merge(options[:headers] || {})
|
||||
options[:headers]['Expect'] ||= ''
|
||||
options[:verbose] = Typhoeus::Config.verbose if options[:verbose].nil? && !Typhoeus::Config.verbose.nil?
|
||||
options[:timeout] = Typhoeus::Config.timeout if options[:timeout].nil? && !Typhoeus::Config.timeout.nil?
|
||||
options[:connecttimeout] = Typhoeus::Config.connecttimeout if options[:connecttimeout].nil? && !Typhoeus::Config.connecttimeout.nil?
|
||||
options[:maxredirs] ||= 50
|
||||
options[:proxy] = Typhoeus::Config.proxy unless options.has_key?(:proxy) || Typhoeus::Config.proxy.nil?
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user