arachni-typhoeus 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -0
- data/CHANGELOG.markdown +43 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +30 -0
- data/README.textile +6 -0
- data/Rakefile +40 -0
- data/VERSION +1 -0
- data/benchmarks/profile.rb +25 -0
- data/benchmarks/vs_nethttp.rb +35 -0
- data/examples/twitter.rb +21 -0
- data/ext/typhoeus/.gitignore +7 -0
- data/ext/typhoeus/extconf.rb +65 -0
- data/ext/typhoeus/native.c +11 -0
- data/ext/typhoeus/native.h +21 -0
- data/ext/typhoeus/typhoeus_easy.c +220 -0
- data/ext/typhoeus/typhoeus_easy.h +19 -0
- data/ext/typhoeus/typhoeus_multi.c +211 -0
- data/ext/typhoeus/typhoeus_multi.h +16 -0
- data/lib/typhoeus.rb +58 -0
- data/lib/typhoeus/.gitignore +1 -0
- data/lib/typhoeus/easy.rb +366 -0
- data/lib/typhoeus/filter.rb +28 -0
- data/lib/typhoeus/hydra.rb +245 -0
- data/lib/typhoeus/hydra/callbacks.rb +24 -0
- data/lib/typhoeus/hydra/connect_options.rb +61 -0
- data/lib/typhoeus/hydra/stubbing.rb +52 -0
- data/lib/typhoeus/hydra_mock.rb +131 -0
- data/lib/typhoeus/multi.rb +37 -0
- data/lib/typhoeus/normalized_header_hash.rb +58 -0
- data/lib/typhoeus/remote.rb +306 -0
- data/lib/typhoeus/remote_method.rb +108 -0
- data/lib/typhoeus/remote_proxy_object.rb +50 -0
- data/lib/typhoeus/request.rb +210 -0
- data/lib/typhoeus/response.rb +91 -0
- data/lib/typhoeus/service.rb +20 -0
- data/lib/typhoeus/utils.rb +24 -0
- data/profilers/valgrind.rb +24 -0
- data/spec/fixtures/result_set.xml +60 -0
- data/spec/servers/app.rb +84 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/typhoeus/easy_spec.rb +284 -0
- data/spec/typhoeus/filter_spec.rb +35 -0
- data/spec/typhoeus/hydra_mock_spec.rb +300 -0
- data/spec/typhoeus/hydra_spec.rb +526 -0
- data/spec/typhoeus/multi_spec.rb +74 -0
- data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
- data/spec/typhoeus/remote_method_spec.rb +141 -0
- data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
- data/spec/typhoeus/remote_spec.rb +695 -0
- data/spec/typhoeus/request_spec.rb +276 -0
- data/spec/typhoeus/response_spec.rb +151 -0
- data/spec/typhoeus/utils_spec.rb +22 -0
- data/typhoeus.gemspec +123 -0
- metadata +196 -0
data/spec/servers/app.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'sinatra'
|
4
|
+
require 'json'
|
5
|
+
require 'zlib'
|
6
|
+
|
7
|
+
@@fail_count = 0
|
8
|
+
get '/fail/:number' do
|
9
|
+
if @@fail_count >= params[:number].to_i
|
10
|
+
"ok"
|
11
|
+
else
|
12
|
+
@@fail_count += 1
|
13
|
+
error 500, "oh noes!"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/fail_forever' do
|
18
|
+
error 500, "oh noes!"
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/redirect' do
|
22
|
+
redirect '/'
|
23
|
+
end
|
24
|
+
|
25
|
+
get '/bad_redirect' do
|
26
|
+
redirect '/bad_redirect'
|
27
|
+
end
|
28
|
+
|
29
|
+
get '/auth_basic/:username/:password' do
|
30
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
31
|
+
# Check that we've got a basic auth, and that it's credentials match the ones
|
32
|
+
# provided in the request
|
33
|
+
if @auth.provided? && @auth.basic? && @auth.credentials == [ params[:username], params[:password] ]
|
34
|
+
# auth is valid - confirm it
|
35
|
+
true
|
36
|
+
else
|
37
|
+
# invalid auth - request the authentication
|
38
|
+
response['WWW-Authenticate'] = %(Basic realm="Testing HTTP Auth")
|
39
|
+
throw(:halt, [401, "Not authorized\n"])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/auth_ntlm' do
|
44
|
+
# we're just checking for the existence if NTLM auth header here. It's validation
|
45
|
+
# is too troublesome and really doesn't bother is much, it's up to libcurl to make
|
46
|
+
# it valid
|
47
|
+
response['WWW-Authenticate'] = 'NTLM'
|
48
|
+
is_ntlm_auth = /^NTLM/ =~ request.env['HTTP_AUTHORIZATION']
|
49
|
+
true if is_ntlm_auth
|
50
|
+
throw(:halt, [401, "Not authorized\n"]) if !is_ntlm_auth
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/gzipped' do
|
54
|
+
req_env = request.env.to_json
|
55
|
+
z = Zlib::Deflate.new
|
56
|
+
gzipped_env = z.deflate(req_env, Zlib::FINISH)
|
57
|
+
z.close
|
58
|
+
response['Content-Encoding'] = 'gzip'
|
59
|
+
gzipped_env
|
60
|
+
end
|
61
|
+
|
62
|
+
get '/**' do
|
63
|
+
sleep params["delay"].to_i if params.has_key?("delay")
|
64
|
+
request.env.merge!(:body => request.body.read).to_json
|
65
|
+
end
|
66
|
+
|
67
|
+
head '/**' do
|
68
|
+
sleep params["delay"].to_i if params.has_key?("delay")
|
69
|
+
end
|
70
|
+
|
71
|
+
put '/**' do
|
72
|
+
puts request.inspect
|
73
|
+
request.env.merge!(:body => request.body.read).to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
post '/**' do
|
77
|
+
puts request.inspect
|
78
|
+
request.env.merge!(:body => request.body.read).to_json
|
79
|
+
end
|
80
|
+
|
81
|
+
delete '/**' do
|
82
|
+
puts request.inspect
|
83
|
+
request.env.merge!(:body => request.body.read).to_json
|
84
|
+
end
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require 'json'
|
3
|
+
require "spec"
|
4
|
+
|
5
|
+
# gem install redgreen for colored test output
|
6
|
+
begin require "redgreen" unless ENV['TM_CURRENT_LINE']; rescue LoadError; end
|
7
|
+
|
8
|
+
path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
9
|
+
$LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
|
10
|
+
|
11
|
+
require path + '/typhoeus'
|
@@ -0,0 +1,284 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Typhoeus::Easy do
|
4
|
+
describe "#supports_zlib" do
|
5
|
+
before(:each) do
|
6
|
+
@easy = Typhoeus::Easy.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should return true if the version string has zlib" do
|
10
|
+
@easy.stub!(:curl_version).and_return("libcurl/7.20.0 OpenSSL/0.9.8l zlib/1.2.3 libidn/1.16")
|
11
|
+
@easy.supports_zlib?.should be_true
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should return false if the version string doesn't have zlib" do
|
15
|
+
@easy.stub!(:curl_version).and_return("libcurl/7.20.0 OpenSSL/0.9.8l libidn/1.16")
|
16
|
+
@easy.supports_zlib?.should be_false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "curl errors" do
|
21
|
+
it "should provide the CURLE_OPERATION_TIMEDOUT return code when a request times out" do
|
22
|
+
e = Typhoeus::Easy.new
|
23
|
+
e.url = "http://localhost:3001/?delay=1"
|
24
|
+
e.method = :get
|
25
|
+
e.timeout = 100
|
26
|
+
e.perform
|
27
|
+
e.curl_return_code.should == 28
|
28
|
+
e.curl_error_message.should == "Timeout was reached"
|
29
|
+
e.response_code.should == 0
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should provide the CURLE_COULDNT_CONNECT return code when trying to connect to a non existent port" do
|
33
|
+
e = Typhoeus::Easy.new
|
34
|
+
e.url = "http://localhost:3999"
|
35
|
+
e.method = :get
|
36
|
+
e.connect_timeout = 100
|
37
|
+
e.perform
|
38
|
+
e.curl_return_code.should == 7
|
39
|
+
e.curl_error_message.should == "Couldn't connect to server"
|
40
|
+
e.response_code.should == 0
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should not return an error message on a successful easy operation" do
|
44
|
+
easy = Typhoeus::Easy.new
|
45
|
+
easy.url = "http://localhost:3002"
|
46
|
+
easy.method = :get
|
47
|
+
easy.curl_error_message.should == nil
|
48
|
+
easy.perform
|
49
|
+
easy.response_code.should == 200
|
50
|
+
easy.curl_return_code.should == 0
|
51
|
+
easy.curl_error_message.should == "No error"
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "options" do
|
57
|
+
it "should not follow redirects if not instructed to" do
|
58
|
+
e = Typhoeus::Easy.new
|
59
|
+
e.url = "http://localhost:3001/redirect"
|
60
|
+
e.method = :get
|
61
|
+
e.perform
|
62
|
+
e.response_code.should == 302
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should allow for following redirects" do
|
66
|
+
e = Typhoeus::Easy.new
|
67
|
+
e.url = "http://localhost:3001/redirect"
|
68
|
+
e.method = :get
|
69
|
+
e.follow_location = true
|
70
|
+
e.perform
|
71
|
+
e.response_code.should == 200
|
72
|
+
JSON.parse(e.response_body)["REQUEST_METHOD"].should == "GET"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should allow you to set the user agent" do
|
76
|
+
easy = Typhoeus::Easy.new
|
77
|
+
easy.url = "http://localhost:3002"
|
78
|
+
easy.method = :get
|
79
|
+
easy.user_agent = "myapp"
|
80
|
+
easy.perform
|
81
|
+
easy.response_code.should == 200
|
82
|
+
JSON.parse(easy.response_body)["HTTP_USER_AGENT"].should == "myapp"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should provide a timeout in milliseconds" do
|
86
|
+
e = Typhoeus::Easy.new
|
87
|
+
e.url = "http://localhost:3001/?delay=1"
|
88
|
+
e.method = :get
|
89
|
+
e.timeout = 10
|
90
|
+
e.perform
|
91
|
+
e.timed_out?.should == true
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should allow the setting of the max redirects to follow" do
|
95
|
+
e = Typhoeus::Easy.new
|
96
|
+
e.url = "http://localhost:3001/redirect"
|
97
|
+
e.method = :get
|
98
|
+
e.follow_location = true
|
99
|
+
e.max_redirects = 5
|
100
|
+
e.perform
|
101
|
+
e.response_code.should == 200
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should handle our bad redirect action, provided we've set max_redirects properly" do
|
105
|
+
e = Typhoeus::Easy.new
|
106
|
+
e.url = "http://localhost:3001/bad_redirect"
|
107
|
+
e.method = :get
|
108
|
+
e.follow_location = true
|
109
|
+
e.max_redirects = 5
|
110
|
+
e.perform
|
111
|
+
e.response_code.should == 302
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "authentication" do
|
116
|
+
it "should allow to set username and password" do
|
117
|
+
e = Typhoeus::Easy.new
|
118
|
+
username, password = 'foo', 'bar'
|
119
|
+
e.auth = { :username => username, :password => password }
|
120
|
+
e.url = "http://localhost:3001/auth_basic/#{username}/#{password}"
|
121
|
+
e.method = :get
|
122
|
+
e.perform
|
123
|
+
e.response_code.should == 200
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should allow to query auth methods support by the server" do
|
127
|
+
e = Typhoeus::Easy.new
|
128
|
+
e.url = "http://localhost:3001/auth_basic/foo/bar"
|
129
|
+
e.method = :get
|
130
|
+
e.perform
|
131
|
+
e.auth_methods.should == Typhoeus::Easy::AUTH_TYPES[:CURLAUTH_BASIC]
|
132
|
+
end
|
133
|
+
|
134
|
+
it "should allow to set authentication method" do
|
135
|
+
e = Typhoeus::Easy.new
|
136
|
+
e.auth = { :username => 'username', :password => 'password', :method => Typhoeus::Easy::AUTH_TYPES[:CURLAUTH_NTLM] }
|
137
|
+
e.url = "http://localhost:3001/auth_ntlm"
|
138
|
+
e.method = :get
|
139
|
+
e.perform
|
140
|
+
e.response_code.should == 200
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe "get" do
|
145
|
+
it "should perform a get" do
|
146
|
+
easy = Typhoeus::Easy.new
|
147
|
+
easy.url = "http://localhost:3002"
|
148
|
+
easy.method = :get
|
149
|
+
easy.perform
|
150
|
+
easy.response_code.should == 200
|
151
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "GET"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
describe "purge" do
|
156
|
+
it "should set custom request to purge" do
|
157
|
+
easy = Typhoeus::Easy.new
|
158
|
+
easy.should_receive(:set_option).with(Typhoeus::Easy::OPTION_VALUES[:CURLOPT_CUSTOMREQUEST], "PURGE").once
|
159
|
+
easy.method = :purge
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "head" do
|
164
|
+
it "should perform a head" do
|
165
|
+
easy = Typhoeus::Easy.new
|
166
|
+
easy.url = "http://localhost:3002"
|
167
|
+
easy.method = :head
|
168
|
+
easy.perform
|
169
|
+
easy.response_code.should == 200
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
describe "start_time" do
|
174
|
+
it "should be get/settable" do
|
175
|
+
time = Time.now
|
176
|
+
easy = Typhoeus::Easy.new
|
177
|
+
easy.start_time.should be_nil
|
178
|
+
easy.start_time = time
|
179
|
+
easy.start_time.should == time
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
describe "params=" do
|
184
|
+
it "should handle arrays of params" do
|
185
|
+
easy = Typhoeus::Easy.new
|
186
|
+
easy.url = "http://localhost:3002/index.html"
|
187
|
+
easy.method = :get
|
188
|
+
easy.request_body = "this is a body!"
|
189
|
+
easy.params = {
|
190
|
+
:foo => 'bar',
|
191
|
+
:username => ['dbalatero', 'dbalatero2']
|
192
|
+
}
|
193
|
+
|
194
|
+
easy.url.should =~ /\?.*username=dbalatero&username=dbalatero2/
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
|
199
|
+
describe "put" do
|
200
|
+
it "should perform a put" do
|
201
|
+
easy = Typhoeus::Easy.new
|
202
|
+
easy.url = "http://localhost:3002"
|
203
|
+
easy.method = :put
|
204
|
+
easy.perform
|
205
|
+
easy.response_code.should == 200
|
206
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "PUT"
|
207
|
+
end
|
208
|
+
|
209
|
+
it "should send a request body" do
|
210
|
+
easy = Typhoeus::Easy.new
|
211
|
+
easy.url = "http://localhost:3002"
|
212
|
+
easy.method = :put
|
213
|
+
easy.request_body = "this is a body!"
|
214
|
+
easy.perform
|
215
|
+
easy.response_code.should == 200
|
216
|
+
easy.response_body.should include("this is a body!")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
describe "post" do
|
221
|
+
it "should perform a post" do
|
222
|
+
easy = Typhoeus::Easy.new
|
223
|
+
easy.url = "http://localhost:3002"
|
224
|
+
easy.method = :post
|
225
|
+
easy.perform
|
226
|
+
easy.response_code.should == 200
|
227
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "POST"
|
228
|
+
end
|
229
|
+
|
230
|
+
it "should send a request body" do
|
231
|
+
easy = Typhoeus::Easy.new
|
232
|
+
easy.url = "http://localhost:3002"
|
233
|
+
easy.method = :post
|
234
|
+
easy.request_body = "this is a body!"
|
235
|
+
easy.perform
|
236
|
+
easy.response_code.should == 200
|
237
|
+
easy.response_body.should include("this is a body!")
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should handle params" do
|
241
|
+
easy = Typhoeus::Easy.new
|
242
|
+
easy.url = "http://localhost:3002"
|
243
|
+
easy.method = :post
|
244
|
+
easy.params = {:foo => "bar"}
|
245
|
+
easy.perform
|
246
|
+
easy.response_code.should == 200
|
247
|
+
easy.response_body.should include("foo=bar")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
describe "delete" do
|
252
|
+
it "should perform a delete" do
|
253
|
+
easy = Typhoeus::Easy.new
|
254
|
+
easy.url = "http://localhost:3002"
|
255
|
+
easy.method = :delete
|
256
|
+
easy.perform
|
257
|
+
easy.response_code.should == 200
|
258
|
+
JSON.parse(easy.response_body)["REQUEST_METHOD"].should == "DELETE"
|
259
|
+
end
|
260
|
+
|
261
|
+
it "should send a request body" do
|
262
|
+
easy = Typhoeus::Easy.new
|
263
|
+
easy.url = "http://localhost:3002"
|
264
|
+
easy.method = :delete
|
265
|
+
easy.request_body = "this is a body!"
|
266
|
+
easy.perform
|
267
|
+
easy.response_code.should == 200
|
268
|
+
easy.response_body.should include("this is a body!")
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe "encoding/compression support" do
|
273
|
+
|
274
|
+
it "should send valid encoding headers and decode the response" do
|
275
|
+
easy = Typhoeus::Easy.new
|
276
|
+
easy.url = "http://localhost:3002/gzipped"
|
277
|
+
easy.method = :get
|
278
|
+
easy.perform
|
279
|
+
easy.response_code.should == 200
|
280
|
+
JSON.parse(easy.response_body)["HTTP_ACCEPT_ENCODING"].should == "deflate, gzip"
|
281
|
+
end
|
282
|
+
|
283
|
+
end
|
284
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
2
|
+
|
3
|
+
describe Typhoeus::Filter do
|
4
|
+
it "should take a method name and optionally take options" do
|
5
|
+
filter = Typhoeus::Filter.new(:bar, :only => :foo)
|
6
|
+
filter = Typhoeus::Filter.new(:bar)
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#apply_filter?" do
|
10
|
+
it "should return true for any method when :only and :except aren't specified" do
|
11
|
+
filter = Typhoeus::Filter.new(:bar)
|
12
|
+
filter.apply_filter?(:asdf).should be_true
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return true if a method is in only" do
|
16
|
+
filter = Typhoeus::Filter.new(:bar, :only => :foo)
|
17
|
+
filter.apply_filter?(:foo).should be_true
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return false if a method isn't in only" do
|
21
|
+
filter = Typhoeus::Filter.new(:bar, :only => :foo)
|
22
|
+
filter.apply_filter?(:bar).should be_false
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return true if a method isn't in except" do
|
26
|
+
filter = Typhoeus::Filter.new(:bar, :except => :foo)
|
27
|
+
filter.apply_filter?(:bar).should be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return false if a method is in except" do
|
31
|
+
filter = Typhoeus::Filter.new(:bar, :except => :foo)
|
32
|
+
filter.apply_filter?(:foo).should be_false
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/../spec_helper")
|
2
|
+
|
3
|
+
describe Typhoeus::HydraMock do
|
4
|
+
it "should mark all responses as mocks" do
|
5
|
+
response = Typhoeus::Response.new(:mock => false)
|
6
|
+
response.should_not be_mock
|
7
|
+
|
8
|
+
mock = Typhoeus::HydraMock.new("http://localhost", :get)
|
9
|
+
mock.and_return(response)
|
10
|
+
|
11
|
+
mock.response.should be_mock
|
12
|
+
response.should be_mock
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "stubbing response values" do
|
16
|
+
before(:each) do
|
17
|
+
@stub = Typhoeus::HydraMock.new('http://localhost:3000', :get)
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "with a single response" do
|
21
|
+
it "should always return that response" do
|
22
|
+
response = Typhoeus::Response.new
|
23
|
+
@stub.and_return(response)
|
24
|
+
|
25
|
+
5.times do
|
26
|
+
@stub.response.should == response
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "with multiple responses" do
|
32
|
+
it "should return consecutive responses in the array, then keep returning the last one" do
|
33
|
+
responses = []
|
34
|
+
3.times do |i|
|
35
|
+
responses << Typhoeus::Response.new(:body => "response #{i}")
|
36
|
+
end
|
37
|
+
|
38
|
+
# Stub 3 consecutive responses.
|
39
|
+
@stub.and_return(responses)
|
40
|
+
|
41
|
+
0.upto(2) do |i|
|
42
|
+
@stub.response.should == responses[i]
|
43
|
+
end
|
44
|
+
|
45
|
+
5.times do
|
46
|
+
@stub.response.should == responses.last
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#matches?" do
|
53
|
+
describe "basic matching" do
|
54
|
+
it "should not match if the HTTP verbs are different" do
|
55
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
56
|
+
:method => :get)
|
57
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :post)
|
58
|
+
mock.matches?(request).should be_false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "matching on ports" do
|
63
|
+
it "should handle default port 80 sanely" do
|
64
|
+
mock = Typhoeus::HydraMock.new('http://www.example.com:80/', :get,
|
65
|
+
:headers => { 'user-agent' => 'test' })
|
66
|
+
request = Typhoeus::Request.new('http://www.example.com/',
|
67
|
+
:method => :get,
|
68
|
+
:user_agent => 'test')
|
69
|
+
mock.matches?(request).should be_true
|
70
|
+
end
|
71
|
+
|
72
|
+
it "should handle default port 443 sanely" do
|
73
|
+
mock = Typhoeus::HydraMock.new('https://www.example.com:443/', :get,
|
74
|
+
:headers => { 'user-agent' => 'test' })
|
75
|
+
request = Typhoeus::Request.new('https://www.example.com/',
|
76
|
+
:method => :get,
|
77
|
+
:user_agent => 'test')
|
78
|
+
mock.matches?(request).should be_true
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
describe "any HTTP verb" do
|
84
|
+
it "should match any verb" do
|
85
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :any,
|
86
|
+
:headers => { 'user-agent' => 'test' })
|
87
|
+
[:get, :post, :delete, :put].each do |verb|
|
88
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
89
|
+
:method => verb,
|
90
|
+
:user_agent => 'test')
|
91
|
+
mock.matches?(request).should be_true
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "header matching" do
|
97
|
+
def request(options = {})
|
98
|
+
Typhoeus::Request.new("http://localhost:3000", options.merge(:method => :get))
|
99
|
+
end
|
100
|
+
|
101
|
+
def mock(options = {})
|
102
|
+
Typhoeus::HydraMock.new("http://localhost:3000", :get, options)
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'when no :headers option is given' do
|
106
|
+
subject { mock }
|
107
|
+
|
108
|
+
it "matches regardless of whether or not the request has headers" do
|
109
|
+
subject.matches?(request(:headers => nil)).should be_true
|
110
|
+
subject.matches?(request(:headers => {})).should be_true
|
111
|
+
subject.matches?(request(:headers => { 'a' => 'b' })).should be_true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
[nil, {}].each do |value|
|
116
|
+
context "for :headers => #{value.inspect}" do
|
117
|
+
subject { mock(:headers => value) }
|
118
|
+
|
119
|
+
it "matches when the request has no headers" do
|
120
|
+
subject.matches?(request(:headers => nil)).should be_true
|
121
|
+
subject.matches?(request(:headers => {})).should be_true
|
122
|
+
end
|
123
|
+
|
124
|
+
it "does not match when the request has headers" do
|
125
|
+
subject.matches?(request(:headers => { 'a' => 'b' })).should be_false
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'for :headers => [a hash]' do
|
131
|
+
it 'does not match if the request has no headers' do
|
132
|
+
m = mock(:headers => { 'A' => 'B', 'C' => 'D' })
|
133
|
+
|
134
|
+
m.matches?(request).should be_false
|
135
|
+
m.matches?(request(:headers => nil)).should be_false
|
136
|
+
m.matches?(request(:headers => {})).should be_false
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'does not match if the request lacks any of the given headers' do
|
140
|
+
mock(
|
141
|
+
:headers => { 'A' => 'B', 'C' => 'D' }
|
142
|
+
).matches?(request(
|
143
|
+
:headers => { 'A' => 'B' }
|
144
|
+
)).should be_false
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'does not match if any of the specified values are different from the request value' do
|
148
|
+
mock(
|
149
|
+
:headers => { 'A' => 'B', 'C' => 'D' }
|
150
|
+
).matches?(request(
|
151
|
+
:headers => { 'A' => 'B', 'C' => 'E' }
|
152
|
+
)).should be_false
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'matches if the given hash is exactly equal to the request headers' do
|
156
|
+
mock(
|
157
|
+
:headers => { 'A' => 'B', 'C' => 'D' }
|
158
|
+
).matches?(request(
|
159
|
+
:headers => { 'A' => 'B', 'C' => 'D' }
|
160
|
+
)).should be_true
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'matches even if the request has additional headers not specified in the mock' do
|
164
|
+
mock(
|
165
|
+
:headers => { 'A' => 'B', 'C' => 'D' }
|
166
|
+
).matches?(request(
|
167
|
+
:headers => { 'A' => 'B', 'C' => 'D', 'E' => 'F' }
|
168
|
+
)).should be_true
|
169
|
+
end
|
170
|
+
|
171
|
+
it 'matches even if the casing of the header keys is different between the mock and request' do
|
172
|
+
mock(
|
173
|
+
:headers => { 'A' => 'B', 'c' => 'D' }
|
174
|
+
).matches?(request(
|
175
|
+
:headers => { 'a' => 'B', 'C' => 'D' }
|
176
|
+
)).should be_true
|
177
|
+
end
|
178
|
+
|
179
|
+
it 'matches if the mocked values are regexes and match the request values' do
|
180
|
+
mock(
|
181
|
+
:headers => { 'A' => /foo/, }
|
182
|
+
).matches?(request(
|
183
|
+
:headers => { 'A' => 'foo bar' }
|
184
|
+
)).should be_true
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'does not match if the mocked values are regexes and do not match the request values' do
|
188
|
+
mock(
|
189
|
+
:headers => { 'A' => /foo/, }
|
190
|
+
).matches?(request(
|
191
|
+
:headers => { 'A' => 'bar' }
|
192
|
+
)).should be_false
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when a header is specified as an array' do
|
196
|
+
it 'matches when the request header has the same array' do
|
197
|
+
mock(
|
198
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
199
|
+
).matches?(request(
|
200
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
201
|
+
)).should be_true
|
202
|
+
end
|
203
|
+
|
204
|
+
it 'matches when the request header is a single value and the mock array has the same value' do
|
205
|
+
mock(
|
206
|
+
:headers => { 'Accept' => ['text/html'] }
|
207
|
+
).matches?(request(
|
208
|
+
:headers => { 'Accept' => 'text/html' }
|
209
|
+
)).should be_true
|
210
|
+
end
|
211
|
+
|
212
|
+
it 'matches even when the request header array is ordered differently' do
|
213
|
+
mock(
|
214
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
215
|
+
).matches?(request(
|
216
|
+
:headers => { 'Accept' => ['text/plain', 'text/html'] }
|
217
|
+
)).should be_true
|
218
|
+
end
|
219
|
+
|
220
|
+
it 'does not match when the request header array lacks a value' do
|
221
|
+
mock(
|
222
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
223
|
+
).matches?(request(
|
224
|
+
:headers => { 'Accept' => ['text/plain'] }
|
225
|
+
)).should be_false
|
226
|
+
end
|
227
|
+
|
228
|
+
it 'does not match when the request header array has an extra value' do
|
229
|
+
mock(
|
230
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
231
|
+
).matches?(request(
|
232
|
+
:headers => { 'Accept' => ['text/html', 'text/plain', 'application/xml'] }
|
233
|
+
)).should be_false
|
234
|
+
end
|
235
|
+
|
236
|
+
it 'does not match when the request header is not an array' do
|
237
|
+
mock(
|
238
|
+
:headers => { 'Accept' => ['text/html', 'text/plain'] }
|
239
|
+
).matches?(request(
|
240
|
+
:headers => { 'Accept' => 'text/html' }
|
241
|
+
)).should be_false
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
describe "post body matching" do
|
248
|
+
it "should not bother matching on body if we don't turn the option on" do
|
249
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
250
|
+
:method => :get,
|
251
|
+
:user_agent => 'test',
|
252
|
+
:body => "fdsafdsa")
|
253
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :get,
|
254
|
+
:headers => { 'user-agent' => 'test' })
|
255
|
+
mock.matches?(request).should be_true
|
256
|
+
end
|
257
|
+
|
258
|
+
it "should match nil correctly" do
|
259
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
260
|
+
:method => :get,
|
261
|
+
:body => "fdsafdsa")
|
262
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :get,
|
263
|
+
:body => nil)
|
264
|
+
mock.matches?(request).should be_false
|
265
|
+
end
|
266
|
+
|
267
|
+
it "should not match if the bodies do not match" do
|
268
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
269
|
+
:method => :get,
|
270
|
+
:body => "ffdsadsafdsa")
|
271
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :get,
|
272
|
+
:body => 'fdsafdsa')
|
273
|
+
mock.matches?(request).should be_false
|
274
|
+
end
|
275
|
+
|
276
|
+
it "should match on optional body parameter" do
|
277
|
+
request = Typhoeus::Request.new("http://localhost:3000",
|
278
|
+
:method => :get,
|
279
|
+
:user_agent => 'test',
|
280
|
+
:body => "fdsafdsa")
|
281
|
+
mock = Typhoeus::HydraMock.new("http://localhost:3000", :get,
|
282
|
+
:body => 'fdsafdsa',
|
283
|
+
:headers => {
|
284
|
+
'User-Agent' => 'test'
|
285
|
+
})
|
286
|
+
mock.matches?(request).should be_true
|
287
|
+
end
|
288
|
+
|
289
|
+
it "should regex match" do
|
290
|
+
request = Typhoeus::Request.new("http://localhost:3000/whatever/fdsa",
|
291
|
+
:method => :get,
|
292
|
+
:user_agent => 'test')
|
293
|
+
mock = Typhoeus::HydraMock.new(/fdsa/, :get,
|
294
|
+
:headers => { 'user-agent' => 'test' })
|
295
|
+
mock.matches?(request).should be_true
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|