pax_global_header00006660000000000000000000000064121453606370014521gustar00rootroot0000000000000052 comment=19dc58acb45ff77c1fc26ab471fe695bc92b452c ruby-typhoeus-0.6.3/000077500000000000000000000000001214536063700143665ustar00rootroot00000000000000ruby-typhoeus-0.6.3/.gitignore000066400000000000000000000000761214536063700163610ustar00rootroot00000000000000*.gem Gemfile.lock doc/ .yardoc .rvmrc coverage check.sh tags ruby-typhoeus-0.6.3/.rspec000066400000000000000000000000611214536063700155000ustar00rootroot00000000000000--tty --color --format documentation --backtrace ruby-typhoeus-0.6.3/.travis.yml000066400000000000000000000002151214536063700164750ustar00rootroot00000000000000script: "bundle exec rake" rvm: - 1.8.7 - 1.9.2 - 1.9.3 - jruby-head - jruby-18mode - jruby-19mode - rbx-18mode - rbx-19mode ruby-typhoeus-0.6.3/CHANGELOG.md000066400000000000000000000237371214536063700162130ustar00rootroot00000000000000# Changelog ## Master [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.3...master) ## 0.6.3 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.2...v0.6.3) Enhancements: * Cache hydra per thread. * Various documentation improvements. ([craiglittle](https://github.com/craiglittle)) * Add support for lazy construction of responses from stubbed requests. ([ryankindermann](https://github.com/ryankinderman), [\#275](https://github.com/typhoeus/typhoeus/pull/275)) ## 0.6.2 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.1...v0.6.2) Enhancements: * Reintroduce a global cache. * `Request#handled_response` falls back to the original response. ([turnerking](https://github.com/turnerking), [\#272](https://github.com/typhoeus/typhoeus/pull/272)) * When `Errors::NoStub` is raised the `url` is displayed. ([dschneider](https://github.com/dschneider), [\#276](https://github.com/typhoeus/typhoeus/pull/276)) * Make `Request#hash` consistent. * Add `.rvmrc` and `ctags` to `.gitignore`. ([ryankindermann](https://github.com/ryankinderman), [\#274](https://github.com/typhoeus/typhoeus/pull/274)) ## 0.6.1 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.6.0...v0.6.1) Enhancements: * Updated ethon version which allows to set multiple protocols. ## 0.6.0 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.4...v0.6.0) Enhancements: * `Request#url` now also contains the url parameters. * Use updated ethon version which provides access to protocols and redir_protocols in response to [libcurl SASL buffer overflow vulnerability](http://curl.haxx.se/docs/adv_20130206.html) Bugfixes: * Corrected ssl options for the faraday adapter. * The before hook now correctly returns the response. ([Mattias Putman](https://github.com/challengee), [\#268](https://github.com/typhoeus/typhoeus/pull/268)) * Benchmark is working again. ## 0.5.4 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.3...v0.5.4) Enhancements: * Make sure response_code is an integer. * When setting an header through vcr or webmock it becomes a `Typhoeus::Response::Header`. * Provide a Rack middleware to decode nested Typhoeus arrays properly. ([Dwayne Macgowan](https://github.com/dwaynemac), [\#224](https://github.com/typhoeus/typhoeus/issues/224)) * Handled response is available again. * Rename parameter `url` to `base_url`. See discussion here: [\#250](https://github.com/typhoeus/typhoeus/issues/250). ([bkimble](https://github.com/bkimble), [\#256](https://github.com/typhoeus/typhoeus/pull/256)) * Provide O(1) header access. * Work around ruby 1.8.7 limitations. ([Chris Johnson](https://github.com/findchris), [\#227](https://github.com/typhoeus/typhoeus/pull/227) ) * Provide symbol access. ## 0.5.3 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.2...v0.5.3) Enhancements: * When checking options in Expecation#matches? also consider Request#options. Bugfixes: * Do not break backwards compatibility with case insensitive headers access. * Make sure hydra behaves correct in case of before hooks. ## 0.5.2 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.1...v0.5.2) Enhancements: * Do not check the return_code in Response#success? when response is mocked. * Check for memoization, stubbing, before hooks are delayed to Hydra#run. It was on Hydra#queue before and led to strange behavior because if the request was stubbed, it was wrapped up in queue already. There was no way to add callbacks after queue thatswhy. This is now different, since everything happens in run, just as you expect. ## 0.5.1 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.5.0...v0.5.1) Enhancements: * Downcase header keys for easier access ( [\#227](https://github.com/typhoeus/typhoeus/issues/227) ) * Using an updated Ethon version. ## 0.5.0 [Full Changelog](http://github.com/typhoeus/typhoeus/compare/v0.4.2...v0.5.0) Major Changes: * Ethon integration * Params are url params and a body is always a body for every request type * The options you can set might have a slightly other names, as Ethon sticks to libcurl names. See [Easy.new](http://rubydoc.info/github/typhoeus/ethon/Ethon/Easy#initialize-instance_method) for a description. * Request parameter and body are properly encoded (only POST multiform body is not) * No more header sanitizing. Before: `:headers => { 'user_agent' => 'Custom' }` was modified to `:headers => { 'User-Agent' => 'Custom' }` * `Typhoeus::Easy` and `Typhoeus::Multi` are now `Ethon::Easy` and `Ethon::Multi` * Request shortcuts: `Typhoeus.get("www.google.de")` * Global configuration: ```ruby Typhoeus.configure do |config| config.verbose = true config.memoize = true end ``` * No more `Response#headers_hash`, instead `Response#headers` returning the last header and response#redirections returning the responses with headers generated through redirections * Instead of defining the same callbacks on every request, you can define global callbacks: ```ruby Typhoeus.on_complete { p "yay" } ``` * The stubbing interface changed slightly. You now have the same syntax as for requests: ```ruby Typhoeus.stub(url, options).and_return(response) ``` * The following things were removed because they do not seemed to be used at all. Ping me if you disagree! * `Typhoeus::Filter` * `Typhoeus::Remote` * `Typhoeus::RemoteMethod` * `Typhoeus::RemoteProxyObject` * build in cache interface Enhancements: * Documentation ( [Alex P](https://github.com/ifesdjeen), [\#188](https://github.com/typhoeus/typhoeus/issues/188) ) * Request#on\_complete can hold multiple blocks. * Request#eql? recognizes when header/params/body has a different order, but still same keys and values ( [Alex P](https://github.com/ifesdjeen), [\#194](https://github.com/typhoeus/typhoeus/issues/194) ) Bug Fixes: * Zero bytes in strings are escaped for libcurl * Add support for socks5 hostname proxy type ( [eweathers](https://github.com/eweathers), [\#183](https://github.com/typhoeus/typhoeus/issues/183) ) * Post body is encoded ( [Rohan Deshpande](https://github.com/rdeshpande), [\#143](https://github.com/typhoeus/typhoeus/issues/143) ) * Set default user agent ( [Steven Shingler](https://github.com/sshingler), [\#176](https://github.com/typhoeus/typhoeus/issues/176) ) ## 0.4.2 * A header hotfix ## 0.4.1 * Fix verifypeer and verifyhost options * Fix header sending ## 0.4.0 * Make a GET even when a body is given * Deprecated User Agent setter removed * Allow cache key basis overwrite (John Crepezzi, #147) * FFI integration (Daniel Cavanagh, #151) * Refactor upload code (Marnen Laibow-Koser, #152) * Fix travis-ci build (Ezekiel Templin, #160) ## 0.3.3 * Make sure to call the Easy::failure callback on all non-success http response codes, even invalid ones. [balexis] * Use bytesize instead of length to determine Content-Length [dlamacchia] * Added SSL version option to Easy/Request [michelbarbosa/dbalatero] ## 0.3.2 * Fix array params to be consistent with HTTP spec [gridaphobe] * traversal\_to\_params\_hash should use the escape option [itsmeduncan] * Fix > 1024 open file descriptors [mschulkind] * Fixed a bug with internally queued requests being dropped [mschulkind] * Use gemspec in bundler to avoid duplication [mschulkind] * Run internally queued requests in FIFO order [mschulkind] * Moved Typhoeus::VERSION to a separate file, to fix rake build\_native [mschulkind] * Fixed problems related to put requests with empty bodies [skaes, GH-84] * Added CURLOPT\_INTERFACE option via Request#interface=. [spiegela] * Added Tempfile support to Form#process! [richievos] * Hydra won't forget to accept gzip/deflate encoding [codesnik] * Accept and convert strings to integers in Typhoeus::Request#initialize for timeout/cache\_timeout/connect\_timeout values when using ruby 1.9.x. [djnawara] * Added interface for registering stub finders [myronmarston] * Fixed header stubbing [myronmarston] * Added PKCS12 support [jodell] * Make a request with handlers marshallable [bernerdschaefer] * Upgraded to RSpec 2 [bernerdschaefer] * Fix HTTP status edge-case [balexis] * Expose primary\_ip to easy object [balexis] ## 0.2.4 * Fix form POSTs to only use multipart for file uploads, otherwise use application/x-www-form-urlencoded [dbalatero] ## 0.2.3 * Code duplication in Typhoeus::Form led to nested URL param errors on POST only. Fixed [dbalatero] ## 0.2.2 * Fixed a problem with nested URL params encoding incorrectly [dbalatero] ## 0.2.1 * Added extended proxy support [Zapotek, GH-46] * eliminated compile time warnings by using proper type declarations [skaes, GH-54] * fixed broken calls to rb\_raise [skaes, GH-54] * prevent leaking of curl easy handles when exceptions are raised (either from typhoeus itself or user callbacks) [skaes, GH-54] * fixed Easy#timed\_out? using curl return codes [skaes, GH-54] * provide curl return codes and corresponding curl error messages on classes Easy and Request [skaes, GH-54] * allow VCR to whitelist hosts in Typhoeus stubbing/mocking [myronmarston, GH-57] * added timed\_out? documentation, method to Response [dbalatero, GH-34] * added abort to Hydra to prematurely stop a hydra.run [Zapotek] * added file upload support for POST requests [jtarchie, GH-59] ## 0.2.0 * Fix warning in Request#headers from attr\_accessor * Params with array values were not parsing into the format that rack expects [GH-39, smartocci] * Removed Rack as a dependency [GH-45] * Added integration hooks for VCR! ## 0.1.31 * Fixed bug in setting compression encoding [morhekil] * Exposed authentication control methods through Request interface [morhekil] ## 0.1.30 * Exposed CURLOPT\_CONNECTTIMEOUT\_MS to Requests [balexis] ## 0.1.29 * Fixed a memory corruption with using CURLOPT\_POSTFIELDS [gravis, 32531d0821aecc4] ## 0.1.28 * Added SSL cert options for Typhoeus::Easy [GH-25, gravis] * Ported SSL cert options to Typhoeus::Request interface [gravis] * Added support for any HTTP method (purge for Varnish) [ryana] ## 0.1.27 * Added rack as dependency, added dev dependencies to Rakefile [GH-21] ruby-typhoeus-0.6.3/CONTRIBUTING.md000066400000000000000000000007711214536063700166240ustar00rootroot00000000000000We love pull requests. Here's a quick guide: 1. Fork the repo. 2. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate: `bundle && bundle exec rake` 3. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or fixing a bug, we need a test! 4. Make the test pass. 5. Push to your fork and submit a pull request. And in case we didn't emphasize it enough: we love tests! ruby-typhoeus-0.6.3/Gemfile000066400000000000000000000005001214536063700156540ustar00rootroot00000000000000source "https://rubygems.org" gemspec gem "rake" group :development, :test do gem "rspec", "~> 2.11" gem "sinatra", "~> 1.3" gem "json" gem "faraday", "~> 0.8.4" if RUBY_PLATFORM == "java" gem "spoon" end unless ENV["CI"] gem "guard-rspec", "~> 0.7" gem 'rb-fsevent', '~> 0.9.1' end end ruby-typhoeus-0.6.3/Guardfile000066400000000000000000000003531214536063700162140ustar00rootroot00000000000000# vim:set filetype=ruby: guard( "rspec", all_after_pass: false, cli: "--fail-fast --tty --format documentation --colour") do watch(%r{^spec/.+_spec\.rb$}) watch(%r{^lib/(.+)\.rb$}) { |match| "spec/#{match[1]}_spec.rb" } end ruby-typhoeus-0.6.3/LICENSE000066400000000000000000000021461214536063700153760ustar00rootroot00000000000000Copyright (c) 2009-2010 Paul Dix Copyright (c) 2011 David Balatero Copyright (c) 2012 Hans Hasselberg Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby-typhoeus-0.6.3/README.md000066400000000000000000000042451214536063700156520ustar00rootroot00000000000000# Typhoeus [![Build Status](https://secure.travis-ci.org/typhoeus/typhoeus.png)](http://travis-ci.org/typhoeus/typhoeus) [![Code Climate](https://codeclimate.com/github/typhoeus/typhoeus.png)](https://codeclimate.com/github/typhoeus/typhoeus) Like a modern code version of the mythical beast with 100 serpent heads, Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling logic. ## Example A single request: ```ruby Typhoeus.get("www.example.com", followlocation: true) ``` Parallel requests: ```ruby hydra = Typhoeus::Hydra.new 10.times.map{ hydra.queue(Typhoeus::Request.new("www.example.com", followlocation: true)) } hydra.run ``` ## Installation ``` gem install typhoeus ``` ``` gem "typhoeus" ``` ## Project Tracking * [Documentation](http://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) (GitHub master) * [Website](http://typhoeus.github.com/) (v0.4.2) * [Mailing list](http://groups.google.com/group/typhoeus) ## LICENSE (The MIT License) Copyright © 2009-2010 [Paul Dix](http://www.pauldix.net/) Copyright © 2011-2012 [David Balatero](https://github.com/dbalatero/) Copyright © 2012-2013 [Hans Hasselberg](http://github.com/i0rek/) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby-typhoeus-0.6.3/Rakefile000066400000000000000000000014501214536063700160330ustar00rootroot00000000000000require "bundler" Bundler.setup require "rake" require "rspec/core/rake_task" $LOAD_PATH.unshift File.expand_path("../lib", __FILE__) require "typhoeus/version" task :gem => :build task :build do system "gem build typhoeus.gemspec" end task :install => :build do system "gem install typhoeus-#{Typhoeus::VERSION}.gem" end task :release => :build do system "git tag -a v#{Typhoeus::VERSION} -m 'Tagging #{Typhoeus::VERSION}'" system "git push --tags" system "gem push typhoeus-#{Typhoeus::VERSION}.gem" end RSpec::Core::RakeTask.new(:spec) do |t| t.verbose = false t.ruby_opts = "-W -I./spec -rspec_helper" end desc "Start up the test servers" task :start do require_relative 'spec/support/boot' begin Boot.start_servers(:rake) rescue Exception end end task :default => :spec ruby-typhoeus-0.6.3/UPGRADE.md000066400000000000000000000031411214536063700157760ustar00rootroot00000000000000# Upgrade guide ## 0.5 ### Options Fix the option names, because some were renamed. The errors should point you in the right direction: ```ruby Typhoeus.get("www.example.com", follow_location: true) # Ethon::Errors::InvalidOption: The option: follow_location is invalid. # Please try followlocation instead of follow_location. # ... [Backtrace] Typhoeus.get("www.example.com", followlocation: true).code #=> 200 ``` ### Headers `Response#headers` returns a hash now and replaces `Response#headers_hash`, use `Response#response_headers` for the raw string: ```ruby Typhoeus.get("www.example.com", followlocation: true).headers #=> { # "date"=>"Tue, 06 Nov 2012 09:07:27 GMT", # "server"=>"Apache/2.2.3 (CentOS)", # "last-modified"=>"Wed, 09 Feb 2011 17:13:15 GMT", # "vary"=>"Accept-Encoding", # "connection"=>"close", # "content-type"=>"text/html; charset=UTF-8" # } Typhoeus.get("www.example.com", followlocation: true).response_headers #=> "HTTP/1.0 302 Found\r\nLocation: http://www.iana.org/domains/example/ [...]" ``` ### Params vs body Make sure every request sends proper params and body (especially POST/PUT). `:params` becomes url parameter and `:body` request body. Before params for POST was smashed into the body. ### Configuration Create a global configuration in case you want to turn on verbose, memoize or block_connection: ```ruby Typhoeus.configure do |config| config.verbose = true config.memoize = true end ``` ### Docs When in doubt, read the [docs](http://rubydoc.info/github/typhoeus/typhoeus/frames/Typhoeus) or the [code](https://www.github.com/typhoeus). ruby-typhoeus-0.6.3/lib/000077500000000000000000000000001214536063700151345ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/rack/000077500000000000000000000000001214536063700160545ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/rack/typhoeus.rb000066400000000000000000000000621214536063700202570ustar00rootroot00000000000000require "rack/typhoeus/middleware/params_decoder" ruby-typhoeus-0.6.3/lib/rack/typhoeus/000077500000000000000000000000001214536063700177345ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/rack/typhoeus/middleware/000077500000000000000000000000001214536063700220515ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/rack/typhoeus/middleware/params_decoder.rb000066400000000000000000000031111214536063700253420ustar00rootroot00000000000000require 'rack/typhoeus/middleware/params_decoder/helper' module Rack module Typhoeus module Middleware # This Rack middleware takes care of the proper deserialization of # the nested params encoded by Typhoeus. # # @example Require the railtie when using Rails. # require 'typhoeus/railtie' # # @example Include the middleware for Rack based applications. # use Rack::Typhoeus::Middleware::ParamsDecoder # # @example Use the helper directly. Not recommended as b/c the interface might change. # require 'rack/typhoeus/middleware/params_decoder/helper' # include Rack::Typhoeus::Middleware::ParamsDecoder::Helper # decode!(params) # # @author Dwayne Macgowan # @since 0.5.4 class ParamsDecoder include ParamsDecoder::Helper def initialize(app) @app = app end def call(env) req = Rack::Request.new(env) decode(req.params).each_pair { |k, v| update_params req, k, v } @app.call(env) end private # Persist params change in environment. Extracted from: # https://github.com/rack/rack/blob/master/lib/rack/request.rb#L233 def update_params(req, k, v) found = false if req.GET.has_key?(k) found = true req.GET[k] = v end if req.POST.has_key?(k) found = true req.POST[k] = v end unless found req.GET[k] = v end end end end end end ruby-typhoeus-0.6.3/lib/rack/typhoeus/middleware/params_decoder/000077500000000000000000000000001214536063700250215ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/rack/typhoeus/middleware/params_decoder/helper.rb000066400000000000000000000040061214536063700266250ustar00rootroot00000000000000module Rack module Typhoeus module Middleware class ParamsDecoder module Helper # Recursively decodes Typhoeus encoded arrays in given Hash. # # @example Use directly in a Rails controller. # class ApplicationController # before_filter :decode_typhoeus_arrays # end # # @author Dwayne Macgowan # def decode_typhoeus_arrays decode!(params) end # Recursively decodes Typhoeus encoded arrays in given Hash. # # @param hash [Hash]. This Hash will be modified! # # @return [Hash] Hash with properly decoded nested arrays. def decode!(hash) return hash unless hash.is_a?(Hash) hash.each_pair do |key,value| if value.is_a?(Hash) decode!(value) hash[key] = convert(value) end end hash end def decode(hash) decode!(hash.dup) end private # Checks if Hash is an Array encoded as a Hash. # Specifically will check for the Hash to have this # form: {'0' => v0, '1' => v1, .., 'n' => vN } # # @param hash [Hash] # # @return [Boolean] True if its a encoded Array, else false. def encoded?(hash) return false if hash.empty? keys = hash.keys.map{|i| i.to_i if i.respond_to?(:to_i)}.sort keys == hash.keys.size.times.to_a end # If the Hash is an array encoded by typhoeus an array is returned # else the self is returned # # @param hash [Hash] The Hash to convert into an Array. # # @return [Arraya/Hash] def convert(hash) if encoded?(hash) Hash[hash.sort].values else hash end end end end end end end ruby-typhoeus-0.6.3/lib/typhoeus.rb000066400000000000000000000065441214536063700173520ustar00rootroot00000000000000require 'digest/sha2' require 'ethon' require 'typhoeus/config' require 'typhoeus/easy_factory' require 'typhoeus/errors' require 'typhoeus/expectation' require 'typhoeus/hydra' require 'typhoeus/pool' require 'typhoeus/request' require 'typhoeus/response' require 'typhoeus/version' # If we are using any Rack-based application, then we need the Typhoeus rack # middleware to ensure our app is running properly. if defined?(Rack) require "rack/typhoeus" end # If we are using Rails, then we will include the Typhoeus railtie. # if defined?(Rails) # require "typhoeus/railtie" # end # Typhoeus is a HTTP client library based on Ethon which # wraps libcurl. Sitting on top of libcurl makes Typhoeus # very reliable and fast. # # There are some gems using Typhoeus like # {https://github.com/myronmarston/vcr VCR}, # {https://github.com/bblimke/webmock WebMock} or # {https://github.com/technoweenie/faraday Faraday}. VCR # and WebMock provide their own adapter whereas # Faraday relies on {Faraday::Adapter::Typhoeus} # since Typhoeus version 0.5. # # @example (see Typhoeus::Request) # @example (see Typhoeus::Hydra) # # @see Typhoeus::Request # @see Typhoeus::Hydra # @see Faraday::Adapter::Typhoeus # # @since 0.5.0 module Typhoeus extend self extend Request::Actions extend Request::Callbacks::Types # The default Typhoeus user agent. USER_AGENT = "Typhoeus - https://github.com/typhoeus/typhoeus" # Set the Typhoeus configuration options by passing a block. # # @example (see Typhoeus::Config) # # @yield [ Typhoeus::Config ] # # @return [ Typhoeus::Config ] The configuration. # # @see Typhoeus::Config def configure yield Config end # Stub out a specific request. # # @example (see Typhoeus::Expectation) # # @param [ String ] base_url The url to stub out. # @param [ Hash ] options The options to stub out. # # @return [ Typhoeus::Expectation ] The expecatation. # # @see Typhoeus::Expectation def stub(base_url, options = {}, &block) expectation = Expectation.all.find{ |e| e.base_url == base_url && e.options == options } if expectation.nil? expectation = Expectation.new(base_url, options) Expectation.all << expectation end expectation.and_return(&block) unless block.nil? expectation end # Add before callbacks. # # @example Add before callback. # Typhoeus.before { |request| p request.base_url } # # @param [ Block ] block The callback. # # @yield [ Typhoeus::Request ] # # @return [ Array ] All before blocks. def before(&block) @before ||= [] @before << block if block_given? @before end # Execute given block as if block connection is turned off. # The old block connection state is restored afterwards. # # @example Make a real request, no matter if it's blocked. # Typhoeus::Config.block_connection = true # Typhoeus.get("www.example.com").code # #=> raise Typhoeus::Errors::NoStub # # Typhoeus.with_connection do # Typhoeus.get("www.example.com").code # #=> :ok # end # # @param [ Block ] block The block to execute. # # @return [ Object ] Returns the return value of the block. # # @see Typhoeus::Config#block_connection def with_connection old = Config.block_connection Config.block_connection = false result = yield if block_given? Config.block_connection = old result end end ruby-typhoeus-0.6.3/lib/typhoeus/000077500000000000000000000000001214536063700170145ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/adapters/000077500000000000000000000000001214536063700206175ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/adapters/faraday.rb000066400000000000000000000110001214536063700225430ustar00rootroot00000000000000require 'faraday' module Faraday # :nodoc: class Adapter # :nodoc: # Adapter to use Faraday with Typhoeus. # # @example Use Typhoeus. # require 'faraday' # require 'typhoeus' # require 'typhoeus/adapters/faraday' # # conn = Faraday.new(url: "www.example.com") do |faraday| # faraday.adapter :typhoeus # end # # response = conn.get("/") class Typhoeus < Faraday::Adapter self.supports_parallel = true (class << self; self; end).instance_eval do remove_method :setup_parallel_manager if method_defined? :setup_parallel_manager end remove_method :call if method_defined? :call remove_method :perform_request if method_defined? :perform_request remove_method :request if method_defined? :request remove_method :read_body if method_defined? :read_body remove_method :configure_ssl if method_defined? :configure_ssl remove_method :configure_proxy if method_defined? :configure_proxy remove_method :configure_timeout if method_defined? :configure_timeout remove_method :configure_socket if method_defined? :configure_socket remove_method :parallel? if method_defined? :parallel? # Setup Hydra with provided options. # # @example Setup Hydra. # Faraday::Adapter::Typhoeus.setup_parallel_manager # #=> # # # @param (see Typhoeus::Hydra#initialize) # @option (see Typhoeus::Hydra#initialize) # # @return [ Typhoeus::Hydra ] The hydra. def self.setup_parallel_manager(options = {}) ::Typhoeus::Hydra.new(options) end dependency 'typhoeus' # Hook into Faraday and perform the request with Typhoeus. # # @param [ Hash ] env The environment. # # @return [ void ] def call(env) super perform_request env @app.call env end private def perform_request(env) if parallel?(env) env[:parallel_manager].queue request(env) else request(env).run end end def request(env) read_body env req = ::Typhoeus::Request.new( env[:url].to_s, :method => env[:method], :body => env[:body], :headers => env[:request_headers] ) configure_ssl req, env configure_proxy req, env configure_timeout req, env configure_socket req, env req.on_complete do |resp| if resp.timed_out? if parallel?(env) # TODO: error callback in async mode else raise Faraday::Error::TimeoutError, "request timed out" end end save_response(env, resp.code, resp.body) do |response_headers| response_headers.parse resp.response_headers end # in async mode, :response is initialized at this point env[:response].finish(env) if parallel?(env) end req end def read_body(env) env[:body] = env[:body].read if env[:body].respond_to? :read end def configure_ssl(req, env) ssl = env[:ssl] ssl_verifyhost = (ssl && ssl.fetch(:verify, true)) ? 2 : 0 req.options[:ssl_verifyhost] = ssl_verifyhost req.options[:sslversion] = ssl[:version] if ssl[:version] req.options[:sslcert] = ssl[:client_cert] if ssl[:client_cert] req.options[:sslkey] = ssl[:client_key] if ssl[:client_key] req.options[:cainfo] = ssl[:ca_file] if ssl[:ca_file] req.options[:capath] = ssl[:ca_path] if ssl[:ca_path] end def configure_proxy(req, env) proxy = env[:request][:proxy] return unless proxy req.options[:proxy] = "#{proxy[:uri].host}:#{proxy[:uri].port}" if proxy[:username] && proxy[:password] req.options[:proxyuserpwd] = "#{proxy[:username]}:#{proxy[:password]}" end end def configure_timeout(req, env) env_req = env[:request] req.options[:timeout_ms] = (env_req[:timeout] * 1000) if env_req[:timeout] req.options[:connecttimeout_ms] = (env_req[:open_timeout] * 1000) if env_req[:open_timeout] end def configure_socket(req, env) if bind = env[:request][:bind] req.options[:interface] = bind[:host] end end def parallel?(env) !!env[:parallel_manager] end end end end ruby-typhoeus-0.6.3/lib/typhoeus/config.rb000066400000000000000000000027551214536063700206170ustar00rootroot00000000000000module Typhoeus # The Typhoeus configuration used to set global # options. # @example Set the configuration options within a block. # Typhoeus.configure do |config| # config.verbose = true # end # # @example Set the configuration directly. # Typhoeus::Config.verbose = true module Config extend self # Defines whether the connection is blocked. # Defaults to false. When set to true, only # stubbed requests are allowed. A # {Typhoeus::Errors::NoStub} error is raised, # when trying to do a real request. It's possible # to work around inside # {Typhoeus#with_connection}. # # @return [ Boolean ] # # @see Typhoeus::Request::BlockConnection # @see Typhoeus::Hydra::BlockConnection # @see Typhoeus#with_connection # @see Typhoeus::Errors::NoStub attr_accessor :block_connection # Defines whether GET requests are memoized when using the {Typhoeus::Hydra}. # # @return [ Boolean ] # # @see Typhoeus::Hydra # @see Typhoeus::Hydra::Memoizable attr_accessor :memoize # Defines whether curls debug output is shown. # Unfortunately it prints to stderr. # # @return [ Boolean ] # # @see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTVERBOSE attr_accessor :verbose # Defines whether requests are cached. # # @return [ Object ] # # @see Typhoeus::Hydra::Cacheable # @see Typhoeus::Request::Cacheable attr_accessor :cache end end ruby-typhoeus-0.6.3/lib/typhoeus/easy_factory.rb000066400000000000000000000062061214536063700220350ustar00rootroot00000000000000module Typhoeus # This is a Factory for easies to be used in the hydra. # Before an easy is ready to be added to a multi the # on_complete callback to be set. # This is done by this class. # # @api private class EasyFactory # Returns the request provided. # # @return [ Typhoeus::Request ] attr_reader :request # Returns the hydra provided. # # @return [ Typhoeus::Hydra ] attr_reader :hydra # Create an easy factory. # # @example Create easy factory. # Typhoeus::Hydra::EasyFactory.new(request, hydra) # # @param [ Request ] request The request to build an easy for. # @param [ Hydra ] hydra The hydra to build an easy for. def initialize(request, hydra = nil) @request = request @hydra = hydra end # Return the easy in question. # # @example Return easy. # easy_factory.easy # # @return [ Ethon::Easy ] The easy. def easy @easy ||= Typhoeus::Pool.get end # Fabricated easy. # # @example Prepared easy. # easy_factory.get # # @return [ Ethon::Easy ] The easy. def get begin easy.http_request( request.base_url, request.options.fetch(:method, :get), request.options.reject{ |k,_| [:method, :cache_ttl].include?(k) } ) rescue Ethon::Errors::InvalidOption => e help = provide_help(e.message.match(/:\s(\w+)/)[1]) raise $!, "#{$!}#{help}", $!.backtrace end set_callback easy end private # Sets on_complete callback on easy in order to be able to # track progress. # # @example Set callback. # easy_factory.set_callback # # @return [ Ethon::Easy ] The easy. def set_callback easy.on_complete do |easy| request.finish(Response.new(easy.to_hash)) Typhoeus::Pool.release(easy) if hydra && !hydra.queued_requests.empty? hydra.add(hydra.queued_requests.shift) end end end def provide_help(option) renamed = { :auth_method => :httpauth, :connect_timeout => :connecttimeout, :disable_ssl_host_verification => :ssl_verifyhost, :disable_ssl_peer_verification => :ssl_verifypeer, :encoding => :accept_encoding, :follow_location => :followlocation, :max_redirects => :maxredirs, :password => :userpwd, :proxy_auth_method => :proxyauth, :proxy_password => :proxyuserpwd, :proxy_type => :proxytype, :proxy_username => :proxyuserpwd, :ssl_cacert => :cainfo, :ssl_capath => :capath, :ssl_cert => :sslcert, :ssl_cert_type => :sslcerttype, :ssl_key => :sslkey, :ssl_key_password => :keypasswd, :ssl_key_type => :sslkeytype, :ssl_version => :sslversion, :username => :userpwd } removed = [:cache_key_basis, :cache_timout, :user_agent] if new_option = renamed[option.to_sym] "\nPlease try #{new_option} instead of #{option}." if new_option elsif removed.include?(option.to_sym) "\nThe option #{option} was removed." end end end end ruby-typhoeus-0.6.3/lib/typhoeus/errors.rb000066400000000000000000000002621214536063700206550ustar00rootroot00000000000000require 'typhoeus/errors/typhoeus_error' require 'typhoeus/errors/no_stub' module Typhoeus # This namespace contains all errors raised by Typhoeus. module Errors end end ruby-typhoeus-0.6.3/lib/typhoeus/errors/000077500000000000000000000000001214536063700203305ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/errors/no_stub.rb000066400000000000000000000004341214536063700223270ustar00rootroot00000000000000module Typhoeus module Errors # Raises when block connection is turned on # and making a real request. class NoStub < TyphoeusError def initialize(request) super("The connection is blocked and no stub defined: #{request.url}") end end end end ruby-typhoeus-0.6.3/lib/typhoeus/errors/typhoeus_error.rb000066400000000000000000000002251214536063700237450ustar00rootroot00000000000000module Typhoeus module Errors # Default typhoeus error class for all custom errors. class TyphoeusError < StandardError end end end ruby-typhoeus-0.6.3/lib/typhoeus/expectation.rb000066400000000000000000000132341214536063700216670ustar00rootroot00000000000000module Typhoeus # This class represents an expectation. It is part # of the stubbing mechanism. An expectation contains # a url and options, like a request. They are compared # to the request url and options in order to evaluate # whether they match. If that's the case, the attached # responses are returned one by one. # # @example Stub a request and get specified response. # expected = Typhoeus::Response.new # Typhoeus.stub("www.example.com").and_return(expected) # # actual = Typhoeus.get("www.example.com") # expected == actual # #=> true # # @example Stub a request and get a lazily-constructed response containing data from actual widgets that exist in the system when the stubbed request is made. # Typhoeus.stub("www.example.com/widgets") do # actual_widgets = Widget.all # Typhoeus::Response.new( # :body => actual_widgets.inject([]) do |ids, widget| # ids << widget.id # end.join(",") # ) # end # # @example Stub a request and get a lazily-constructed response in the format requested. # Typhoeus.stub("www.example.com") do |request| # accept = (request.options[:headers]||{})['Accept'] || "application/json" # format = accept.split(",").first # body_obj = { 'things' => [ { 'id' => 'foo' } ] } # # Typhoeus::Response.new( # :headers => { # 'Content-Type' => format # }, # :body => SERIALIZERS[format].serialize(body_obj) # ) # end class Expectation # @api private attr_reader :base_url # @api private attr_reader :options # @api private attr_reader :from class << self # Returns all expectations. # # @example Return expectations. # Typhoeus::Expectation.all # # @return [ Array ] The expectations. def all @expectations ||= [] end # Clears expectations. This is handy while # testing, and you want to make sure that # you don't get canned responses. # # @example Clear expectations. # Typhoeus::Expectation.clear def clear all.clear end # Returns stubbed response matching the # provided request. # # @example Find response # Typhoeus::Expectation.response_for(request) # # @return [ Typhoeus::Response ] The stubbed response from a # matching expectation, or nil if no matching expectation # is found. # # @api private def response_for(request) expectation = find_by(request) return nil if expectation.nil? expectation.response(request) end # @api private def find_by(request) all.find do |expectation| expectation.matches?(request) end end end # Creates an expectation. # # @example Create expectation. # Typhoeus::Expectation.new(base_url) # # @return [ Expectation ] The created expectation. # # @api private def initialize(base_url, options = {}) @base_url = base_url @options = options @response_counter = 0 @from = nil end # Set from value to mark an expectaion. Useful for # other libraries, e.g. WebMock. # # @example Mark expectation. # expectation.from(:webmock) # # @param [ String ] value Value to set. # # @return [ Expectation ] Returns self. # # @api private def stubbed_from(value) @from = value self end # Specify what should be returned, # when this expectation is hit. # # @example Add response. # expectation.and_return(response) # # @return [ void ] def and_return(response=nil, &block) responses << (response.nil? ? block : response) end # Checks whether this expectation matches # the provided request. # # @example Check if request matches. # expectation.matches? request # # @param [ Request ] request The request to check. # # @return [ Boolean ] True when matches, else false. # # @api private def matches?(request) url_match?(request.base_url) && options_match?(request) end # Return canned responses. # # @example Return responses. # expectation.responses # # @return [ Array ] The responses. # # @api private def responses @responses ||= [] end # Return the response. When there are # multiple responses, they are returned one # by one. # # @example Return response. # expectation.response # # @return [ Response ] The response. # # @api private def response(request) response = responses.fetch(@response_counter, responses.last) if response.respond_to?(:call) response = response.call(request) end @response_counter += 1 response.mock = @from || true response end private # Check whether the options matches the request options. # I checks options and original options. def options_match?(request) (options ? options.all?{ |k,v| request.original_options[k] == v || request.options[k] == v } : true) end # Check whether the base_url matches the request url. # The base_url can be a string, regex or nil. String and # regexp are checked, nil is always true, else false. # # Nil serves as a placeholder in case you want to match # all urls. def url_match?(request_url) case base_url when String base_url == request_url when Regexp !!request_url.match(base_url) when nil true else false end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra.rb000066400000000000000000000062201214536063700204500ustar00rootroot00000000000000require 'typhoeus/hydra/addable' require 'typhoeus/hydra/before' require 'typhoeus/hydra/cacheable' require 'typhoeus/hydra/block_connection' require 'typhoeus/hydra/memoizable' require 'typhoeus/hydra/queueable' require 'typhoeus/hydra/runnable' require 'typhoeus/hydra/stubbable' module Typhoeus # Hydra manages making parallel HTTP requests. This # is achieved by using libcurls multi interface: # http://curl.haxx.se/libcurl/c/libcurl-multi.html # The benefits are that you don't have to worry running # the requests by yourself. # # Hydra will also handle how many requests you can # make in parallel. Things will get flakey if you # try to make too many requests at the same time. # The built in limit is 200. When more requests than # that are queued up, hydra will save them for later # and start the requests as others are finished. You # can raise or lower the concurrency limit through # the Hydra constructor. # # Regarding the asynchronous behavior of the hydra, # it is important to know that this is completely hidden # from the developer and you are free to apply # whatever technique you want to your code. That should not # conflict with libcurls internal concurrency mechanism. # # @example Use the hydra to do multiple requests. # hydra = Typhoeus::Hydra.new # requests = (0..9).map{ Typhoeus::Request.new("www.example.com") } # requests.each{ |request| hydra.queue(request) } # hydra.run # # @note Callbacks are going to delay the request # execution. class Hydra include Hydra::Addable include Hydra::Runnable include Hydra::Memoizable include Hydra::Cacheable include Hydra::BlockConnection include Hydra::Stubbable include Hydra::Before include Hydra::Queueable # @example Set max_concurrency. # Typhoeus::Hydra.new(max_concurrency: 20) attr_reader :max_concurrency # @api private attr_reader :multi class << self # Returns a memoized hydra instance. # # @example Get a hydra. # Typhoeus::Hydra.hydra # # @return [Typhoeus::Hydra] A new hydra. # # @deprecated This is only for convenience because so # much external code relies on it. def hydra Thread.current[:typhoeus_hydra] ||= new end end # Create a new hydra. All # {http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method Ethon::Multi#initialize} # options are also available. # # @example Create a hydra. # Typhoeus::Hydra.new # # @example Create a hydra with max_concurrency. # Typhoeus::Hydra.new(max_concurrency: 20) # # @param [ Hash ] options The options hash. # # @option options :max_concurrency [ Integer ] Number # of max concurrent connections to create. Default is # 200. # # @see http://rubydoc.info/github/typhoeus/ethon/Ethon/Multi#initialize-instance_method # Ethon::Multi#initialize def initialize(options = {}) @options = options @max_concurrency = @options.fetch(:max_concurrency, 200) @multi = Ethon::Multi.new(options.reject{|k,_| k==:max_concurrency}) end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/000077500000000000000000000000001214536063700201235ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/hydra/addable.rb000066400000000000000000000006621214536063700220300ustar00rootroot00000000000000module Typhoeus class Hydra # This module handles the request adding on # hydra. # # @api private module Addable # Adds request to multi. # # @example Add request. # hydra.add(request) # # @param [ Typhoeus::Request ] request to add. # # @return [ void ] def add(request) multi.add(EasyFactory.new(request, self).get) end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/before.rb000066400000000000000000000014671214536063700217220ustar00rootroot00000000000000module Typhoeus class Hydra # This module provides a way to hook into before # a request gets queued in hydra. This is very powerful # and you should be careful because when you accidently # return a falsy value the request won't be executed. # # @api private module Before # Overrride add in order to execute callbacks in # Typhoeus.before. Will break and return when a # callback returns nil or false. Calls super # otherwise. # # @example Add the request. # hydra.add(request) def add(request) Typhoeus.before.each do |callback| value = callback.call(request) if value.nil? || value == false || value.is_a?(Response) return value end end super end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/block_connection.rb000066400000000000000000000015701214536063700237640ustar00rootroot00000000000000module Typhoeus class Hydra # This module handles the blocked connection request mode on # the hydra side, where only stubbed requests # are allowed. # Connection blocking needs to be turned on: # Typhoeus.configure do |config| # config.block_connection = true # end # # When trying to do real requests a NoStub error # is raised. # # @api private module BlockConnection # Overrides add in order to check before if block connection # is turned on. If thats the case a NoStub error is # raised. # # @example Add the request. # hydra.add(request) # # @param [ Request ] request The request to enqueue. def add(request) if request.blocked? raise Typhoeus::Errors::NoStub.new(request) else super end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/cacheable.rb000066400000000000000000000004021214536063700223330ustar00rootroot00000000000000module Typhoeus class Hydra module Cacheable def add(request) if request.cacheable? && response = Typhoeus::Config.cache.get(request) request.finish(response) else super end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/memoizable.rb000066400000000000000000000024371214536063700226020ustar00rootroot00000000000000module Typhoeus class Hydra # This module handles the GET request memoization # on the hydra side. Memoization needs to be turned # on: # Typhoeus.configure do |config| # config.memoize = true # end # # @api private module Memoizable # Return the memory. # # @example Return the memory. # hydra.memory # # @return [ Hash ] The memory. def memory @memory ||= {} end # Overrides add in order to check before if request # is memoizable and already in memory. If thats the case, # super is not called, instead the response is set and # the on_complete callback called. # # @example Add the request. # hydra.add(request) # # @param [ Request ] request The request to add. # # @return [ Request ] The added request. def add(request) if request.memoizable? && memory.has_key?(request) response = memory[request] request.finish(response, true) else super end end # Overrides run to make sure the memory is cleared after # each run. # # @example Run hydra. # hydra.run def run super memory.clear end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/queueable.rb000066400000000000000000000020411214536063700224150ustar00rootroot00000000000000module Typhoeus class Hydra # This module handles the request queueing on # hydra. # # @api private module Queueable # Return the queued requests. # # @example Return queued requests. # hydra.queued_requests # # @return [ Array ] The queued requests. def queued_requests @queued_requests ||= [] end # Abort the current hydra run as good as # possible. This means that it only # clears the queued requests and can't do # anything about already running requests. # # @example Abort hydra. # hydra.abort def abort queued_requests.clear end # Enqueues a request in order to be performed # by the hydra. This can even be done while # the hydra is running. Also sets hydra on # request. # # @example Queue request. # hydra.queue(request) def queue(request) request.hydra = self queued_requests << request end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/runnable.rb000066400000000000000000000011131214536063700222520ustar00rootroot00000000000000module Typhoeus class Hydra # This module contains logic to run a hydra. module Runnable # Start the hydra run. # # @example Start hydra run. # hydra.run # # @return [ Symbol ] Return value from multi.perform. def run number_requests = 0 loop do break if number_requests == max_concurrency || queued_requests.empty? number_requests += queued_requests.pop(max_concurrency).map do |request| add(request) end.size end multi.perform end end end end ruby-typhoeus-0.6.3/lib/typhoeus/hydra/stubbable.rb000066400000000000000000000012711214536063700224140ustar00rootroot00000000000000module Typhoeus class Hydra # This module handles stubbing on the hydra side. # It plays well with the block_connection configuration, # which raises when you make a request which is not stubbed. # # @api private module Stubbable # Override add in order to check for matching expecations. # When an expecation is found, super is not called. Instead a # canned response is assigned to the request. # # @example Add the request. # hydra.add(request) def add(request) if response = Expectation.response_for(request) request.finish(response) else super end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/pool.rb000066400000000000000000000021241214536063700203110ustar00rootroot00000000000000require 'thread' module Typhoeus # The easy pool stores already initialized # easy handles for future use. This is useful # because creating them is quite expensive. # # @api private module Pool extend self @mutex = Mutex.new # Releases easy into the pool. The easy handle is # reset before it gets back in. # # @example Release easy. # hydra.release_easy(easy) def release(easy) easy.reset @mutex.synchronize { easies << easy } end # Return an easy from the pool. # # @example Return easy. # hydra.get_easy # # @return [ Ethon::Easy ] The easy. def get @mutex.synchronize { easies.pop } || Ethon::Easy.new end def clear @mutex.synchronize { easies.clear } end def with_easy(&block) easy = get yield easy ensure release(easy) if easy end private # Return the easy pool. # # @example Return easy pool. # hydra.easy_pool # # @return [ Array ] The easy pool. def easies @easies ||= [] end end end ruby-typhoeus-0.6.3/lib/typhoeus/railtie.rb000066400000000000000000000004471214536063700207770ustar00rootroot00000000000000require "typhoeus" module Rails module Typhoeus class Railtie < Rails::Railtie # Need to include the Typhoeus middleware. initializer "include the identity map" do |app| app.config.middleware.use "Rack::Typhoeus::Middleware::ParamsDecoder" end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request.rb000066400000000000000000000116071214536063700210360ustar00rootroot00000000000000require '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/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::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 EasyFactory.new(self).get.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 Digest::MD5.hexdigest("#{self.class.name}#{base_url}#{options}").to_i(16) 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 # Sets default header and verbose when turned on. def set_defaults if @options[:headers] @options[:headers] = {'User-Agent' => Typhoeus::USER_AGENT}.merge(options[:headers]) else @options[:headers] = {'User-Agent' => Typhoeus::USER_AGENT} end @options[:verbose] = Typhoeus::Config.verbose if @options[:verbose].nil? && !Typhoeus::Config.verbose.nil? end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/000077500000000000000000000000001214536063700205045ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/request/actions.rb000066400000000000000000000070261214536063700224760ustar00rootroot00000000000000module Typhoeus class Request # Module containing logic about shortcuts to # http methods. Like # Typhoeus.get("www.example.com") module Actions # Make a get request. # # @example Make get request. # Typhoeus.get("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def get(base_url, options = {}) Request.new(base_url, options.merge(:method => :get)).run end # Make a post request. # # @example Make post request. # Typhoeus.post("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def post(base_url, options = {}) Request.new(base_url, options.merge(:method => :post)).run end # Make a put request. # # @example Make put request. # Typhoeus.put("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option options :params [ Hash ] Params hash which # is attached to the base_url. # @option options :body [ Hash ] Body hash which # becomes a PUT request body. # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def put(base_url, options = {}) Request.new(base_url, options.merge(:method => :put)).run end # Make a delete request. # # @example Make delete request. # Typhoeus.delete("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def delete(base_url, options = {}) Request.new(base_url, options.merge(:method => :delete)).run end # Make a head request. # # @example Make head request. # Typhoeus.head("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def head(base_url, options = {}) Request.new(base_url, options.merge(:method => :head)).run end # Make a patch request. # # @example Make patch request. # Typhoeus.patch("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def patch(base_url, options = {}) Request.new(base_url, options.merge(:method => :patch)).run end # Make a options request. # # @example Make options request. # Typhoeus.options("www.example.com") # # @param (see Typhoeus::Request#initialize) # # @option (see Typhoeus::Request#initialize) # # @return (see Typhoeus::Request#initialize) # # @note (see Typhoeus::Request#initialize) def options(base_url, options = {}) Request.new(base_url, options.merge(:method => :options)).run end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/before.rb000066400000000000000000000014311214536063700222720ustar00rootroot00000000000000module Typhoeus class Request # This module provides a way to hook into before # a request runs. This is very powerful # and you should be careful because when you accidently # return a falsy value the request won't be executed. # # @api private module Before # Overrride run in order to execute callbacks in # Typhoeus.before. Will break and return when a # callback returns nil or false. Calls super # otherwise. # # @example Run the request. # request.run def run Typhoeus.before.each do |callback| value = callback.call(self) if value.nil? || value == false || value.is_a?(Response) return response end end super end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/block_connection.rb000066400000000000000000000024761214536063700243530ustar00rootroot00000000000000module Typhoeus class Request # This module handles the blocked connection request mode on # the request side, where only stubbed requests # are allowed. # Connection blocking needs to be turned on: # Typhoeus.configure do |config| # config.block_connection = true # end # # When trying to do real requests a NoStub error # is raised. # # @api private module BlockConnection # Overrides run in order to check before if block connection # is turned on. If thats the case a NoStub error is # raised. # # @example Run request. # request.run # # @raise [Typhoeus::Errors::NoStub] If connection is blocked # and no stub defined. def run if blocked? raise Typhoeus::Errors::NoStub.new(self) else super end end # Returns wether a request is blocked or not. Takes # request.block_connection and Typhoeus::Config.block_connection # into consideration. # # @example Blocked? # request.blocked? # # @return [ Boolean ] True if blocked, false else. def blocked? if block_connection.nil? Typhoeus::Config.block_connection else block_connection end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/cacheable.rb000066400000000000000000000007321214536063700227220ustar00rootroot00000000000000module Typhoeus class Request module Cacheable def response=(response) Typhoeus::Config.cache.set(self, response) if cacheable? super end def cacheable? Typhoeus::Config.cache end def run if cacheable? && response = Typhoeus::Config.cache.get(self) finish(response) else super end end def cache_ttl options[:cache_ttl] end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/callbacks.rb000066400000000000000000000056051214536063700227560ustar00rootroot00000000000000module Typhoeus class Request # This module contains the logic for the response callbacks. # The on_complete callback is the only one at the moment. # # You can set multiple callbacks, which are then executed # in the same order. # # request.on_complete { |response| p 1 } # request.on_complete { |response| p 2 } # request.execute_callbacks # #=> 1 # #=> 2 # # You can clear the callbacks: # # request.on_complete { |response| p 1 } # request.on_complete { |response| p 2 } # request.on_complete.clear # request.execute_callbacks # #=> [] # # @note If you're using the Hydra to execute multiple # requests, then callbacks are delaying the # request execution. module Callbacks module Types # :nodoc: # Set on_complete callback. # # @example Set on_complete. # request.on_complete { |response| p "yay" } # # @param [ Block ] block The block to execute. # # @yield [ Typhoeus::Response ] # # @return [ Array ] All on_complete blocks. def on_complete(&block) @on_complete ||= [] @on_complete << block if block_given? @on_complete end # Set on_success callback. # # @example Set on_success. # request.on_success { |response| p "yay" } # # @param [ Block ] block The block to execute. # # @yield [ Typhoeus::Response ] # # @return [ Array ] All on_success blocks. def on_success(&block) @on_success ||= [] @on_success << block if block_given? @on_success end # Set on_failure callback. # # @example Set on_failure. # request.on_failure { |response| p "yay" } # # @param [ Block ] block The block to execute. # # @yield [ Typhoeus::Response ] # # @return [ Array ] All on_failure blocks. def on_failure(&block) @on_failure ||= [] @on_failure << block if block_given? @on_failure end end # Execute nessecary callback and yields response. This # include in every case on_complete, on_success if # successful and on_failure if not. # # @example Execute callbacks. # request.execute_callbacks # # @return [ void ] # # @api private def execute_callbacks callbacks = Typhoeus.on_complete + on_complete if response && response.success? callbacks += Typhoeus.on_success + on_success elsif response callbacks += Typhoeus.on_failure + on_failure end callbacks.map do |callback| self.response.handled_response = callback.call(self.response) end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/marshal.rb000066400000000000000000000010651214536063700224620ustar00rootroot00000000000000module Typhoeus class Request # This module contains custom serializer. module Marshal # Return the important data needed to serialize this Request, except the # `on_complete` handler, since they cannot be marshalled. def marshal_dump (instance_variables - ['@on_complete', :@on_complete]).map do |name| [name, instance_variable_get(name)] end end # Load. def marshal_load(attributes) attributes.each { |name, value| instance_variable_set(name, value) } end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/memoizable.rb000066400000000000000000000017231214536063700231600ustar00rootroot00000000000000module Typhoeus class Request # This module handles the GET request memoization # on the request side. Memoization needs to be turned # on: # Typhoeus.configure do |config| # config.memoize = true # end # # @api private module Memoizable # Override response setter and memoizes response # if the request is memoizable. # # @param [ Response ] response The response to set. # # @example Set response. # request.response = response def response=(response) hydra.memory[self] = response if memoizable? super end # Return whether a request is memoizable. # # @example Is request memoizable? # request.memoizable? # # @return [ Boolean ] Return true if memoizable, false else. def memoizable? Typhoeus::Config.memoize && (options[:method].nil? || options[:method] == :get) end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/operations.rb000066400000000000000000000020151214536063700232120ustar00rootroot00000000000000module Typhoeus class Request # This module contains everything what is necessary # to make a single request. module Operations # Run a request. # # @example Run a request. # Typhoeus::Request.new("www.example.com").run # # @return [ Response ] The response. def run easy = EasyFactory.new(self).get easy.perform response end # Sets a response, the request on the response # and executes the callbacks. # # @param [Typhoeus::Response] response The response. # @param [Boolean] bypass_memoization Wether to bypass # memoization or not. Decides how the response is set. # # @return [Typhoeus::Response] The response. def finish(response, bypass_memoization = nil) if bypass_memoization @response = response else self.response = response end self.response.request = self execute_callbacks response end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/responseable.rb000066400000000000000000000011141214536063700235100ustar00rootroot00000000000000module Typhoeus class Request # This module contains logic for having a reponse # getter and setter. module Responseable # Set the response. # # @example Set response. # request.response = response # # @param [ Response ] value The response to set. def response=(value) @response = value end # Return the response. # # @example Return response. # request.response # # @return [ Response ] The response. def response @response ||= nil end end end end ruby-typhoeus-0.6.3/lib/typhoeus/request/stubbable.rb000066400000000000000000000013251214536063700227750ustar00rootroot00000000000000module Typhoeus class Request # This module handles stubbing on the request side. # It plays well with the block_connection configuration, # which raises when you make a request which is not stubbed. # # @api private module Stubbable # Override run in order to check for matching expecations. # When an expecation is found, super is not called. Instead a # canned response is assigned to the request. # # @example Run the request. # request.run # # @return [ Response ] The response. def run if response = Expectation.response_for(self) finish(response) else super end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/response.rb000066400000000000000000000030271214536063700212010ustar00rootroot00000000000000require 'typhoeus/response/header' require 'typhoeus/response/informations' require 'typhoeus/response/status' module Typhoeus # This class represents the response. class Response include Response::Informations include Response::Status # Remembers the corresponding request. # # @example Get request. # request = Typhoeus::Request.get("www.example.com") # response = request.run # request == response.request # #=> true # # @return [ Typhoeus::Request ] attr_accessor :request # The provided options, which contain all the # informations about the request. # # @return [ Hash ] attr_accessor :options # Set the handled response. attr_writer :handled_response # @api private attr_writer :mock # Create a new response. # # @example Create a response. # Response.new # # @param [ Hash ] options The options hash. # # @return [ Response ] The new response. def initialize(options = {}) @options = options @headers = Header.new(options[:headers]) if options[:headers] end # Returns whether this request is mocked # or not. # # @api private def mock defined?(@mock) ? @mock : options[:mock] end # Returns the handled_response if it has # been defined; otherwise, returns the response # # @return [ Object ] The result of callbacks # done on the response or the original response. def handled_response @handled_response || self end end end ruby-typhoeus-0.6.3/lib/typhoeus/response/000077500000000000000000000000001214536063700206525ustar00rootroot00000000000000ruby-typhoeus-0.6.3/lib/typhoeus/response/header.rb000066400000000000000000000042701214536063700224320ustar00rootroot00000000000000module Typhoeus class Response # This class represents the response header. # It can be accessed like a hash. # # @api private class Header < Hash # Create a new header. # # @example Create new header. # Header.new(raw) # # @param [ String ] raw The raw header. def initialize(raw) @raw = raw @sanitized = {} parse set_default_proc_on(self, lambda { |h, k| @sanitized[k.to_s.downcase] }) end # Parses the raw header. # # @example Parse header. # header.parse def parse case @raw when Hash raw.each do |k, v| process_pair(k, v) end when String raw.lines.each do |header| next if header.empty? || header =~ /^HTTP\/1.[01]/ process_line(header) end end end private # Processes line and saves the result. # # @return [ void ] def process_line(header) key, value = header.split(':', 2).map(&:strip) process_pair(key, value) end # Sets key value pair for self and @sanitized. # # @return [ void ] def process_pair(key, value) set_value(key, value, self) set_value(key.downcase, value, @sanitized) end # Sets value for key in specified hash # # @return [ void ] def set_value(key, value, hash) if hash.has_key?(key) hash[key] = [hash[key]] unless hash[key].is_a? Array hash[key].push(value) else hash[key] = value end end # Returns the raw header or empty string. # # @example Return raw header. # header.raw # # @return [ String ] The raw header. def raw @raw || '' end # Sets the default proc for the specified hash independent of the Ruby version. # # @return [ void ] def set_default_proc_on(hash, default_proc) if hash.respond_to?(:default_proc=) hash.default_proc = default_proc else hash.replace(Hash.new(&default_proc).merge(hash)) end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/response/informations.rb000066400000000000000000000145641214536063700237210ustar00rootroot00000000000000module Typhoeus class Response # This module contains logic about informations # on a response. module Informations # Return libcurls return value. # # @example Get return_code. # response.return_code # # @return [ Symbol ] The return_code. def return_code options[:return_code] end # Returns a string describing the return. # # @example Get return_message. # response.return_message # # @return [ String ] The return_message. # # @since 0.6.2 def return_message Ethon::Curl.easy_strerror(return_code) end # Return the http response body. # # @example Get response_body. # response.response_body # # @return [ String ] The response_body. def response_body options[:response_body] || options[:body] end alias :body :response_body # Return the http response headers. # # @example Get response_headers. # response.response_headers # # @return [ String ] The response_headers. def response_headers options[:response_headers] end # Return the last received HTTP, FTP or SMTP response code. # The value will be zero if no server response code has # been received. Note that a proxy's CONNECT response should # be read with http_connect_code and not this. # # @example Get response_code. # response.response_code # # @return [ Integer ] The response_code. def response_code (options[:response_code] || options[:code]).to_i end alias :code :response_code # Return the available http auth methods. # Bitmask indicating the authentication method(s) # available. # # @example Get httpauth_avail. # response.httpauth_avail # # @return [ Integer ] The bitmask. def httpauth_avail options[:httpauth_avail] end # Return the total time in seconds for the previous # transfer, including name resolving, TCP connect etc. # # @example Get total_time. # response.total_time # # @return [ Float ] The total_time. def total_time options[:total_time] || options[:time] end alias :time :total_time # Return the time, in seconds, it took from the start # until the first byte is received by libcurl. This # includes pretransfer time and also the time the # server needs to calculate the result. # # @example Get starttransfer_time. # response.starttransfer_time # # @return [ Float ] The starttransfer_time. def starttransfer_time options[:starttransfer_time] || options[:start_transfer_time] end alias :start_transfer_time :starttransfer_time # Return the time, in seconds, it took from the start # until the SSL/SSH connect/handshake to the remote # host was completed. This time is most often very near # to the pre transfer time, except for cases such as HTTP # pippelining where the pretransfer time can be delayed # due to waits in line for the pipeline and more. # # @example Get appconnect_time. # response.appconnect_time # # @return [ Float ] The appconnect_time. def appconnect_time options[:appconnect_time] || options[:app_connect_time] end alias :app_connect_time :appconnect_time # Return the time, in seconds, it took from the start # until the file transfer is just about to begin. This # includes all pre-transfer commands and negotiations # that are specific to the particular protocol(s) involved. # It does not involve the sending of the protocol- # specific request that triggers a transfer. # # @example Get pretransfer_time. # response.pretransfer_time # # @return [ Float ] The pretransfer_time. def pretransfer_time options[:pretransfer_time] end # Return the time, in seconds, it took from the start # until the connect to the remote host (or proxy) was completed. # # @example Get connect_time. # response.connect_time # # @return [ Float ] The connect_time. def connect_time options[:connect_time] end # Return the time, in seconds, it took from the # start until the name resolving was completed. # # @example Get namelookup_time. # response.namelookup_time # # @return [ Float ] The namelookup_time. def namelookup_time options[:namelookup_time] || options[:name_lookup_time] end alias :name_lookup_time :namelookup_time # Return the last used effective url. # # @example Get effective_url. # response.effective_url # # @return [ String ] The effective_url. def effective_url options[:effective_url] end # Return the string holding the IP address of the most recent # connection done with this curl handle. This string # may be IPv6 if that's enabled. # # @example Get primary_ip. # response.primary_ip # # @return [ String ] The primary_ip. def primary_ip options[:primary_ip] end # Return the total number of redirections that were # actually followed # # @example Get redirect_count. # response.redirect_count # # @return [ Integer ] The redirect_count. def redirect_count options[:redirect_count] end # Returns the response header. # # @example Return headers. # response.headers # # @return [ Typhoeus::Header ] The response header. def headers return nil if response_headers.nil? && !defined?(@headers) @headers ||= Response::Header.new(response_headers.split("\r\n\r\n").last) end alias :headers_hash :headers # Return all redirections in between as multiple # responses with header. # # @example Return redirections. # response.redirections # # @return [ Array ] The redirections def redirections return [] unless response_headers response_headers.split("\r\n\r\n")[0..-2].map{ |h| Response.new(:response_headers => h) } end end end end ruby-typhoeus-0.6.3/lib/typhoeus/response/status.rb000066400000000000000000000053661214536063700225340ustar00rootroot00000000000000module Typhoeus class Response # This module contains logic about the http # status. module Status # Return the status message if present. # # @example Return status message. # reesponse.status_message # # @return [ String ] The message. def status_message return @status_message if defined?(@status_message) && @status_message return options[:status_message] unless options[:status_message].nil? # HTTP servers can choose not to include the explanation to HTTP codes. The RFC # states this (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4): # Except when responding to a HEAD request, the server SHOULD include an entity containing # an explanation of the error situation [...] # This means 'HTTP/1.1 404' is as valid as 'HTTP/1.1 404 Not Found' and we have to handle it. # # Regexp doc: http://rubular.com/r/eAr1oVYsVa if first_header_line != nil and first_header_line[/\d{3} (.*)$/, 1] != nil @status_message = first_header_line[/\d{3} (.*)$/, 1].chomp else @status_message = nil end end # Return the http version. # # @example Return http version. # response.http_version # # @return [ String ] The http version. def http_version @http_version ||= first_header_line ? first_header_line[/HTTP\/(\S+)/, 1] : nil end # Return wether the response is a success. # # @example Return if the response was successful. # response.success? # # @return [ Boolean ] Return true if successful, false else. def success? (mock || return_code == :ok) && response_code && response_code >= 200 && response_code < 300 end # Return wether the response is modified. # # @example Return if the response was modified. # response.modified? # # @return [ Boolean ] Return true if modified, false else. def modified? (mock || return_code == :ok) && response_code && response_code != 304 end # Return wether the response is timed out. # # @example Return if the response timed out. # response.timed_out? # # @return [ Boolean ] Return true if timed out, false else. def timed_out? [:operation_timedout, :couldnt_connect].include?(return_code) end private # :nodoc: def first_header_line @first_header_line ||= begin if response_headers.to_s.include?("\r\n\r\n") response_headers.to_s.split("\r\n\r\n").last.split("\r\n").first else response_headers.to_s.split("\r\n").first end end end end end end ruby-typhoeus-0.6.3/lib/typhoeus/version.rb000066400000000000000000000001131214536063700210210ustar00rootroot00000000000000module Typhoeus # The current Typhoeus version. VERSION = '0.6.3' end ruby-typhoeus-0.6.3/perf/000077500000000000000000000000001214536063700153225ustar00rootroot00000000000000ruby-typhoeus-0.6.3/perf/profile.rb000066400000000000000000000004011214536063700173020ustar00rootroot00000000000000require 'typhoeus' require 'ruby-prof' calls = 50 base_url = "http://127.0.0.1:3000/" RubyProf.start calls.times do |i| Typhoeus::Request.get(base_url+i.to_s) end result = RubyProf.stop printer = RubyProf::FlatPrinter.new(result) printer.print(STDOUT) ruby-typhoeus-0.6.3/perf/vs_nethttp.rb000066400000000000000000000025721214536063700200530ustar00rootroot00000000000000require 'typhoeus' require 'net/http' require 'open-uri' require 'benchmark' URL = "http://localhost:300" hydra = Typhoeus::Hydra.new(max_concurrency: 3) if defined? require_relative require_relative '../spec/support/localhost_server.rb' require_relative '../spec/support/server.rb' else require '../spec/support/localhost_server.rb' require '../spec/support/server.rb' end LocalhostServer.new(TESTSERVER.new, 3000) LocalhostServer.new(TESTSERVER.new, 3001) LocalhostServer.new(TESTSERVER.new, 3002) def url_for(i) "#{URL}#{i%3}/" end Benchmark.bm do |bm| [1000].each do |calls| puts "[ #{calls} requests ]" bm.report("net/http ") do calls.times do |i| uri = URI.parse(url_for(i)) Net::HTTP.get_response(uri) end end bm.report("open ") do calls.times do |i| open(url_for(i)) end end bm.report("request ") do calls.times do |i| Typhoeus::Request.get(url_for(i)) end end bm.report("hydra ") do calls.times do |i| hydra.queue(Typhoeus::Request.new(url_for(i))) end hydra.run end bm.report("hydra memoize ") do Typhoeus::Config.memoize = true calls.times do |i| hydra.queue(Typhoeus::Request.new(url_for(i))) end hydra.run Typhoeus::Config.memoize = false end end end ruby-typhoeus-0.6.3/spec/000077500000000000000000000000001214536063700153205ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/rack/000077500000000000000000000000001214536063700162405ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/rack/typhoeus/000077500000000000000000000000001214536063700201205ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/rack/typhoeus/middleware/000077500000000000000000000000001214536063700222355ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/rack/typhoeus/middleware/params_decoder/000077500000000000000000000000001214536063700252055ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/rack/typhoeus/middleware/params_decoder/helper_spec.rb000066400000000000000000000051421214536063700300250ustar00rootroot00000000000000require 'spec_helper' require "rack/typhoeus" describe "Rack::Typhoeus::Middleware::ParamsDecoder::Helper" do let(:klass) do Class.new do include Rack::Typhoeus::Middleware::ParamsDecoder::Helper end.new end describe "#decode" do let(:decoded) { klass.decode(params) } let(:params) { { :array => {'0' => :a, '1' => :b } } } it "decodes" do expect(decoded[:array]).to match_array([:a, :b]) end it "doesn't modify" do expect(decoded).to_not be(params) end end describe "#decode!" do let(:decoded) { klass.decode!(params) } context "when hash" do context "when encoded" do context "when simple" do let(:params) { { :array => {'0' => :a, '1' => :b } } } it "decodes" do expect(decoded[:array]).to match_array([:a, :b]) end it "modifies" do expect(decoded).to eq(params) end end context "when nested" do let(:params) do { :array => { '0' => 0, '1' => { '0' => 'sub0', '1' => 'sub1' } } } end it "decodes" do expect(decoded[:array]).to include(0) expect(decoded[:array].find{|e| e.is_a?(Array)}).to( match_array(['sub0', 'sub1']) ) end it "modifies" do expect(decoded).to eq(params) end end end context "when not encoded" do let(:params) { {:a => :a} } it "doesn't modify" do expect(decoded).to be(params) end end end context "when no hash" do let(:params) { "a" } it "returns self" do expect(decoded).to be(params) end end end describe "#encoded?" do let(:encoded) { klass.send(:encoded?, params) } context "when keys are ascending numbers starting with zero" do let(:params) { Hash[12.times.map {|i| [i, (i+65).chr]}] } it "returns true" do expect(encoded).to be_true end end context "when keys are not ascending numbers starting with zero" do let(:params) { {:a => 1} } it "returns false" do expect(encoded).to be_false end end end describe "#convert" do let(:converted) { klass.send(:convert, params) } context "when encoded" do let(:params) { {'0' => :a, '1' => :b} } it "returns values" do expect(converted).to match_array([:a, :b]) end end context "when not encoded" do let(:params) { {:a => :a} } it "returns unmodified" do expect(converted).to be(params) end end end end ruby-typhoeus-0.6.3/spec/rack/typhoeus/middleware/params_decoder_spec.rb000066400000000000000000000010201214536063700265350ustar00rootroot00000000000000require 'spec_helper' describe "Rack::Typhoeus::Middleware::ParamsDecoder" do before(:all) do require "rack/typhoeus" end let(:app) do stub end let(:env) do stub end let(:klass) do Rack::Typhoeus::Middleware::ParamsDecoder end describe "#call" do end context "when requesting" do let(:response) { Typhoeus.get("localhost:3001", :params => {:x => [:a]}) } it "transforms parameters" do expect(response.body).to include("query_hash\":{\"x\":[\"a\"]}") end end end ruby-typhoeus-0.6.3/spec/spec_helper.rb000066400000000000000000000014311214536063700201350ustar00rootroot00000000000000$LOAD_PATH.unshift(File.dirname(__FILE__)) $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "..", "lib")) require "bundler" Bundler.setup require "typhoeus" require "rspec" if defined? require_relative require_relative 'support/localhost_server.rb' require_relative 'support/server.rb' else require 'support/localhost_server.rb' require 'support/server.rb' end RSpec.configure do |config| config.order = :rand config.before(:suite) do LocalhostServer.new(TESTSERVER.new, 3001) end config.after do Typhoeus::Pool.clear Typhoeus::Expectation.clear Typhoeus.before.clear Typhoeus.on_complete.clear Typhoeus.on_success.clear Typhoeus.on_failure.clear Typhoeus::Config.verbose = false Typhoeus::Config.block_connection = false end end ruby-typhoeus-0.6.3/spec/support/000077500000000000000000000000001214536063700170345ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/support/localhost_server.rb000066400000000000000000000043571214536063700227500ustar00rootroot00000000000000require 'rack' require 'rack/handler/webrick' require 'net/http' # The code for this is inspired by Capybara's server: # http://github.com/jnicklas/capybara/blob/0.3.9/lib/capybara/server.rb class LocalhostServer READY_MESSAGE = "Server ready" class Identify def initialize(app) @app = app end def call(env) if env["PATH_INFO"] == "/__identify__" [200, {}, [LocalhostServer::READY_MESSAGE]] else @app.call(env) end end end attr_reader :port def initialize(rack_app, port = nil) @port = port || find_available_port @rack_app = rack_app concurrently { boot } wait_until(10, "Boot failed.") { booted? } end private def find_available_port server = TCPServer.new('127.0.0.1', 0) server.addr[1] ensure server.close if server end def boot # Use WEBrick since it's part of the ruby standard library and is available on all ruby interpreters. options = { :Port => port } options.merge!(:AccessLog => [], :Logger => WEBrick::BasicLog.new(StringIO.new)) unless ENV['VERBOSE_SERVER'] Rack::Handler::WEBrick.run(Identify.new(@rack_app), options) end def booted? res = ::Net::HTTP.get_response("localhost", '/__identify__', port) if res.is_a?(::Net::HTTPSuccess) or res.is_a?(::Net::HTTPRedirection) return res.body == READY_MESSAGE end rescue Errno::ECONNREFUSED, Errno::EBADF return false end def concurrently if should_use_subprocess? pid = Process.fork do trap(:INT) { ::Rack::Handler::WEBrick.shutdown } yield exit # manually exit; otherwise this sub-process will re-run the specs that haven't run yet. end at_exit do Process.kill('INT', pid) begin Process.wait(pid) rescue Errno::ECHILD # ignore this error...I think it means the child process has already exited. end end else Thread.new { yield } end end def should_use_subprocess? # !ENV['THREADED'] false end def wait_until(timeout, error_message, &block) start_time = Time.now while true return if yield raise TimeoutError.new(error_message) if (Time.now - start_time) > timeout sleep(0.05) end end end ruby-typhoeus-0.6.3/spec/support/server.rb000066400000000000000000000052261214536063700206740ustar00rootroot00000000000000#!/usr/bin/env ruby require 'json' require 'zlib' require 'sinatra/base' require 'rack/typhoeus' TESTSERVER = Sinatra.new do set :logging, false use Rack::Typhoeus::Middleware::ParamsDecoder fail_count = 0 post '/file' do { 'content-type' => params[:file][:type], 'filename' => params[:file][:filename], 'content' => params[:file][:tempfile].read, 'request-content-type' => request.env['CONTENT_TYPE'] }.to_json end get '/multiple-headers' do [200, { 'Set-Cookie' => %w[ foo bar ], 'Content-Type' => 'text/plain' }, ['']] end get '/fail/:number' do if fail_count >= params[:number].to_i "ok" else fail_count += 1 error 500, "oh noes!" end end get '/fail_forever' do error 500, "oh noes!" end get '/redirect' do redirect '/' end get '/bad_redirect' do redirect '/bad_redirect' end get '/auth_basic/:username/:password' do @auth ||= Rack::Auth::Basic::Request.new(request.env) # Check that we've got a basic auth, and that it's credentials match the ones # provided in the request if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ] # auth is valid - confirm it true else # invalid auth - request the authentication response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth") throw(:halt, [401, "Not authorized\n"]) end end get '/auth_ntlm' do # we're just checking for the existence if NTLM auth header here. It's validation # is too troublesome and really doesn't bother is much, it's up to libcurl to make # it valid response['WWW-Authenticate'] = 'NTLM' is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION'] true if is_ntlm_auth throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth end get '/gzipped' do req_env = request.env.to_json z = Zlib::Deflate.new gzipped_env = z.deflate(req_env, Zlib::FINISH) z.close response['Content-Encoding'] = 'gzip' gzipped_env end get '/**' do sleep params["delay"].to_i if params.has_key?("delay") request.env.merge!(:body => request.body.read).to_json end head '/**' do sleep params["delay"].to_i if params.has_key?("delay") end put '/**' do request.env.merge!(:body => request.body.read).to_json end post '/**' do request.env.merge!(:body => request.body.read).to_json end delete '/**' do request.env.merge!(:body => request.body.read).to_json end patch '/**' do request.env.merge!(:body => request.body.read).to_json end options '/**' do request.env.merge!(:body => request.body.read).to_json end end ruby-typhoeus-0.6.3/spec/typhoeus/000077500000000000000000000000001214536063700172005ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/adapters/000077500000000000000000000000001214536063700210035ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/adapters/faraday_spec.rb000066400000000000000000000127131214536063700237550ustar00rootroot00000000000000require 'spec_helper' require 'typhoeus/adapters/faraday' describe Faraday::Adapter::Typhoeus do let(:base_url) { "http://localhost:3001" } let(:adapter) { described_class.new } let(:request) { Typhoeus::Request.new(base_url) } let(:conn) do Faraday.new(:url => base_url) do |faraday| faraday.adapter :typhoeus end end let(:response) { conn.get("/") } context "when parallel" do it "returns a faraday response" do response = nil conn.in_parallel { response = conn.get("/") } expect(response).to be_a(Faraday::Response) end it "succeeds" do response = nil conn.in_parallel { response = conn.get("/") } expect(response.status).to be(200) end end context "when not parallel" do it "returns a faraday response" do expect(response).to be_a(Faraday::Response) end it "succeeds" do expect(response.status).to be(200) end end describe "#perform_request" do let(:env) { {} } context "when body" do let(:env) { { :body => stub(:read => "body") } } it "reads body" do expect(adapter.method(:read_body).call(env)).to eq("body") end end context "parallel_manager" do context "when given" do let(:env) { { :parallel_manager => stub(:queue => true), :ssl => {}, :request => {} } } it "uses" do adapter.method(:perform_request).call(env) end end context "when not given" do let(:env) { { :method => :get, :ssl => {}, :request => {} } } it "falls back to single" do Typhoeus::Request.should_receive(:new).and_return(stub(:options => {}, :on_complete => [], :run => true)) adapter.method(:perform_request).call(env) end end end end describe "#request" do let(:env) do { :url => "url", :method => :get, :body => "body", :request_headers => {}, :ssl => {}, :request => {} } end let(:request) { adapter.method(:request).call(env) } it "returns request" do expect(request).to be_a(Typhoeus::Request) end it "sets url" do expect(request.base_url).to eq("url") end it "sets http method" do expect(request.original_options[:method]).to eq(:get) end it "sets body" do expect(request.original_options[:body]).to eq("body") end it "sets headers" do expect(request.original_options[:headers]).to eq({}) end it "sets on_complete callback" do expect(request.on_complete).to have(1).items end end describe "#configure_socket" do let(:env) { { :request => { :bind => { :host => "interface" } } } } before { adapter.method(:configure_socket).call(request, env) } context "when host" do it "sets interface" do expect(request.options[:interface]).to eq("interface") end end end describe "#configure_timeout" do before { adapter.method(:configure_timeout).call(request, env) } context "when timeout" do let(:env) { { :request => { :timeout => 1 } } } it "sets timeout_ms" do expect(request.options[:timeout_ms]).to eq(1000) end end context "when open_timeout" do let(:env) { { :request => { :open_timeout => 1 } } } it "sets connecttimeout_ms" do expect(request.options[:connecttimeout_ms]).to eq(1000) end end end describe "#configure_proxy" do before { adapter.method(:configure_proxy).call(request, env) } context "when proxy" do let(:env) { { :request => { :proxy => { :uri => stub(:host => "localhost", :port => "3001") } } } } it "sets proxy" do expect(request.options[:proxy]).to eq("localhost:3001") end context "when username and password" do let(:env) do { :request => { :proxy => { :uri => stub(:host => :a, :port => :b), :username => "a", :password => "b" } } } end it "sets proxyuserpwd" do expect(request.options[:proxyuserpwd]).to eq("a:b") end end end end describe "#configure_ssl" do before { adapter.method(:configure_ssl).call(request, env) } context "when version" do let(:env) { { :ssl => { :version => "a" } } } it "sets sslversion" do expect(request.options[:sslversion]).to eq("a") end end context "when client_cert" do let(:env) { { :ssl => { :client_cert => "a" } } } it "sets sslcert" do expect(request.options[:sslcert]).to eq("a") end end context "when client_key" do let(:env) { { :ssl => { :client_key => "a" } } } it "sets sslkey" do expect(request.options[:sslkey]).to eq("a") end end context "when ca_file" do let(:env) { { :ssl => { :ca_file => "a" } } } it "sets cainfo" do expect(request.options[:cainfo]).to eq("a") end end context "when ca_path" do let(:env) { { :ssl => { :ca_path => "a" } } } it "sets capath" do expect(request.options[:capath]).to eq("a") end end end describe "#parallel?" do context "when parallel_manager" do let(:env) { { :parallel_manager => true } } it "returns true" do expect(adapter.method(:parallel?).call(env)).to be_true end end context "when no parallel_manager" do let(:env) { { :parallel_manager => nil } } it "returns false" do expect(adapter.method(:parallel?).call(env)).to be_false end end end end ruby-typhoeus-0.6.3/spec/typhoeus/config_spec.rb000066400000000000000000000005161214536063700220060ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Config do let(:config) { Typhoeus::Config } [:block_connection, :memoize, :verbose, :cache].each do |name| it "responds to #{name}" do expect(config).to respond_to(name) end it "responds to #{name}=" do expect(config).to respond_to("#{name}=") end end end ruby-typhoeus-0.6.3/spec/typhoeus/easy_factory_spec.rb000066400000000000000000000026571214536063700232410ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::EasyFactory do let(:base_url) { "http://localhost:3001" } let(:hydra) { Typhoeus::Hydra.new(:max_concurrency => 0) } let(:options) { {} } let(:request) { Typhoeus::Request.new(base_url, options) } let(:easy_factory) { described_class.new(request, hydra) } describe "#get" do context "when option[:cache_ttl]" do let(:options) { {:cache_ttl => 1} } it "creates Ethon::Easy" do expect(easy_factory.get).to be_a(Ethon::Easy) end end end describe "#set_callback" do it "sets easy.on_complete callback" do easy_factory.easy.should_receive(:on_complete) easy_factory.send(:set_callback) end it "finishes request" do easy_factory.send(:set_callback) request.should_receive(:finish) easy_factory.easy.complete end it "resets easy" do easy_factory.send(:set_callback) easy_factory.easy.should_receive(:reset) easy_factory.easy.complete end it "pushes easy back into the pool" do easy_factory.send(:set_callback) easy_factory.easy.complete expect(Typhoeus::Pool.send(:easies)).to include(easy_factory.easy) end it "adds next request" do easy_factory.hydra.instance_variable_set(:@queued_requests, [request]) easy_factory.hydra.should_receive(:add).with(request) easy_factory.send(:set_callback) easy_factory.easy.complete end end end ruby-typhoeus-0.6.3/spec/typhoeus/errors/000077500000000000000000000000001214536063700205145ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/errors/no_stub_spec.rb000066400000000000000000000006101214536063700235210ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Errors::NoStub do let(:base_url) { "localhost:3001" } let(:request) { Typhoeus::Request.new(base_url) } let(:message) { "The connection is blocked and no stub defined: " } subject { Typhoeus::Errors::NoStub } it "displays the request url" do expect { raise subject.new(request) }.to raise_error(subject, message + base_url) end end ruby-typhoeus-0.6.3/spec/typhoeus/expectation_spec.rb000066400000000000000000000156521214536063700230730ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Expectation do let(:options) { {} } let(:base_url) { "www.example.com" } let(:expectation) { described_class.new(base_url, options) } describe ".new" do it "sets base_url" do expect(expectation.instance_variable_get(:@base_url)).to eq(base_url) end it "sets options" do expect(expectation.instance_variable_get(:@options)).to eq(options) end it "initializes response_counter" do expect(expectation.instance_variable_get(:@response_counter)).to eq(0) end end describe ".all" do context "when @expectations nil" do it "returns empty array" do expect(Typhoeus::Expectation.all).to eq([]) end end context "when @expectations not nil" do let(:expectations) { [1] } it "returns @expectations" do Typhoeus::Expectation.instance_variable_set(:@expectations, expectations) expect(Typhoeus::Expectation.all).to be(expectations) end end end describe ".clear" do let(:expectations) { mock(:clear) } it "clears all" do expectations.should_receive(:clear) Typhoeus::Expectation.instance_variable_set(:@expectations, expectations) Typhoeus::Expectation.clear Typhoeus::Expectation.instance_variable_set(:@expectations, nil) end end describe ".response_for" do let(:request) { Typhoeus::Request.new("") } let(:stubbed_response) { Typhoeus::Response.new } it "finds a matching expectation and returns its next response" do Typhoeus::Expectation.all << expectation expectation.should_receive(:matches?).with(request).and_return(true) expectation.should_receive(:response).with(request).and_return(stubbed_response) response = Typhoeus::Expectation.response_for(request) expect(response).to be(stubbed_response) end it "returns nil if no matching expectation is found" do response = Typhoeus::Expectation.response_for(request) expect(response).to be(nil) end end describe "#stubbed_from" do it "sets value" do expectation.stubbed_from(:webmock) expect(expectation.from).to eq(:webmock) end it "returns self" do expect(expectation.stubbed_from(:webmock)).to be(expectation) end end describe "#and_return" do context "when value" do it "adds to responses" do expectation.and_return(1) expect(expectation.responses).to eq([1]) end end context "when array" do it "adds to responses" do pending expectation.and_return([1, 2]) expect(expectation.responses).to eq([1, 2]) end end context "when block" do it "adds to responses" do block = Proc.new {} expectation.and_return(&block) expect(expectation.responses).to eq([block]) end end end describe "#responses" do it "returns responses" do expect(expectation.responses).to be_a(Array) end end describe "#response" do let(:request) { Typhoeus::Request.new("") } before { expectation.instance_variable_set(:@responses, responses) } context "when one response" do context "is pre-constructed" do let(:responses) { [Typhoeus::Response.new] } it "returns response" do expect(expectation.response(request)).to be(responses[0]) end end context "is lazily-constructed" do def construct_response(request) @request_from_response_construction = request lazily_constructed_response end let(:lazily_constructed_response) { Typhoeus::Response.new } let(:responses) { [ Proc.new { |request| construct_response(request) } ] } it "returns response" do expect(expectation.response(request)).to be(lazily_constructed_response) expect(@request_from_response_construction).to be(request) end end end context "when multiple responses" do let(:responses) { [Typhoeus::Response.new, Typhoeus::Response.new, Typhoeus::Response.new] } it "returns one by one" do 3.times do |i| expect(expectation.response(request)).to be(responses[i]) end end end end describe "#matches?" do let(:request) { stub(:base_url => nil) } it "calls url_match?" do expectation.should_receive(:url_match?) expectation.matches?(request) end it "calls options_match?" do expectation.should_receive(:url_match?).and_return(true) expectation.should_receive(:options_match?) expectation.matches?(request) end end describe "#url_match?" do let(:request_url) { "www.example.com" } let(:request) { Typhoeus::Request.new(request_url) } let(:url_match) { expectation.method(:url_match?).call(request.base_url) } context "when string" do context "when match" do it "returns true" do expect(url_match).to be_true end end context "when no match" do let(:base_url) { "no_match" } it "returns false" do expect(url_match).to be_false end end end context "when regexp" do context "when match" do let(:base_url) { /example/ } it "returns true" do expect(url_match).to be_true end end context "when no match" do let(:base_url) { /nomatch/ } it "returns false" do expect(url_match).to be_false end end end context "when nil" do let(:base_url) { nil } it "returns true" do expect(url_match).to be_true end end context "when not string, regexp, nil" do let(:base_url) { 1 } it "returns false" do expect(url_match).to be_false end end end describe "options_match?" do let(:request_options) { {} } let(:request) { Typhoeus::Request.new(nil, request_options) } let(:options_match) { expectation.method(:options_match?).call(request) } context "when match" do let(:options) { { :a => 1 } } let(:request_options) { options } it "returns true" do expect(options_match).to be_true end end context "when options are a subset from request_options" do let(:options) { { :a => 1 } } let(:request_options) { { :a => 1, :b => 2 } } it "returns true" do expect(options_match).to be_true end end context "when options are nested" do let(:options) { { :a => { :b => 1 } } } let(:request_options) { options } it "returns true" do expect(options_match).to be_true end end context "when options contains an array" do let(:options) { { :a => [1, 2] } } let(:request_options) { options } it "returns true" do expect(options_match).to be_true end end context "when no match" do let(:options) { { :a => 1 } } it "returns false" do expect(options_match).to be_false end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/000077500000000000000000000000001214536063700203075ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/hydra/addable_spec.rb000066400000000000000000000013161214536063700232230ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Addable do let(:hydra) { Typhoeus::Hydra.new() } let(:request) { Typhoeus::Request.new("localhost:3001", {:method => :get}) } it "asks easy factory for an easy" do multi = stub Typhoeus::EasyFactory.should_receive(:new).with(request, hydra).and_return(stub(:get => 1)) hydra.should_receive(:multi).and_return(multi) multi.should_receive(:add).with(1) hydra.add(request) end it "adds easy to multi" do multi = stub Typhoeus::EasyFactory.should_receive(:new).with(request, hydra).and_return(stub(:get => 1)) hydra.should_receive(:multi).and_return(multi) multi.should_receive(:add).with(1) hydra.add(request) end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/before_spec.rb000066400000000000000000000044341214536063700231150ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Before do let(:request) { Typhoeus::Request.new("") } let(:hydra) { Typhoeus::Hydra.new } describe "#add" do context "when before" do context "when one" do it "executes" do Typhoeus.before { |r| String.new(r.base_url) } String.should_receive(:new).and_return("") hydra.add(request) end context "when true" do it "calls super" do Typhoeus.before { true } Typhoeus::Expectation.should_receive(:response_for) hydra.add(request) end end context "when false" do it "doesn't call super" do Typhoeus.before { false } Typhoeus::Expectation.should_receive(:response_for).never hydra.add(request) end end context "when response" do it "doesn't call super" do Typhoeus.before { Typhoeus::Response.new } Typhoeus::Expectation.should_receive(:response_for).never hydra.add(request) end end end context "when multi" do context "when all true" do before { 3.times { Typhoeus.before { |r| String.new(r.base_url) } } } it "calls super" do Typhoeus::Expectation.should_receive(:response_for) hydra.add(request) end it "executes all" do String.should_receive(:new).exactly(3).times.and_return("") hydra.add(request) end end context "when middle false" do before do Typhoeus.before { |r| String.new(r.base_url) } Typhoeus.before { |r| String.new(r.base_url); nil } Typhoeus.before { |r| String.new(r.base_url) } end it "doesn't call super" do Typhoeus::Expectation.should_receive(:response_for).never hydra.add(request) end it "executes only two" do String.should_receive(:new).exactly(2).times.and_return("") hydra.add(request) end end end end context "when no before" do it "calls super" do Typhoeus::Expectation.should_receive(:response_for) hydra.add(request) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/block_connection_spec.rb000066400000000000000000000010231214536063700251530ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::BlockConnection do let(:base_url) { "localhost:3001" } let(:hydra) { Typhoeus::Hydra.new() } let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } describe "add" do context "when block_connection activated" do before { Typhoeus::Config.block_connection = true } after { Typhoeus::Config.block_connection = false } it "raises" do expect{ hydra.add(request) }.to raise_error(Typhoeus::Errors::NoStub) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/cacheable_spec.rb000066400000000000000000000023171214536063700235400ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Cacheable do let(:base_url) { "localhost:3001" } let(:hydra) { Typhoeus::Hydra.new() } let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } let(:cache) { Class.new do attr_reader :memory def initialize @memory = {} end def get(request) memory[request] end def set(request, response) memory[request] = response end end.new } describe "add" do context "when cache activated" do before { Typhoeus::Config.cache = cache } after { Typhoeus::Config.cache = false } context "when request new" do it "sets no response" do hydra.add(request) expect(request.response).to be_nil end it "doesn't call complete" do request.should_receive(:complete).never hydra.add(request) end end context "when request in memory" do let(:response) { Typhoeus::Response.new } before { cache.memory[request] = response } it "finishes request" do request.should_receive(:finish).with(response) hydra.add(request) end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/memoizable_spec.rb000066400000000000000000000021361214536063700237740ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Memoizable do let(:base_url) { "localhost:3001" } let(:hydra) { Typhoeus::Hydra.new() } let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } describe "add" do context "when memoization activated" do before { Typhoeus::Config.memoize = true } after { Typhoeus::Config.memoize = false } context "when request new" do it "sets no response" do hydra.add(request) expect(request.response).to be_nil end it "doesn't call complete" do request.should_receive(:complete).never hydra.add(request) end end context "when request in memory" do let(:response) { Typhoeus::Response.new } before { hydra.memory[request] = response } it "finishes request" do request.should_receive(:finish).with(response, true) hydra.add(request) end end end end describe "#run" do it "clears memory before starting" do hydra.memory.should_receive(:clear) hydra.run end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/queueable_spec.rb000066400000000000000000000013301214536063700236130ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Queueable do let(:base_url) { "localhost:3001" } let(:options) { {} } let(:hydra) { Typhoeus::Hydra.new(options) } describe "#queue" do let(:request) { Typhoeus::Request.new("") } it "accepts requests" do hydra.queue(request) end it "sets hydra on request" do hydra.queue(request) expect(request.hydra).to eq(hydra) end it "adds to queued requests" do hydra.queue(request) expect(hydra.queued_requests).to include(request) end end describe "#abort" do before { hydra.queued_requests << 1 } it "clears queue" do hydra.abort expect(hydra.queued_requests).to be_empty end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/runnable_spec.rb000066400000000000000000000100011214536063700234440ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Runnable do let(:base_url) { "localhost:3001" } let(:options) { {} } let(:hydra) { Typhoeus::Hydra.new(options) } describe "#run" do before do requests.each { |r| hydra.queue r } end context "when no request queued" do let(:requests) { [] } it "does nothing" do hydra.multi.should_receive(:perform) hydra.run end end context "when request queued" do let(:first) { Typhoeus::Request.new("localhost:3001/first") } let(:requests) { [first] } it "adds request from queue to multi" do hydra.should_receive(:add).with(first) hydra.run end it "runs multi#perform" do hydra.multi.should_receive(:perform) hydra.run end it "sends" do hydra.run expect(first.response).to be end end context "when three request queued" do let(:first) { Typhoeus::Request.new("localhost:3001/first") } let(:second) { Typhoeus::Request.new("localhost:3001/second") } let(:third) { Typhoeus::Request.new("localhost:3001/third") } let(:requests) { [first, second, third] } it "adds requests from queue to multi" do hydra.should_receive(:add).with(first) hydra.should_receive(:add).with(second) hydra.should_receive(:add).with(third) hydra.run end it "runs multi#perform" do hydra.multi.should_receive(:perform) hydra.run end it "sends first" do hydra.run expect(first.response).to be end it "sends second" do hydra.run expect(second.response).to be end it "sends third" do hydra.run expect(third.response).to be end it "sends first first" do first.on_complete do expect(second.response).to be_nil expect(third.response).to be_nil end end it "sends second second" do first.on_complete do expect(first.response).to be expect(third.response).to be_nil end end it "sends thirds last" do first.on_complete do expect(second.response).to be expect(third.response).to be end end end context "when really queued request" do let(:options) { {:max_concurrency => 1} } let(:first) { Typhoeus::Request.new("localhost:3001/first") } let(:second) { Typhoeus::Request.new("localhost:3001/second") } let(:third) { Typhoeus::Request.new("localhost:3001/third") } let(:requests) { [first, second, third] } it "sends first" do hydra.run expect(first.response).to be end it "sends second" do hydra.run expect(second.response).to be end it "sends third" do hydra.run expect(third.response).to be end end context "when request queued in callback" do let(:first) do Typhoeus::Request.new("localhost:3001/first").tap do |r| r.on_complete{ hydra.queue(second) } end end let(:second) { Typhoeus::Request.new("localhost:3001/second") } let(:requests) { [first] } before { Typhoeus.on_complete { |r| String.new(r.code) } } after { Typhoeus.on_complete.clear; Typhoeus.before.clear } context "when real request" do context "when max_concurrency default" do let(:options) { {} } it "calls on_complete callback once for every response" do String.should_receive(:new).exactly(2).times hydra.run end end end context "when no real request" do context "when before hook returns and finishes response" do before { Typhoeus.before{ |request| request.finish(Typhoeus::Response.new) } } it "simulates real multi run and adds and finishes both requests" do String.should_receive(:new).exactly(2).times hydra.run end end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra/stubbable_spec.rb000066400000000000000000000012241214536063700236100ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Hydra::Stubbable do let(:base_url) { "localhost:3001" } let(:request) { Typhoeus::Request.new(base_url) } let(:response) { Typhoeus::Response.new } let(:hydra) { Typhoeus::Hydra.new } before { Typhoeus.stub(base_url).and_return(response) } describe "#add" do it "checks expectations" do hydra.add(request) end context "when expectation found" do it "finishes response" do request.should_receive(:finish) hydra.add(request) end it "is a mock" do hydra.add(request) expect(request.response.mock).to be(true) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/hydra_spec.rb000066400000000000000000000010651214536063700216500ustar00rootroot00000000000000require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') describe Typhoeus::Hydra do let(:base_url) { "localhost:3001" } let(:options) { {} } let(:hydra) { Typhoeus::Hydra.new(options) } describe "#new" do let(:options) { {:pipeling => true} } it "passes options to multi" do Ethon::Multi.should_receive(:new).with(options) hydra end end describe "#hydra" do it "returns a hydra" do expect(Typhoeus::Hydra.hydra).to be_a(Typhoeus::Hydra) end end describe "#fire_and_forget" do it end end ruby-typhoeus-0.6.3/spec/typhoeus/pool_spec.rb000066400000000000000000000034471214536063700215200ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Pool do let(:easy) { Ethon::Easy.new } after { Typhoeus::Pool.clear } describe "#easies" do it "returns array" do expect(Typhoeus::Pool.send(:easies)).to be_a(Array) end end describe "#release" do it "resets easy" do easy.should_receive(:reset) Typhoeus::Pool.release(easy) end it "puts easy back into pool" do Typhoeus::Pool.release(easy) expect(Typhoeus::Pool.send(:easies)).to include(easy) end context "when threaded access" do it "releases correct number of easies" do (0..9).map do |n| Thread.new do Typhoeus::Pool.release(Ethon::Easy.new) end end.map(&:join) expect(Typhoeus::Pool.send(:easies)).to have(10).easies end end end describe "#get" do context "when easy in pool" do before { Typhoeus::Pool.send(:easies) << easy } it "takes" do expect(Typhoeus::Pool.get).to eq(easy) end end context "when no easy in pool" do it "creates" do expect(Typhoeus::Pool.get).to be_a(Ethon::Easy) end context "when threaded access" do it "creates correct number of easies" do array = [] (0..9).map do |n| Thread.new do array << Typhoeus::Pool.get end end.map(&:join) expect(array.uniq).to have(10).easies end end end end describe "#with" do it "is re-entrant" do array = [] Typhoeus::Pool.with_easy do |e1| array << e1 Typhoeus::Pool.with_easy do |e2| array << e2 Typhoeus::Pool.with_easy do |e3| array << e3 end end end expect(array.uniq).to have(3).easies end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/000077500000000000000000000000001214536063700206705ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/request/actions_spec.rb000066400000000000000000000010421214536063700236640ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Actions do [:get, :post, :put, :delete, :head, :patch, :options].each do |name| describe ".#{name}" do let(:response) { Typhoeus::Request.method(name).call("http://localhost:3001") } it "returns ok" do expect(response.return_code).to eq(:ok) end unless name == :head it "makes #{name.to_s.upcase} Request" do expect(response.response_body).to include("\"REQUEST_METHOD\":\"#{name.to_s.upcase}\"") end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/before_spec.rb000066400000000000000000000050101214536063700234650ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Before do let(:request) { Typhoeus::Request.new("") } describe "#queue" do context "when before" do context "when one" do it "executes" do Typhoeus.before { |r| String.new(r.base_url) } String.should_receive(:new).and_return("") request.run end context "when true" do it "calls super" do Typhoeus.before { true } Typhoeus::Expectation.should_receive(:response_for) request.run end end context "when false" do it "doesn't call super" do Typhoeus.before { false } Typhoeus::Expectation.should_receive(:response_for).never request.run end it "returns response" do Typhoeus.before { |r| r.response = 1; false } expect(request.run).to be(1) end end context "when a response" do it "doesn't call super" do Typhoeus.before { Typhoeus::Response.new } Typhoeus::Expectation.should_receive(:response_for).never request.run end it "returns response" do Typhoeus.before { |r| r.response = Typhoeus::Response.new } expect(request.run).to be_a(Typhoeus::Response) end end end context "when multi" do context "when all true" do before { 3.times { Typhoeus.before { |r| String.new(r.base_url) } } } it "calls super" do Typhoeus::Expectation.should_receive(:response_for) request.run end it "executes all" do String.should_receive(:new).exactly(3).times.and_return("") request.run end end context "when middle false" do before do Typhoeus.before { |r| String.new(r.base_url) } Typhoeus.before { |r| String.new(r.base_url); nil } Typhoeus.before { |r| String.new(r.base_url) } end it "doesn't call super" do Typhoeus::Expectation.should_receive(:response_for).never request.run end it "executes only two" do String.should_receive(:new).exactly(2).times.and_return("") request.run end end end end context "when no before" do it "calls super" do Typhoeus::Expectation.should_receive(:response_for) request.run end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/block_connection_spec.rb000066400000000000000000000034631214536063700255460ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::BlockConnection do let(:base_url) { "localhost:3001" } let(:request) { Typhoeus::Request.new(base_url, {:method => :get}) } describe "run" do context "when blocked" do before { request.block_connection = true } it "raises" do expect{ request.run }.to raise_error(Typhoeus::Errors::NoStub) end end context "when not blocked" do before { request.block_connection = false } it "doesn't raise" do expect{ request.run }.to_not raise_error end end end describe "#blocked?" do context "when local block_connection" do context "when true" do before { request.block_connection = true } it "returns true" do expect(request.blocked?).to be_true end end context "when false" do before { request.block_connection = false } it "returns false" do expect(request.blocked?).to be_false end end end context "when global block_connection" do context "when true" do before { Typhoeus::Config.block_connection = true } after { Typhoeus::Config.block_connection = false } it "returns true" do expect(request.blocked?).to be_true end end context "when false" do before { Typhoeus::Config.block_connection = false } it "returns false" do expect(request.blocked?).to be_false end end end context "when global and local block_connection" do before do Typhoeus::Config.block_connection = true request.block_connection = false end after { Typhoeus::Config.block_connection = false } it "takes local" do expect(request.blocked?).to be_false end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/cacheable_spec.rb000066400000000000000000000034651214536063700241260ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Cacheable do let(:cache) { Class.new do attr_reader :memory def initialize @memory = {} end def get(request) memory[request] end def set(request, response) memory[request] = response end end.new } let(:options) { {} } let(:request) { Typhoeus::Request.new("http://localhost:3001", options) } let(:response) { Typhoeus::Response.new } before { Typhoeus::Config.cache = cache } after { Typhoeus::Config.cache = false } describe "#response=" do context "when cache activated" do context "when nequest new" do it "caches response" do request.response = response expect(cache.memory[request]).to be end end context "when request in memory" do before { cache.memory[request] = response } it "finishes request" do request.should_receive(:finish).with(response) request.run end end end end describe "#run" do context "when cache activated" do before { Typhoeus::Config.cache = cache } after { Typhoeus::Config.cache = false } context "when request new" do it "fetches response" do expect(request.response).to_not be(response) end end context "when request in memory" do let(:response) { Typhoeus::Response.new } before { cache.memory[request] = response } it "finishes request" do request.should_receive(:finish).with(response) request.run end end end end describe "#cache_ttl" do context "when option[:cache_ttl]" do let(:options) { {:cache_ttl => 1} } it "returns" do expect(request.cache_ttl).to be(1) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/callbacks_spec.rb000066400000000000000000000052141214536063700241500ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Callbacks do let(:request) { Typhoeus::Request.new("fubar") } [:on_complete, :on_success, :on_failure].each do |callback| describe "##{callback}" do it "responds" do expect(request).to respond_to(callback) end context "when no block given" do it "returns @#{callback}" do expect(request.method(callback).call).to eq([]) end end context "when block given" do it "stores" do request.method(callback).call { p 1 } expect(request.instance_variable_get("@#{callback}")).to have(1).items end end context "when multiple blocks given" do it "stores" do request.method(callback).call { p 1 } request.method(callback).call { p 2 } expect(request.instance_variable_get("@#{callback}")).to have(2).items end end end end describe "#execute_callbacks" do [:on_complete, :on_success, :on_failure].each do |callback| context "when #{callback}" do context "when local callback" do before do code = if callback == :on_failure 500 else 200 end request.response = Typhoeus::Response.new(:mock => true, :response_code => code) request.method(callback).call {|r| expect(r).to be_a(Typhoeus::Response) } end it "executes blocks and passes response" do request.execute_callbacks end it "sets handled_response" do request.method(callback).call { 1 } request.execute_callbacks expect(request.response.handled_response).to be(1) end end context "when global callback" do before do request.response = Typhoeus::Response.new Typhoeus.method(callback).call {|r| expect(r).to be_a(Typhoeus::Response) } end it "executes blocks and passes response" do request.execute_callbacks end end context "when global and local callbacks" do before do request.response = Typhoeus::Response.new Typhoeus.method(callback).call {|r| r.instance_variable_set(:@fu, 1) } request.method(callback).call {|r| expect(r.instance_variable_get(:@fu)).to eq(1) } end it "runs global first" do request.execute_callbacks end end end end context "when local on_complete and gobal on_success" do it "runs all global callbacks first" do pending end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/marshal_spec.rb000066400000000000000000000017671214536063700236710ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Marshal do let(:base_url) { "localhost:3001" } let(:request) { Typhoeus::Request.new(base_url) } describe "#marshal_dump" do let(:base_url) { "http://www.google.com" } ['on_complete'].each do |name| context "when #{name} handler" do before { request.instance_variable_set("@#{name}", Proc.new{}) } it "doesn't include @#{name}" do expect(request.send(:marshal_dump).map(&:first)).to_not include("@#{name}") end it "doesn't raise when dumped" do expect { Marshal.dump(request) }.to_not raise_error end context "when loading" do let(:loaded) { Marshal.load(Marshal.dump(request)) } it "includes base_url" do expect(loaded.base_url).to eq(request.base_url) end it "doesn't include #{name}" do expect(loaded.instance_variables).to_not include("@#{name}") end end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/memoizable_spec.rb000066400000000000000000000016431214536063700243570ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Memoizable do let(:options) { {} } let(:request) { Typhoeus::Request.new("fu", options) } let(:response) { Typhoeus::Response.new } let(:hydra) { Typhoeus::Hydra.new } describe "#response=" do context "when memoization activated" do before { Typhoeus::Config.memoize = true } after { Typhoeus::Config.memoize = false } context "when GET request" do let(:options) { {:method => :get} } before { request.hydra = hydra } it "stores response in memory" do request.response = response expect(hydra.memory[request]).to be end end context "when no GET request" do let(:options) { {:method => :post} } it "doesn't store response in memory" do request.response = response expect(hydra.memory[request]).to be_nil end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/operations_spec.rb000066400000000000000000000047631214536063700244240ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Operations do let(:base_url) { "localhost:3001" } let(:options) { {} } let(:request) { Typhoeus::Request.new(base_url, options) } describe "#run" do let(:easy) { Ethon::Easy.new } before { Typhoeus::Pool.should_receive(:get).and_return(easy) } it "grabs an easy" do request.run end it "generates settings" do easy.should_receive(:http_request) request.run end it "performs" do easy.should_receive(:perform) request.run end it "sets response" do request.run expect(request.response).to be end it "releases easy" do Typhoeus::Pool.should_receive(:release) request.run end it "calls on_complete" do callback = mock(:call) callback.should_receive(:call) request.instance_variable_set(:@on_complete, [callback]) request.run end it "returns a response" do expect(request.run).to be_a(Typhoeus::Response) end context "when invalid option" do let(:options) { { :fubar => true } } it "raises Ethon::Errors::InvalidOption" do expect{ request.run }.to raise_error(Ethon::Errors::InvalidOption) end end context "when option renamed" do let(:options) { { :follow_location => true } } it "raises Ethon::Errors::InvalidOption" do expect{ request.run }.to raise_error(Ethon::Errors::InvalidOption) end it "has hint for new option" do expect{ request.run }.to raise_error(/Please try followlocation instead of follow_location\./) end end context "when option removed" do let(:options) { { :cache_timout => 1 } } it "raises Ethon::Errors::InvalidOption" do expect{ request.run }.to raise_error(Ethon::Errors::InvalidOption) end it "has hint for removed option" do expect{ request.run }.to raise_error(/The option cache_timout was removed\./) end end end describe "#finish" do let(:response) { Typhoeus::Response.new } it "assigns response" do request.finish(response) expect(request.response).to be(response) end it "assigns request to response" do request.finish(response) expect(request.response.request).to be(request) end it "executes callbacks" do request.should_receive(:execute_callbacks) request.finish(response) end it "returns response" do expect(request.finish(response)).to be(response) end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/responseable_spec.rb000066400000000000000000000005041214536063700247100ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Responseable do let(:request) { Typhoeus::Request.new("base_url", {}) } let(:response) { Typhoeus::Response.new } describe "#response=" do it "stores response" do request.response = response expect(request.response).to eq(response) end end end ruby-typhoeus-0.6.3/spec/typhoeus/request/stubbable_spec.rb000066400000000000000000000011461214536063700241740ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request::Stubbable do let(:base_url) { "localhost:3001" } let(:request) { Typhoeus::Request.new(base_url) } let(:response) { Typhoeus::Response.new } before { Typhoeus.stub(base_url).and_return(response) } describe "#run" do it "checks expectations" do request.run end context "when expectation found" do it "finishes request" do request.should_receive(:finish) request.run end it "sets mock on response" do request.run expect(request.response.mock).to be(true) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/request_spec.rb000066400000000000000000000061451214536063700222350ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Request do let(:base_url) { "localhost:3001" } let(:options) { {:verbose => true, :headers => { 'User-Agent' => "Fubar" }} } let(:request) { Typhoeus::Request.new(base_url, options) } describe ".url" do context "when no parameters" do it "returns base_url" do expect(request.url).to eq(request.base_url) end end context "when parameters" do let(:options) { {:params => {:a => 1}} } it "returns full url" do expect(request.url).to eq("#{request.base_url}?a=1") end end end describe ".new" do it "stores base_url" do expect(request.base_url).to eq(base_url) end it "stores options" do expect(request.options).to eq(options) end context "when header with user agent" do let(:options) { {:headers => {'User-Agent' => "Custom"} } } it "doesn't modify user agent" do expect(request.options[:headers]['User-Agent']).to eq("Custom") end end context "when header without user agent" do let(:options) { {:headers => {} } } it "add user agent" do expect(request.options[:headers]['User-Agent']).to eq(Typhoeus::USER_AGENT) end end context "when Config.verbose set" do before { Typhoeus.configure { |config| config.verbose = true} } after { Typhoeus.configure { |config| config.verbose = false} } it "respects" do expect(request.options[:verbose]).to be_true end end end describe "#eql?" do context "when another class" do let(:other) { "" } it "returns false" do expect(request).to_not eql other end end context "when same class" do let(:other) { Typhoeus::Request.new("base_url", options) } context "when other base_url" do it "returns false" do expect(request).to_not eql other end end context "when same base_url and other options" do let(:other) { Typhoeus::Request.new(base_url, {}) } it "returns false" do expect(request).to_not eql other end end context "when same base_url and options" do context "when same order" do let(:other) { Typhoeus::Request.new(base_url, options) } it "returns true" do expect(request).to eql other end end context "when different order" do let(:other_options) { {:headers => { 'User-Agent' => "Fubar", }, :verbose => true } } let(:other) { Typhoeus::Request.new(base_url, other_options)} it "returns true" do expect(request).to eql other end end end end end describe "#hash" do context "when request.eql?(other)" do let(:other) { Typhoeus::Request.new(base_url, options) } it "has same hashes" do expect(request.hash).to eq(other.hash) end end context "when not request.eql?(other)" do let(:other) { Typhoeus::Request.new("base_url", {}) } it "has different hashes" do expect(request.hash).to_not eq(other.hash) end end end end ruby-typhoeus-0.6.3/spec/typhoeus/response/000077500000000000000000000000001214536063700210365ustar00rootroot00000000000000ruby-typhoeus-0.6.3/spec/typhoeus/response/header_spec.rb000066400000000000000000000063051214536063700236310ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Response::Header do let(:raw) { nil } let(:header) { Typhoeus::Response::Header.new(raw) } describe ".new" do context "when string" do let(:raw) { 'Date: Fri, 29 Jun 2012 10:09:23 GMT' } it "sets Date" do expect(header['Date']).to eq('Fri, 29 Jun 2012 10:09:23 GMT') end it "provides case insensitive access" do expect(header['DaTe']).to eq('Fri, 29 Jun 2012 10:09:23 GMT') end it "provides symbol access" do expect(header[:date]).to eq('Fri, 29 Jun 2012 10:09:23 GMT') end end context "when hash" do let(:raw) { { 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT' } } it "sets Date" do expect(header['Date']).to eq(raw['Date']) end it "provides case insensitive access" do expect(header['DaTe']).to eq(raw['Date']) end end end describe "#parse" do context "when no header" do it "returns nil" do expect(header).to be_empty end end context "when header" do let(:raw) do 'HTTP/1.1 200 OK Set-Cookie: NID=61=LblqYgUOu; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly Date: Fri, 29 Jun 2012 10:09:23 GMT Expires: -1 Cache-Control: private, max-age=0 Content-Type: text/html; charset=ISO-8859-1 Set-Cookie: PREF=ID=77e93yv0hPtejLou; expires=Sun, 29-Jun-2014 10:09:23 GMT; path=/; domain=.google.de Set-Cookie: NID=61=LblqYgh5Ou; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly P3P: CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info." Server: gws X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN Transfer-Encoding: chunked' end it "sets raw" do expect(header.send(:raw)).to eq(raw) end it "sets Set-Cookie" do expect(header['set-cookie']).to have(3).items end it "provides case insensitive access" do expect(header['Set-CooKie']).to have(3).items end [ 'NID=61=LblqYgUOu; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly', 'PREF=ID=77e93yv0hPtejLou; expires=Sun, 29-Jun-2014 10:09:23 GMT; path=/; domain=.google.de', 'NID=61=LblqYgh5Ou; expires=Sat, 29-Dec-2012 10:09:23 GMT; path=/; domain=.google.de; HttpOnly' ].each_with_index do |cookie, i| it "sets Cookie##{i}" do expect(header['set-cookie']).to include(cookie) end end { 'Date' => 'Fri, 29 Jun 2012 10:09:23 GMT', 'Expires' => '-1', 'Cache-Control' => 'private, max-age=0', 'Content-Type' => 'text/html; charset=ISO-8859-1', 'P3P' => 'CP="This is not a P3P policy! See http://www.google.com/support/accounts/bin/answer.py?hl=en&answer=151657 for more info."', 'Server' => 'gws', 'X-XSS-Protection' => '1; mode=block', 'X-Frame-Options' => 'SAMEORIGIN', 'Transfer-Encoding' => 'chunked' }.each do |name, value| it "sets #{name}" do expect(header[name.downcase]).to eq(value) end end end end end ruby-typhoeus-0.6.3/spec/typhoeus/response/informations_spec.rb000066400000000000000000000120371214536063700251100ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Response::Informations do let(:options) { {} } let(:response) { Typhoeus::Response.new(options) } describe "#return_code" do let(:options) { { :return_code => :ok } } it "returns return_code from options" do expect(response.return_code).to be(:ok) end end describe "#return_message" do let(:options) { { :return_code => :couldnt_connect } } it "returns a message" do expect(response.return_message).to eq("Couldn't connect to server") end end describe "#response_body" do context "when response_body" do let(:options) { { :response_body => "body" } } it "returns response_body from options" do expect(response.response_body).to eq("body") end end context "when body" do let(:options) { { :body => "body" } } it "returns body from options" do expect(response.body).to eq("body") end end end describe "#response_headers" do let(:options) { { :response_headers => "headers" } } it "returns response_headers from options" do expect(response.response_headers).to eq("headers") end end describe "#response_code" do context "when response_code" do let(:options) { { :response_code => "200" } } it "returns response_code from options" do expect(response.response_code).to eq(200) end end context "when code" do let(:options) { { :code => "200" } } it "returns code from options" do expect(response.code).to eq(200) end end end describe "#httpauth_avail" do let(:options) { { :httpauth_avail => "code" } } it "returns httpauth_avail from options" do expect(response.httpauth_avail).to eq("code") end end describe "#total_time" do let(:options) { { :total_time => 1 } } it "returns total_time from options" do expect(response.total_time).to eq(1) end end describe "#starttransfer_time" do let(:options) { { :starttransfer_time => 1 } } it "returns starttransfer_time from options" do expect(response.starttransfer_time).to eq(1) end end describe "#appconnect_time" do let(:options) { { :appconnect_time => 1 } } it "returns appconnect_time from options" do expect(response.appconnect_time).to eq(1) end end describe "#pretransfer_time" do let(:options) { { :pretransfer_time => 1 } } it "returns pretransfer_time from options" do expect(response.pretransfer_time).to eq(1) end end describe "#connect_time" do let(:options) { { :connect_time => 1 } } it "returns connect_time from options" do expect(response.connect_time).to eq(1) end end describe "#namelookup_time" do let(:options) { { :namelookup_time => 1 } } it "returns namelookup_time from options" do expect(response.namelookup_time).to eq(1) end end describe "#effective_url" do let(:options) { { :effective_url => "http://www.example.com" } } it "returns effective_url from options" do expect(response.effective_url).to eq("http://www.example.com") end end describe "#primary_ip" do let(:options) { { :primary_ip => "127.0.0.1" } } it "returns primary_ip from options" do expect(response.primary_ip).to eq("127.0.0.1") end end describe "#redirect_count" do let(:options) { { :redirect_count => 2 } } it "returns redirect_count from options" do expect(response.redirect_count).to eq(2) end end describe "#headers" do context "when no headers" do it "returns nil" do expect(response.headers).to be_nil end end context "when headers" do let(:options) { {:response_headers => "Expire: -1\nServer: gws"} } it "returns nonempty headers" do expect(response.headers).to_not be_empty end it "has Expire" do expect(response.headers['expire']).to eq('-1') end it "has Server" do expect(response.headers['server']).to eq('gws') end end context "when multiple headers" do let(:options) { {:response_headers => "Server: A\r\n\r\nServer: B"} } it "returns the last" do expect(response.headers['server']).to eq("B") end end context "when requesting" do let(:response) { Typhoeus.get("localhost:3001") } it "returns headers" do expect(response.headers).to_not be_empty end end end describe "#redirections" do context "when no response_headers" do it "returns empty array" do expect(response.redirections).to be_empty end end context "when headers" do let(:options) { {:response_headers => "Expire: -1\nServer: gws"} } it "returns empty array" do expect(response.redirections).to be_empty end end context "when multiple headers" do let(:options) { {:response_headers => "Server: A\r\n\r\nServer: B"} } it "returns response from all but last headers" do expect(response.redirections).to have(1).item end end end end ruby-typhoeus-0.6.3/spec/typhoeus/response/status_spec.rb000066400000000000000000000123001214536063700237140ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Response::Status do let(:response) { Typhoeus::Response.new(options) } let(:options) { {} } describe "timed_out?" do context "when return code is operation_timedout" do let(:options) { {:return_code => :operation_timedout} } it "return true" do expect(response).to be_timed_out end end context "when return code is couldnt_connect" do let(:options) { {:return_code => :couldnt_connect} } it "return true" do expect(response).to be_timed_out end end context "when return code is not operation_timedout or couldnt_connect" do let(:options) { {:return_code => 14} } it "returns false" do expect(response).to_not be_timed_out end end end describe "#status_message" do context "when no header" do it "returns nil" do expect(response.status_message).to be_nil end end context "when header" do context "when no message" do let(:options) { {:response_headers => "HTTP/1.1 200\r\n"} } it "returns nil" do expect(response.status_message).to be_nil end end context "when messsage" do let(:options) { {:response_headers => "HTTP/1.1 200 message\r\n"} } it "returns message" do expect(response.status_message).to eq("message") end end end end describe "#http_version" do context "when no header" do it "returns nil" do expect(response.http_version).to be_nil end end context "when header" do context "when no http version" do let(:options) { {:response_headers => "HTTP OK"} } it "returns nil" do expect(response.http_version).to be_nil end end context "when invalid http_version" do let(:options) { {:response_headers => "HTTP foo/bar OK"} } it "returns nil" do expect(response.http_version).to be_nil end end context "when valid http_version" do let(:options) { {:response_headers => "HTTP/1.1 OK"} } it "returns http_version" do expect(response.http_version).to eq("1.1") end end end end describe "#success?" do context "when response code 200-299" do let(:options) { {:return_code => return_code, :response_code => 201} } context "when mock" do before { response.mock = true } context "when return_code :ok" do let(:return_code) { :ok } it "returns true" do expect(response.success?).to be_true end end context "when return_code nil" do let(:return_code) { nil } it "returns true" do expect(response.success?).to be_true end end end context "when no mock" do before { response.mock = nil } context "when return_code :ok" do let(:return_code) { :ok } it "returns true" do expect(response.success?).to be_true end end context "when return_code nil" do let(:return_code) { nil } it "returns false" do expect(response.success?).to be_false end end end end context "when response code is not 200-299" do let(:options) { {:return_code => :ok, :response_code => 500} } it "returns false" do expect(response.success?).to be_false end end end describe "#modified?" do context "when response code 304" do let(:options) { {:return_code => :ok, :response_code => 304} } context "when mock" do before { response.mock = true } context "when return_code :ok" do let(:return_code) { :ok } it "returns false" do expect(response.modified?).to be_false end end context "when return_code nil" do let(:return_code) { nil } it "returns false" do expect(response.modified?).to be_false end end end context "when no mock" do before { response.mock = nil } context "when return_code :ok" do let(:return_code) { :ok } it "returns false" do expect(response.modified?).to be_false end end context "when return_code nil" do let(:return_code) { nil } it "returns true" do expect(response.modified?).to be_false end end end end context "when response code is not 304" do let(:options) { {:return_code => :ok, :response_code => 500} } it "returns true" do expect(response.modified?).to be_true end end end describe "#first_header_line" do context "when multiple header" do let(:options) { {:response_headers => "1\r\n\r\n2\r\nbla"} } it "returns first line of last block" do expect(response.method(:first_header_line).call).to eq("2") end end context "when single header" do let(:options) { {:response_headers => "1"} } it "returns first line" do expect(response.method(:first_header_line).call).to eq("1") end end end end ruby-typhoeus-0.6.3/spec/typhoeus/response_spec.rb000066400000000000000000000036361214536063700224050ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus::Response do let(:response) { Typhoeus::Response.new(options) } let(:options) { {} } describe ".new" do context "when options" do context "when return_code" do let(:options) { {:return_code => 2} } it "stores" do expect(response.options[:return_code]).to be(2) end end context "when headers" do let(:options) { {:headers => {'A' => 'B'}} } it "stores unmodified" do expect(response.options[:headers]).to be(options[:headers]) end it "sets @headers to a Typhoeus::Response::Header" do expect(response.instance_variable_get(:@headers)).to be_a(Typhoeus::Response::Header) end it "has key" do expect(response.headers['A']).to eq('B') end end end end describe "#mock" do context "when @mock" do before { response.mock = true } it "returns @mock" do expect(response.mock).to be_true end end context "when options[:mock]" do let(:options) { {:mock => true} } it "returns options[:mock]" do expect(response.mock).to be_true end end context "when @mock and options[:mock]" do let(:options) { {:mock => 1} } before { response.mock = 2 } it "returns @mock" do expect(response.mock).to be(2) end end end describe "#handled_response" do let(:handled_response) { Typhoeus::Response.new } context "when @handled_response" do before { response.handled_response = handled_response } it "returns @handled_response" do expect(response.handled_response).to be(handled_response) end end context "when @handled_response is nil" do before { response.handled_response = nil } it "returns response" do expect(response.handled_response).to be(response) end end end end ruby-typhoeus-0.6.3/spec/typhoeus_spec.rb000066400000000000000000000055211214536063700205420ustar00rootroot00000000000000require 'spec_helper' describe Typhoeus do before(:each) do Typhoeus.configure { |config| config.verbose = false; config.block_connection = false } end describe ".configure" do it "yields config" do Typhoeus.configure do |config| expect(config).to be_a(Typhoeus::Config) end end it "sets values config" do Typhoeus::Config.verbose = true expect(Typhoeus::Config.verbose).to be_true end end describe ".stub" do let(:base_url) { "www.example.com" } shared_examples "lazy response construction" do it "calls the block to construct a response when a request matches the stub" do expected_response = Typhoeus::Response.new Typhoeus.stub(base_url) do |request| expected_response end response = Typhoeus.get(base_url) expect(response).to be(expected_response) end end context "when no similar expectation exists" do include_examples "lazy response construction" it "returns expectation" do expect(Typhoeus.stub(base_url)).to be_a(Typhoeus::Expectation) end it "adds expectation" do Typhoeus.stub(:get, "") expect(Typhoeus::Expectation.all).to have(1).item end end context "when similar expectation exists" do include_examples "lazy response construction" let(:expectation) { Typhoeus::Expectation.new(base_url) } before { Typhoeus::Expectation.all << expectation } it "returns expectation" do expect(Typhoeus.stub(base_url)).to be_a(Typhoeus::Expectation) end it "doesn't add expectation" do Typhoeus.stub(base_url) expect(Typhoeus::Expectation.all).to have(1).item end end end describe ".before" do it "adds callback" do Typhoeus.before { true } expect(Typhoeus.before).to have(1).item end end describe ".with_connection" do it "executes block with block connection is false" do Typhoeus.with_connection { expect(Typhoeus::Config.block_connection).to be(false) } end it "sets block connection back to previous value" do Typhoeus::Config.block_connection = true Typhoeus.with_connection {} expect(Typhoeus::Config.block_connection).to be(true) end it "returns result of block" do expect(Typhoeus.with_connection { "123" }).to eq("123") end end [:get, :post, :put, :delete, :head, :patch, :options].each do |name| describe ".#{name}" do let(:response) { Typhoeus::Request.method(name).call("http://localhost:3001") } it "returns ok" do expect(response.return_code).to eq(:ok) end unless name == :head it "makes #{name.to_s.upcase} requests" do expect(response.response_body).to include("\"REQUEST_METHOD\":\"#{name.to_s.upcase}\"") end end end end end ruby-typhoeus-0.6.3/typhoeus.gemspec000066400000000000000000000016571214536063700176240ustar00rootroot00000000000000# encoding: utf-8 lib = File.expand_path('../lib/', __FILE__) $:.unshift lib unless $:.include?(lib) require 'typhoeus/version' Gem::Specification.new do |s| s.name = "typhoeus" s.version = Typhoeus::VERSION s.platform = Gem::Platform::RUBY s.authors = ["David Balatero", "Paul Dix", "Hans Hasselberg"] s.email = ["hans.hasselberg@gmail.com"] s.homepage = "https://github.com/typhoeus/typhoeus" s.summary = "Parallel HTTP library on top of libcurl multi." s.description = %q{Like a modern code version of the mythical beast with 100 serpent heads, Typhoeus runs HTTP requests in parallel while cleanly encapsulating handling logic.} s.required_rubygems_version = ">= 1.3.6" s.rubyforge_project = '[none]' s.add_dependency('ethon', ["~> 0.5.11"]) s.files = Dir.glob("lib/**/*") + %w(CHANGELOG.md Gemfile LICENSE README.md Rakefile) s.require_path = 'lib' end