itrigga-net_helper 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +6 -2
- data/README.rdoc +36 -1
- data/Rakefile +18 -13
- data/VERSION +1 -1
- data/lib/itrigga/net_helper.rb +52 -145
- data/lib/itrigga/net_helper/rest_client.rb +19 -0
- data/lib/itrigga/net_helper/typhoeus.rb +35 -0
- data/spec/net_helper/rest_client_spec.rb +32 -0
- data/spec/net_helper/typhoeus_spec.rb +90 -0
- data/spec/net_helper_spec.rb +167 -236
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +54 -16
- metadata +95 -31
- data/Gemfile.lock +0 -36
data/Gemfile
CHANGED
@@ -5,13 +5,17 @@ source "http://rubygems.org"
|
|
5
5
|
|
6
6
|
# Add dependencies to develop your gem here.
|
7
7
|
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
gem "rest-client"
|
9
|
+
gem "hpricot"
|
10
|
+
gem 'itrigga-core_ext', :require=>'core_ext'
|
11
|
+
|
8
12
|
group :development do
|
9
13
|
gem "hpricot"
|
10
14
|
gem "bundler", "~> 1.0.0"
|
11
15
|
gem "jeweler", "~> 1.6.4"
|
16
|
+
gem "rspec", "1.3.0"
|
17
|
+
gem "rspec-rails", "1.3.2"
|
12
18
|
gem "rcov", ">= 0"
|
13
|
-
gem 'rspec'
|
14
19
|
gem 'json_pure'
|
15
|
-
gem 'itrigga-core_ext', ">= 0"
|
16
20
|
gem "fastercsv", ">= 1.5.4"
|
17
21
|
end
|
data/README.rdoc
CHANGED
@@ -1,6 +1,41 @@
|
|
1
1
|
= net_helper
|
2
2
|
|
3
|
-
|
3
|
+
Provides a wrapper around HTTP GET requests. Uses Net::HTTP (under RestClient) by default, but will use Typhoeus if available
|
4
|
+
Will return the raw body (unparsed) for each request.
|
5
|
+
|
6
|
+
== Usage
|
7
|
+
Rails2
|
8
|
+
gem.config 'itrigga-net_helper', :lib => 'net_helper'
|
9
|
+
|
10
|
+
Rails3 (bundler)
|
11
|
+
gem 'itrigga-net_helper', :require => 'net_helper'
|
12
|
+
|
13
|
+
=== Basic example
|
14
|
+
Itrigga::NetHelper.get :url => "http://www.google.com"
|
15
|
+
|
16
|
+
=== Adding params
|
17
|
+
Itrigga::NetHelper.get :url => "http://www.google.com", :params => {:p1 => "123"}
|
18
|
+
Gives url http://www.google.com?p1=123
|
19
|
+
|
20
|
+
=== Variables
|
21
|
+
|
22
|
+
timeout - in seconds (default 5)
|
23
|
+
retries_on_timeout - how many times to try again (default 5)
|
24
|
+
max_redirects - number of redirects to follow (default 3)
|
25
|
+
|
26
|
+
The SystemTimer gem will be used for timeout is available.
|
27
|
+
|
28
|
+
Itrigga::NetHelper.get :url => "http://www.google.com", :timeout => 300, :max_redirects => 1
|
29
|
+
|
30
|
+
== Using Typhoeus
|
31
|
+
The Typhoeus gem needs to be installed (see https://github.com/dbalatero/typhoeus)
|
32
|
+
Rails2 - gem.config 'typhoeus'
|
33
|
+
Rails3 - gem 'typhoeus'
|
34
|
+
|
35
|
+
To enable for all requests set the constant ITNH_HTTP_ENGINE = "Typhoeus"
|
36
|
+
To use on a per request basis
|
37
|
+
|
38
|
+
Itrigga::NetHelper.get :url => "http://www.google.com", :http_engine => "Typhoeus"
|
4
39
|
|
5
40
|
== Contributing to net_helper
|
6
41
|
|
data/Rakefile
CHANGED
@@ -26,22 +26,27 @@ Jeweler::Tasks.new do |gem|
|
|
26
26
|
end
|
27
27
|
Jeweler::RubygemsDotOrgTasks.new
|
28
28
|
|
29
|
-
require '
|
30
|
-
|
31
|
-
|
32
|
-
test.pattern = 'test/**/test_*.rb'
|
33
|
-
test.verbose = true
|
34
|
-
end
|
29
|
+
require 'spec/version'
|
30
|
+
require 'spec/rake/spectask'
|
31
|
+
require 'spec/ruby'
|
35
32
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
test.verbose = true
|
41
|
-
test.rcov_opts << '--exclude "gems/*"'
|
33
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
34
|
+
RAILS_ENV = "test"
|
35
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
36
|
+
spec.spec_opts = ['--options', 'spec/spec.opts']
|
42
37
|
end
|
43
38
|
|
44
|
-
task :default => :
|
39
|
+
task :default => :spec
|
40
|
+
|
41
|
+
desc "Run all specs with rcov"
|
42
|
+
Spec::Rake::SpecTask.new(:rcov) do |t|
|
43
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
44
|
+
t.spec_opts = ['--options', 'spec/spec.opts']
|
45
|
+
t.rcov = true
|
46
|
+
t.rcov_dir = 'coverage'
|
47
|
+
t.rcov_opts = ['--exclude', "features,kernel,load-diff-lcs\.rb,instance_exec\.rb,lib/spec.rb,lib/spec/runner.rb,^spec/*,bin/spec,examples,/gems,/Library/Ruby,\.autotest,#{ENV['GEM_HOME']}"]
|
48
|
+
t.rcov_opts << '--sort coverage --text-summary --aggregate coverage.data'
|
49
|
+
end
|
45
50
|
|
46
51
|
require 'rake/rdoctask'
|
47
52
|
Rake::RDocTask.new do |rdoc|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/itrigga/net_helper.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'rest-client'
|
2
|
+
require 'itrigga/core_ext'
|
3
|
+
Dir[File.join(File.expand_path(File.dirname(__FILE__)),"net_helper","*.rb")].each{|f| require f}
|
4
|
+
|
1
5
|
require 'uri'
|
2
6
|
require 'hpricot'
|
3
7
|
require 'json'
|
@@ -10,171 +14,74 @@ module Itrigga
|
|
10
14
|
|
11
15
|
module_function
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
else
|
17
|
-
false
|
18
|
-
end
|
17
|
+
# gets a list of engines available (each is a different class in this module that implements 'get' method)
|
18
|
+
def available_http_engines
|
19
|
+
Itrigga::NetHelper.constants
|
19
20
|
end
|
20
|
-
|
21
|
-
def do_get(url, time_out=5, retries_on_timeout=5, max_redirects = 3)
|
22
|
-
retrycount = 0
|
23
|
-
resp = nil
|
24
|
-
begin
|
25
|
-
resp = get_with_timeout( url, time_out )
|
26
|
-
|
27
|
-
handle_response( url, resp, retries_on_timeout, max_redirects )
|
28
|
-
|
29
|
-
rescue Timeout::Error
|
30
|
-
if(retrycount.to_i < retries_on_timeout.to_i)
|
31
|
-
retrycount+=1
|
32
|
-
retry
|
33
|
-
else
|
34
|
-
raise IOError.new( "HTTP request timed out #{retrycount} times" )
|
35
|
-
end
|
36
|
-
end
|
37
21
|
|
22
|
+
def default_http_engine
|
23
|
+
"RestClient"
|
38
24
|
end
|
39
25
|
|
40
|
-
def typhoeus_request( opts={} )
|
41
|
-
opts[:timeout] ||= 30
|
42
|
-
opts[:timeout] *= 1000 # Typhoeus does its timeouts in ms
|
43
|
-
opts[:follow_location] ||= true
|
44
|
-
opts[:disable_ssl_peer_verification] = true if opts[:disable_ssl_peer_verification].nil?
|
45
|
-
|
46
|
-
request = Typhoeus::Request.new(opts[:url], opts)
|
47
|
-
|
48
|
-
request.on_complete do |response|
|
49
|
-
if response.success?
|
50
|
-
return response.body
|
51
|
-
elsif response.timed_out?
|
52
|
-
# aw hell no
|
53
|
-
raise IOError.new("Timed out request to #{opts[:url]} after #{opts[:timeout]}ms")
|
54
|
-
elsif response.code == 0
|
55
|
-
# Could not get an http response, something's wrong.
|
56
|
-
raise IOError.new(response.curl_error_message)
|
57
|
-
else
|
58
|
-
# Received a non-successful http response.
|
59
|
-
raise IOError.new("HTTP request failed: " + response.code.to_s)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
hydra = Typhoeus::Hydra.new
|
64
|
-
hydra.queue(request)
|
65
|
-
hydra.run
|
66
|
-
end
|
67
26
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
else
|
72
|
-
Net::HTTP.get_response(URI.parse(url))
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def get_with_timeout( url, time_out)
|
77
|
-
resp = nil
|
78
|
-
if defined?(SystemTimer)
|
79
|
-
resp = SystemTimer.timeout_after(time_out) do
|
80
|
-
get_response(url, time_out)
|
81
|
-
end
|
82
|
-
else
|
83
|
-
resp = timeout(time_out) do
|
84
|
-
get_response(url, time_out)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
resp
|
27
|
+
# wrapper method for backwards compat.
|
28
|
+
def do_get(url, timeout=5, retries_on_timeout=5, max_redirects = 3)
|
29
|
+
get :url => url, :timeout => timeout, :retries_on_timeout => retries_on_timeout, :max_redirects => max_redirects
|
88
30
|
end
|
31
|
+
|
32
|
+
|
33
|
+
def get(options = {})
|
34
|
+
opts = { :timeout => 5, :retries_on_timeout => 5, :max_redirects => 3, :headers => {} }.merge(options)
|
35
|
+
raise ArgumentError.new(":url is required" ) unless opts[:url]
|
89
36
|
|
90
|
-
|
91
|
-
|
92
|
-
def handle_response( url, resp, retries_on_timeout=5, max_redirects = 3 )
|
93
|
-
if resp.is_a? Net::HTTPSuccess then resp.body
|
94
|
-
elsif resp.is_a? String then resp
|
95
|
-
elsif resp.is_a? Net::HTTPRedirection
|
96
|
-
if max_redirects > 0
|
97
|
-
do_get( URI.parse(url).merge(resp['location']).to_s, retries_on_timeout, max_redirects - 1 )
|
98
|
-
else
|
99
|
-
raise IOError.new("too many redirects!")
|
100
|
-
end
|
101
|
-
else
|
102
|
-
resp.error!
|
103
|
-
end
|
37
|
+
engine_klass = get_engine opts
|
38
|
+
with_timeout(opts) { engine_klass.get(opts) }
|
104
39
|
end
|
105
|
-
|
106
|
-
|
107
|
-
def get( options = {} )
|
108
|
-
opts = {:timeout=>5, :retries_on_timeout=>5, :max_redirects => 3, :headers=>{} }.merge(options)
|
109
|
-
raise ArgumentError.new(":url is required" ) unless opts[:url]
|
110
40
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
raw_get(opts)
|
120
|
-
end
|
121
|
-
else
|
122
|
-
timeout( opts[:timeout] ) do
|
123
|
-
raw_get(opts)
|
124
|
-
end
|
41
|
+
|
42
|
+
|
43
|
+
def with_timeout(opts, &block)
|
44
|
+
retrycount = 0
|
45
|
+
resp = begin
|
46
|
+
if defined?(SystemTimer)
|
47
|
+
SystemTimer.timeout_after(opts[:timeout]) do
|
48
|
+
yield
|
125
49
|
end
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
retry
|
130
|
-
else
|
131
|
-
raise IOError.new( "HTTP request timed out #{retrycount} times" )
|
50
|
+
else
|
51
|
+
timeout( opts[:timeout] ) do
|
52
|
+
yield
|
132
53
|
end
|
133
54
|
end
|
134
|
-
|
55
|
+
rescue ::TimeoutError, ::RestClient::RequestTimeout
|
56
|
+
if(retrycount < opts[:retries_on_timeout])
|
57
|
+
retrycount+=1
|
58
|
+
retry
|
59
|
+
else
|
60
|
+
raise IOError.new( "HTTP request timed out #{retrycount} times" )
|
61
|
+
end
|
135
62
|
end
|
63
|
+
resp
|
136
64
|
end
|
137
|
-
|
138
|
-
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
def get_engine(opts = {})
|
69
|
+
# default to rest_client if not given an engine
|
70
|
+
opts[:http_engine] ||= ( defined?(ITNH_HTTP_ENGINE) ? ITNH_HTTP_ENGINE : default_http_engine )
|
139
71
|
|
140
|
-
if
|
141
|
-
|
142
|
-
end
|
72
|
+
# only use typhoeus if it is actually been required
|
73
|
+
opts[:http_engine] = default_http_engine if opts[:http_engine] == "Typhoeus" && defined?(::Typhoeus) == nil
|
143
74
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
if opts[:username]
|
148
|
-
resp = get_with_auth(opts)
|
149
|
-
retries = 0
|
150
|
-
while resp.is_a? Net::HTTPRedirection do
|
151
|
-
retries += 1
|
152
|
-
raise IOError.new( "HTTP request timed out #{retries} times" ) if retries > (opts[:max_redirects] || 3)
|
153
|
-
|
154
|
-
resp = get_with_auth(opts.merge(:parsed_url=>URI.parse(resp['location'])))
|
155
|
-
end
|
156
|
-
|
157
|
-
resp.body
|
158
|
-
|
75
|
+
if available_http_engines.include?(opts[:http_engine])
|
76
|
+
Itrigga::NetHelper.const_get opts[:http_engine]
|
159
77
|
else
|
160
|
-
|
161
|
-
|
78
|
+
puts "[NetHelper] Could not find http_engine '#{opts[:http_engine]}'. Available engines are: #{available_http_engines.join(',')}. Defaulting to Net::HTTP"
|
79
|
+
Itrigga::NetHelper.const_get default_http_engine
|
162
80
|
end
|
81
|
+
|
163
82
|
end
|
164
|
-
|
165
|
-
def get_with_auth( opts )
|
166
|
-
establish_session_if_needed(opts)
|
167
83
|
|
168
|
-
|
169
|
-
req.basic_auth( opts[:username], opts[:password] ) if opts[:username]
|
170
|
-
resp = opts[:http_session].request(req, opts[:headers])
|
171
|
-
end
|
172
|
-
|
173
|
-
def establish_session_if_needed(opts)
|
174
|
-
opts[:parsed_url] ||= URI.parse(opts[:url])
|
175
|
-
opts[:http_session] ||= Net::HTTP.new(opts[:parsed_url].host, opts[:parsed_url].port)
|
176
|
-
opts[:http_session].use_ssl = true if opts[:parsed_url].scheme == 'https'
|
177
|
-
end
|
84
|
+
|
178
85
|
|
179
86
|
def query_string( h, opts={:encode_values=>false, :skip_empty=>false} )
|
180
87
|
params = []
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Itrigga
|
2
|
+
module NetHelper
|
3
|
+
class RestClient
|
4
|
+
|
5
|
+
def self.get( opts={} )
|
6
|
+
raise ArgumentError.new(":url is required") unless opts[:url]
|
7
|
+
|
8
|
+
# rest_client expects :user and not :username
|
9
|
+
opts[:user] ||= opts.delete(:username) if opts[:username]
|
10
|
+
|
11
|
+
opts[:headers] = {:params => opts.delete(:params)} if opts[:params]
|
12
|
+
|
13
|
+
response = ::RestClient::Request.new(opts.merge(:method => :get)).execute
|
14
|
+
response.to_str
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Itrigga
|
2
|
+
module NetHelper
|
3
|
+
class Typhoeus
|
4
|
+
|
5
|
+
def self.get( opts={} )
|
6
|
+
opts[:timeout] ||= 30
|
7
|
+
opts[:timeout] *= 1000 # Typhoeus does its timeouts in ms
|
8
|
+
opts[:follow_location] ||= true
|
9
|
+
opts[:disable_ssl_peer_verification] = true if opts[:disable_ssl_peer_verification].nil?
|
10
|
+
|
11
|
+
request = ::Typhoeus::Request.new(opts[:url], opts)
|
12
|
+
|
13
|
+
request.on_complete do |response|
|
14
|
+
if response.success?
|
15
|
+
return response.body
|
16
|
+
elsif response.timed_out?
|
17
|
+
# aw hell no
|
18
|
+
raise ::TimeoutError.new("Timed out request to #{opts[:url]} after #{opts[:timeout]}ms")
|
19
|
+
elsif response.code == 0
|
20
|
+
# Could not get an http response, something's wrong.
|
21
|
+
raise IOError.new(response.curl_error_message)
|
22
|
+
else
|
23
|
+
# Received a non-successful http response.
|
24
|
+
raise IOError.new("HTTP request failed: " + response.code.to_s)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
hydra = ::Typhoeus::Hydra.new
|
29
|
+
hydra.queue(request)
|
30
|
+
hydra.run
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper' )
|
2
|
+
|
3
|
+
describe "Itrigga::NetHelper::RestClient" do
|
4
|
+
before do
|
5
|
+
@mock_response = mock("Response", :to_str => "stuff")
|
6
|
+
@client = mock("RestClient::Request")
|
7
|
+
@client.stub!(:execute).and_return(@mock_response)
|
8
|
+
RestClient::Request.stub!(:new).and_return(@client)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise error if no url" do
|
12
|
+
lambda { Itrigga::NetHelper::RestClient.get }.should raise_error(ArgumentError,":url is required")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should call execute on new Request" do
|
16
|
+
RestClient::Request.should_receive(:new).with(hash_including(:method => :get, :url => "abc", :param1 => "blart")).and_return(@client)
|
17
|
+
Itrigga::NetHelper::RestClient.get :url => "abc", :param1 => "blart"
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return the correct value" do
|
21
|
+
@mock_response.should_receive(:to_str).and_return("stuff")
|
22
|
+
Itrigga::NetHelper::RestClient.get(:url => "abc").should == "stuff"
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when given a :username" do
|
26
|
+
it "should convert it to :user" do
|
27
|
+
RestClient::Request.should_receive(:new).with(hash_including(:method => :get, :url => "abc", :user => "blart")).and_return(@client)
|
28
|
+
Itrigga::NetHelper::RestClient.get :url => "abc", :username => "blart"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper' )
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
describe "Itrigga::NetHelper::Typhoeus" do
|
6
|
+
before do
|
7
|
+
# define Typhoeus stubs as not installed as gem dependancy
|
8
|
+
Object.class_eval %{
|
9
|
+
module Typhoeus
|
10
|
+
class Request
|
11
|
+
attr_accessor :on_complete
|
12
|
+
def initialize(url,opts = {}); end
|
13
|
+
def on_complete(&block); @on_complete = block; end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Hydra
|
17
|
+
attr_accessor :request
|
18
|
+
def queue(request); end
|
19
|
+
def run; end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
@opts = {:url => "blart"}
|
25
|
+
@response = mock("Response", :success? => true, :body => "stuff")
|
26
|
+
@request = Typhoeus::Request.new("blart", @opts)
|
27
|
+
# @request.stub!(:on_complete).and_yield(@response)
|
28
|
+
Typhoeus::Request.stub!(:new).and_return(@request)
|
29
|
+
@hydra = Typhoeus::Hydra.new
|
30
|
+
Typhoeus::Hydra.stub!(:new).and_return(@hydra)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
Object.send(:remove_const, :Typhoeus)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should create a Request object" do
|
38
|
+
Typhoeus::Request.should_receive(:new).with("blart",@opts).and_return(@request)
|
39
|
+
Itrigga::NetHelper::Typhoeus.get @opts
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should call queue on hydra" do
|
43
|
+
@hydra.should_receive(:queue).with(@request)
|
44
|
+
Itrigga::NetHelper::Typhoeus.get(@opts)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should call run on hydra" do
|
48
|
+
@hydra.should_receive(:run)
|
49
|
+
Itrigga::NetHelper::Typhoeus.get(@opts)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return the response body" do
|
53
|
+
@request.stub!(:on_complete).and_yield(@response)
|
54
|
+
Itrigga::NetHelper::Typhoeus.get(@opts).should == "stuff"
|
55
|
+
end
|
56
|
+
|
57
|
+
context "a timeout" do
|
58
|
+
before do
|
59
|
+
@response = mock("Response", :success? => false, :timed_out? => true, :body => "stuff")
|
60
|
+
@request.stub!(:on_complete).and_yield(@response)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "should raise a TimeoutError" do
|
64
|
+
lambda { Itrigga::NetHelper::Typhoeus.get(@opts) }.should raise_error(TimeoutError)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context "response code == 0" do
|
69
|
+
before do
|
70
|
+
@response = mock("Response", :success? => false, :timed_out? => false, :code => 0, :body => "stuff", :curl_error_message => "blart")
|
71
|
+
@request.stub!(:on_complete).and_yield(@response)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should raise a TimeoutError" do
|
75
|
+
lambda { Itrigga::NetHelper::Typhoeus.get(@opts) }.should raise_error(IOError)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "any other http status code" do
|
80
|
+
before do
|
81
|
+
@response = mock("Response", :success? => false, :timed_out? => false, :code => 500, :body => "stuff")
|
82
|
+
@request.stub!(:on_complete).and_yield(@response)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should raise a TimeoutError" do
|
86
|
+
lambda { Itrigga::NetHelper::Typhoeus.get(@opts) }.should raise_error(IOError)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|