marnen-typhoeus 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. data/CHANGELOG.markdown +84 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +56 -0
  4. data/LICENSE +20 -0
  5. data/Rakefile +43 -0
  6. data/ext/typhoeus/.gitignore +7 -0
  7. data/ext/typhoeus/extconf.rb +65 -0
  8. data/ext/typhoeus/native.c +12 -0
  9. data/ext/typhoeus/native.h +22 -0
  10. data/ext/typhoeus/typhoeus_easy.c +232 -0
  11. data/ext/typhoeus/typhoeus_easy.h +20 -0
  12. data/ext/typhoeus/typhoeus_form.c +59 -0
  13. data/ext/typhoeus/typhoeus_form.h +13 -0
  14. data/ext/typhoeus/typhoeus_multi.c +217 -0
  15. data/ext/typhoeus/typhoeus_multi.h +16 -0
  16. data/lib/typhoeus.rb +58 -0
  17. data/lib/typhoeus/.gitignore +1 -0
  18. data/lib/typhoeus/easy.rb +413 -0
  19. data/lib/typhoeus/filter.rb +28 -0
  20. data/lib/typhoeus/form.rb +32 -0
  21. data/lib/typhoeus/hydra.rb +250 -0
  22. data/lib/typhoeus/hydra/callbacks.rb +24 -0
  23. data/lib/typhoeus/hydra/connect_options.rb +61 -0
  24. data/lib/typhoeus/hydra/stubbing.rb +68 -0
  25. data/lib/typhoeus/hydra_mock.rb +131 -0
  26. data/lib/typhoeus/multi.rb +37 -0
  27. data/lib/typhoeus/normalized_header_hash.rb +58 -0
  28. data/lib/typhoeus/remote.rb +306 -0
  29. data/lib/typhoeus/remote_method.rb +108 -0
  30. data/lib/typhoeus/remote_proxy_object.rb +50 -0
  31. data/lib/typhoeus/request.rb +269 -0
  32. data/lib/typhoeus/response.rb +122 -0
  33. data/lib/typhoeus/service.rb +20 -0
  34. data/lib/typhoeus/utils.rb +74 -0
  35. data/lib/typhoeus/version.rb +3 -0
  36. data/spec/fixtures/placeholder.gif +0 -0
  37. data/spec/fixtures/placeholder.txt +1 -0
  38. data/spec/fixtures/placeholder.ukn +0 -0
  39. data/spec/fixtures/result_set.xml +60 -0
  40. data/spec/servers/app.rb +97 -0
  41. data/spec/spec_helper.rb +19 -0
  42. data/spec/support/typhoeus_localhost_server.rb +58 -0
  43. data/spec/typhoeus/easy_spec.rb +391 -0
  44. data/spec/typhoeus/filter_spec.rb +35 -0
  45. data/spec/typhoeus/form_spec.rb +117 -0
  46. data/spec/typhoeus/hydra_mock_spec.rb +300 -0
  47. data/spec/typhoeus/hydra_spec.rb +602 -0
  48. data/spec/typhoeus/multi_spec.rb +74 -0
  49. data/spec/typhoeus/normalized_header_hash_spec.rb +41 -0
  50. data/spec/typhoeus/remote_method_spec.rb +141 -0
  51. data/spec/typhoeus/remote_proxy_object_spec.rb +65 -0
  52. data/spec/typhoeus/remote_spec.rb +695 -0
  53. data/spec/typhoeus/request_spec.rb +387 -0
  54. data/spec/typhoeus/response_spec.rb +192 -0
  55. data/spec/typhoeus/utils_spec.rb +22 -0
  56. data/typhoeus.gemspec +35 -0
  57. metadata +235 -0
@@ -0,0 +1,387 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus::Request do
4
+ describe "#inspect" do
5
+ before(:each) do
6
+ @request = Typhoeus::Request.new('http://www.google.com/',
7
+ :body => "a=1&b=2",
8
+ :params => { :c => 'ok' },
9
+ :method => :get,
10
+ :headers => { 'Content-Type' => 'text/html' })
11
+ end
12
+
13
+ it "should dump out the URI" do
14
+ @request.inspect.should =~ /http:\/\/www\.google\.com/
15
+ end
16
+
17
+ it "should dump out the body" do
18
+ @request.inspect.should =~ /a=1&b=2/
19
+ end
20
+
21
+ it "should dump params" do
22
+ @request.inspect.should =~ /:c\s*=>\s*"ok"/
23
+ end
24
+
25
+ it "should dump the method" do
26
+ @request.inspect.should =~ /:get/
27
+ end
28
+
29
+ it "should dump out headers" do
30
+ @request.inspect.should =~ /"Content-Type"\s*=>\s*"text\/html"/
31
+ end
32
+ end
33
+
34
+ context "marshalling" do
35
+
36
+ let(:request) do
37
+ Typhoeus::Request.new("http://google.com")
38
+ end
39
+
40
+ describe "#marshal_dump" do
41
+ context "when an on_complete handler is defined" do
42
+
43
+ before do
44
+ request.on_complete {}
45
+ end
46
+
47
+ it "does not raise an error" do
48
+ lambda { Marshal.dump(request) }.should_not raise_error(TypeError)
49
+ end
50
+
51
+ end
52
+
53
+ context "when an after_complete handler is defined" do
54
+
55
+ before do
56
+ request.after_complete {}
57
+ end
58
+
59
+ it "does not raise an error" do
60
+ lambda { Marshal.dump(request) }.should_not raise_error(TypeError)
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ it "is reversible but exclude handlers" do
68
+ request.on_complete {}
69
+ request.after_complete {}
70
+
71
+ new_request = Marshal.load(Marshal.dump(request))
72
+
73
+ new_request.url.should == request.url
74
+ new_request.on_complete.should be_nil
75
+ new_request.after_complete.should be_nil
76
+ end
77
+
78
+ end
79
+
80
+ describe "#localhost?" do
81
+ %w(localhost 127.0.0.1 0.0.0.0).each do |host|
82
+ it "should be true for the #{host} host" do
83
+ req = Typhoeus::Request.new("http://#{host}")
84
+ req.should be_localhost
85
+ end
86
+ end
87
+
88
+ it "should be false for other domains" do
89
+ req = Typhoeus::Request.new("http://google.com")
90
+ req.should_not be_localhost
91
+ end
92
+ end
93
+
94
+ describe "#params_string" do
95
+ it "should dump a sorted string" do
96
+ request = Typhoeus::Request.new(
97
+ "http://google.com",
98
+ :params => {
99
+ 'b' => 'fdsa',
100
+ 'a' => 'jlk',
101
+ 'c' => '789'
102
+ }
103
+ )
104
+
105
+ request.params_string.should == "a=jlk&b=fdsa&c=789"
106
+ end
107
+
108
+ it "should accept symboled keys" do
109
+ request = Typhoeus::Request.new('http://google.com',
110
+ :params => {
111
+ :b => 'fdsa',
112
+ :a => 'jlk',
113
+ :c => '789'
114
+ })
115
+ request.params_string.should == "a=jlk&b=fdsa&c=789"
116
+ end
117
+
118
+ it "should translate params with values that are arrays to the proper format" do
119
+ request = Typhoeus::Request.new('http://google.com',
120
+ :params => {
121
+ :a => ['789','2434']
122
+ })
123
+ request.params_string.should == "a=789&a=2434"
124
+ end
125
+
126
+ it "should allow the newer bracket notation for array params" do
127
+ request = Typhoeus::Request.new('http://google.com',
128
+ :params => {
129
+ "a[]" => ['789','2434']
130
+ })
131
+ request.params_string.should == "a%5B%5D=789&a%5B%5D=2434"
132
+ end
133
+
134
+ it "should nest arrays in hashes" do
135
+ request = Typhoeus::Request.new('http://google.com',
136
+ :params => {
137
+ :a => { :b => { :c => ['d','e'] } }
138
+ })
139
+ request.params_string.should == "a%5Bb%5D%5Bc%5D=d&a%5Bb%5D%5Bc%5D=e"
140
+ end
141
+
142
+ it "should translate nested params correctly" do
143
+ request = Typhoeus::Request.new('http://google.com',
144
+ :params => {
145
+ :a => { :b => { :c => 'd' } }
146
+ })
147
+ request.params_string.should == "a%5Bb%5D%5Bc%5D=d"
148
+ end
149
+ end
150
+
151
+ describe "quick request methods" do
152
+ it "can run a GET synchronously" do
153
+ response = Typhoeus::Request.get("http://localhost:3000", :params => {:q => "hi"}, :headers => {:foo => "bar"})
154
+ response.code.should == 200
155
+ JSON.parse(response.body)["REQUEST_METHOD"].should == "GET"
156
+ end
157
+
158
+ it "can run a POST synchronously" do
159
+ response = Typhoeus::Request.post("http://localhost:3000", :params => {:q => { :a => "hi" } }, :headers => {:foo => "bar"})
160
+ response.code.should == 200
161
+
162
+ json = JSON.parse(response.body)
163
+ json["REQUEST_METHOD"].should == "POST"
164
+ json["rack.request.form_hash"]["q"]["a"].should == "hi"
165
+ end
166
+
167
+ it "can run a PUT synchronously" do
168
+ response = Typhoeus::Request.put("http://localhost:3000", :params => {:q => "hi"}, :headers => {:foo => "bar"})
169
+ response.code.should == 200
170
+ JSON.parse(response.body)["REQUEST_METHOD"].should == "PUT"
171
+ end
172
+
173
+ it "can run a DELETE synchronously" do
174
+ response = Typhoeus::Request.delete("http://localhost:3000", :params => {:q => "hi"}, :headers => {:foo => "bar"})
175
+ response.code.should == 200
176
+ JSON.parse(response.body)["REQUEST_METHOD"].should == "DELETE"
177
+ end
178
+ end
179
+
180
+ it "takes url as the first argument" do
181
+ Typhoeus::Request.new("http://localhost:3000").url.should == "http://localhost:3000"
182
+ end
183
+
184
+ it "should parse the host from the url" do
185
+ Typhoeus::Request.new("http://localhost:3000/whatever?hi=foo").host.should == "http://localhost:3000"
186
+ Typhoeus::Request.new("http://localhost:3000?hi=foo").host.should == "http://localhost:3000"
187
+ Typhoeus::Request.new("http://localhost:3000").host.should == "http://localhost:3000"
188
+ end
189
+
190
+ it "takes method as an option" do
191
+ Typhoeus::Request.new("http://localhost:3000", :method => :get).method.should == :get
192
+ end
193
+
194
+ it "takes headers as an option" do
195
+ headers = {:foo => :bar}
196
+ request = Typhoeus::Request.new("http://localhost:3000", :headers => headers)
197
+ request.headers.should == headers
198
+ end
199
+
200
+ it "takes params as an option and adds them to the url" do
201
+ Typhoeus::Request.new("http://localhost:3000", :params => {:foo => "bar"}).url.should == "http://localhost:3000?foo=bar"
202
+ end
203
+
204
+ it "takes request body as an option" do
205
+ Typhoeus::Request.new("http://localhost:3000", :body => "whatever").body.should == "whatever"
206
+ end
207
+
208
+ it "takes timeout as an option" do
209
+ Typhoeus::Request.new("http://localhost:3000", :timeout => 10).timeout.should == 10
210
+ end
211
+
212
+ it "accepts a string for the timeout option" do
213
+ Typhoeus::Request.new("http://localhost:3000", :timeout => "150").timeout.should == 150
214
+ end
215
+
216
+ it "doesn't convert a nil timeout to an integer" do
217
+ Typhoeus::Request.new("http://localhost:3000", :timeout => nil).timeout.should_not == nil.to_i
218
+ end
219
+
220
+ it "doesn't convert an empty timeout to an integer" do
221
+ Typhoeus::Request.new("http://localhost:3000", :timeout => "").timeout.should_not == "".to_i
222
+ end
223
+
224
+ it "takes connect_timeout as an option" do
225
+ Typhoeus::Request.new("http://localhost:3000", :connect_timeout => 14).connect_timeout.should == 14
226
+ end
227
+
228
+ it "accepts a string for the connect_timeout option" do
229
+ Typhoeus::Request.new("http://localhost:3000", :connect_timeout => "420").connect_timeout.should == 420
230
+ end
231
+
232
+ it "doesn't convert a nil connect_timeout to an integer" do
233
+ Typhoeus::Request.new("http://localhost:3000", :connect_timeout => nil).connect_timeout.should_not == nil.to_i
234
+ end
235
+
236
+ it "doesn't convert an empty connect_timeout to an integer" do
237
+ Typhoeus::Request.new("http://localhost:3000", :connect_timeout => "").connect_timeout.should_not == "".to_i
238
+ end
239
+
240
+ it "takes cache_timeout as an option" do
241
+ Typhoeus::Request.new("http://localhost:3000", :cache_timeout => 60).cache_timeout.should == 60
242
+ end
243
+
244
+ it "accepts a string for the cache_timeout option" do
245
+ Typhoeus::Request.new("http://localhost:3000", :cache_timeout => "42").cache_timeout.should == 42
246
+ end
247
+
248
+ it "doesn't convert a nil cache_timeout to an integer" do
249
+ Typhoeus::Request.new("http://localhost:3000", :cache_timeout => nil).cache_timeout.should_not == nil.to_i
250
+ end
251
+
252
+ it "doesn't convert an empty cache_timeout to an integer" do
253
+ Typhoeus::Request.new("http://localhost:3000", :cache_timeout => "").cache_timeout.should_not == "".to_i
254
+ end
255
+
256
+ it "takes follow_location as an option" do
257
+ Typhoeus::Request.new("http://localhost:3000", :follow_location => true).follow_location.should == true
258
+ end
259
+
260
+ it "takes max_redirects as an option" do
261
+ Typhoeus::Request.new("http://localhost:3000", :max_redirects => 10).max_redirects.should == 10
262
+ end
263
+
264
+ it "has the associated response object" do
265
+ request = Typhoeus::Request.new("http://localhost:3000")
266
+ request.response = :foo
267
+ request.response.should == :foo
268
+ end
269
+
270
+ it "has an on_complete handler that is called when the request is completed" do
271
+ request = Typhoeus::Request.new("http://localhost:3000")
272
+ foo = nil
273
+ request.on_complete do |response|
274
+ foo = response
275
+ end
276
+ request.response = :bar
277
+ request.call_handlers
278
+ foo.should == :bar
279
+ end
280
+
281
+ it "has an on_complete setter" do
282
+ foo = nil
283
+ proc = Proc.new {|response| foo = response}
284
+ request = Typhoeus::Request.new("http://localhost:3000")
285
+ request.on_complete = proc
286
+ request.response = :bar
287
+ request.call_handlers
288
+ foo.should == :bar
289
+ end
290
+
291
+ it "stores the handled response that is the return value from the on_complete block" do
292
+ request = Typhoeus::Request.new("http://localhost:3000")
293
+ request.on_complete do |response|
294
+ "handled"
295
+ end
296
+ request.response = :bar
297
+ request.call_handlers
298
+ request.handled_response.should == "handled"
299
+ end
300
+
301
+ it "has an after_complete handler that recieves what on_complete returns" do
302
+ request = Typhoeus::Request.new("http://localhost:3000")
303
+ request.on_complete do |response|
304
+ "handled"
305
+ end
306
+ good = nil
307
+ request.after_complete do |object|
308
+ good = object == "handled"
309
+ end
310
+ request.call_handlers
311
+ good.should be_true
312
+ end
313
+
314
+ it "has an after_complete setter" do
315
+ request = Typhoeus::Request.new("http://localhost:3000")
316
+ request.on_complete do |response|
317
+ "handled"
318
+ end
319
+ good = nil
320
+ proc = Proc.new {|object| good = object == "handled"}
321
+ request.after_complete = proc
322
+
323
+ request.call_handlers
324
+ good.should be_true
325
+ end
326
+
327
+ describe "time info" do
328
+ it "should have time" do
329
+ response = Typhoeus::Request.get("http://localhost:3000")
330
+ response.time.should > 0
331
+ end
332
+
333
+ it "should have connect time" do
334
+ response = Typhoeus::Request.get("http://localhost:3000")
335
+ response.connect_time.should > 0
336
+ end
337
+
338
+ it "should have app connect time" do
339
+ response = Typhoeus::Request.get("http://localhost:3000")
340
+ response.app_connect_time.should > 0
341
+ end
342
+
343
+ it "should have start transfer time" do
344
+ response = Typhoeus::Request.get("http://localhost:3000")
345
+ response.start_transfer_time.should > 0
346
+ end
347
+
348
+ it "should have pre-transfer time" do
349
+ response = Typhoeus::Request.get("http://localhost:3000")
350
+ response.pretransfer_time.should > 0
351
+ end
352
+
353
+ end
354
+
355
+
356
+ describe "authentication" do
357
+
358
+ it "should allow to set username and password" do
359
+ auth = { :username => 'foo', :password => 'bar' }
360
+ e = Typhoeus::Request.get(
361
+ "http://localhost:3001/auth_basic/#{auth[:username]}/#{auth[:password]}",
362
+ auth
363
+ )
364
+ e.code.should == 200
365
+ end
366
+
367
+ it "should allow to set authentication method" do
368
+ auth = {
369
+ :username => 'username',
370
+ :password => 'password',
371
+ :auth_method => :ntlm
372
+ }
373
+ e = Typhoeus::Request.get(
374
+ "http://localhost:3001/auth_ntlm",
375
+ auth
376
+ )
377
+ e.code.should == 200
378
+ end
379
+
380
+ end
381
+
382
+ describe "retry" do
383
+ it "should take a retry option"
384
+ it "should count the number of times a request has failed"
385
+ end
386
+
387
+ end
@@ -0,0 +1,192 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe Typhoeus::Response do
4
+ describe "timed_out?" do
5
+ it "should return true if curl return code is 28" do
6
+ response = Typhoeus::Response.new(:curl_return_code => 28)
7
+ response.should be_timed_out
8
+ end
9
+
10
+ it "should return false for not 28" do
11
+ response = Typhoeus::Response.new(:curl_return_code => 14)
12
+ response.should_not be_timed_out
13
+ end
14
+ end
15
+
16
+ describe "initialize" do
17
+ it "should store headers_hash" do
18
+ response = Typhoeus::Response.new(:headers_hash => {})
19
+ response.headers_hash.should == {}
20
+ end
21
+
22
+ it "allows header access using a different casing of the header key" do
23
+ response = Typhoeus::Response.new(:headers_hash => { 'content-type' => 'text/html' } )
24
+ response.headers_hash['Content-Type'].should == 'text/html'
25
+ end
26
+
27
+ it "should store response_code" do
28
+ Typhoeus::Response.new(:code => 200).code.should == 200
29
+ end
30
+
31
+ it "should store status_message" do
32
+ Typhoeus::Response.new(:status_message => 'Not Found').status_message.should == 'Not Found'
33
+ end
34
+
35
+ it "should return nil for status_message if none is given and no header is given" do
36
+ Typhoeus::Response.new.status_message.should be_nil
37
+ end
38
+
39
+ it "should return nil for status_message if a message-less header is given" do
40
+ Typhoeus::Response.new(:headers => "HTTP/1.1 200\r\n").status_message.should == nil
41
+ end
42
+
43
+ it "should store http_version" do
44
+ Typhoeus::Response.new(:http_version => '1.1').http_version.should == '1.1'
45
+ end
46
+
47
+ it "should return nil for http version if none is given and no header is given" do
48
+ Typhoeus::Response.new.http_version.should be_nil
49
+ end
50
+
51
+ it "should return nil for http version if an invalid or incomplete header is given" do
52
+ Typhoeus::Response.new(:headers => "HTTP foo/bar 200 OK\r\n").http_version.should == nil
53
+ end
54
+
55
+ it "should store response_headers" do
56
+ Typhoeus::Response.new(:headers => "a header!").headers.should == "a header!"
57
+ end
58
+
59
+ it "should store response_body" do
60
+ Typhoeus::Response.new(:body => "a body!").body.should == "a body!"
61
+ end
62
+
63
+ it "should store request_time" do
64
+ Typhoeus::Response.new(:time => 1.23).time.should == 1.23
65
+ end
66
+
67
+ it "should store requested_url" do
68
+ response = Typhoeus::Response.new(:requested_url => "http://test.com")
69
+ response.requested_url.should == "http://test.com"
70
+ end
71
+
72
+ it "should store requested_http_method" do
73
+ response = Typhoeus::Response.new(:requested_http_method => :delete)
74
+ response.requested_http_method.should == :delete
75
+ end
76
+
77
+ it "should store an associated request object" do
78
+ response = Typhoeus::Response.new(:request => "whatever")
79
+ response.request.should == "whatever"
80
+ end
81
+
82
+ it "should not default to be a mock response" do
83
+ response = Typhoeus::Response.new
84
+ response.should_not be_mock
85
+ end
86
+ end
87
+
88
+ describe "#mock?" do
89
+ it "should be true if it's a mock response" do
90
+ response = Typhoeus::Response.new(:mock => true)
91
+ response.should be_mock
92
+ end
93
+ end
94
+
95
+ describe "headers" do
96
+ it 'should return an empty hash from #headers_hash when no headers string is given' do
97
+ response = Typhoeus::Response.new.headers_hash.should == {}
98
+ end
99
+
100
+ context 'when the headers_hash is stubbed' do
101
+ after(:each) { Typhoeus::Hydra.clear_stubs }
102
+ let!(:orig_response) { Typhoeus::Request.get("http://localhost:3000/multiple-headers") }
103
+
104
+ it 'returns a properly formatted string built from the headers_hash, code, status_message and http_version' do
105
+ stub_response = Typhoeus::Response.new(
106
+ :code => orig_response.code,
107
+ :headers_hash => orig_response.headers_hash,
108
+ :status_message => orig_response.status_message,
109
+ :http_version => orig_response.http_version
110
+ )
111
+
112
+ stub_response.headers.size.should == orig_response.headers.size
113
+
114
+ orig_header_lines = orig_response.headers.split("\n")
115
+ stub_header_lines = stub_response.headers.split("\n")
116
+
117
+ # HTTP version/status line should be identical
118
+ orig_header_lines.shift.should == stub_header_lines.shift
119
+
120
+ # "XSS" gets downcased, so we have to fix it here.
121
+ orig_header_lines.each { |line| line.sub!('XSS', 'Xss') }
122
+
123
+ # we can't count on the header order being identical since ruby hashes are not always ordered
124
+ orig_header_lines.should =~ stub_header_lines
125
+ end
126
+
127
+ it 'returns a valid header string even with the code, status message and http_version are not stubbed' do
128
+ response = Typhoeus::Response.new(:headers_hash => orig_response.headers_hash)
129
+ response.headers.should =~ /Content-Type/
130
+ end
131
+ end
132
+
133
+ describe "basic parsing" do
134
+ before(:all) do
135
+ @response = Typhoeus::Response.new(:headers => "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nStatus: 200\r\nX-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.2.9\r\nX-Cache: miss\r\nX-Runtime: 184\r\nETag: e001d08d9354ab7bc7c27a00163a3afa\r\nCache-Control: private, max-age=0, must-revalidate\r\nContent-Length: 4725\r\nSet-Cookie: _some_session=BAh7CDoGciIAOg9zZXNzaW9uX2lkIiU1OTQ2OTcwMjljMWM5ZTQwODU1NjQwYTViMmQxMTkxMjoGcyIKL2NhcnQ%3D--b4c4663932243090c961bb93d4ad5e4327064730; path=/; HttpOnly\r\nServer: nginx/0.6.37 + Phusion Passenger 2.2.4 (mod_rails/mod_rack)\r\nSet-Cookie: foo=bar; path=/;\r\nP3P: CP=\"NOI DSP COR NID ADMa OPTa OUR NOR\"\r\n\r\n")
136
+ end
137
+
138
+ it "can be accessed with lowercase keys" do
139
+ @response.headers_hash['content-type'].should == 'text/html; charset=utf-8'
140
+ end
141
+
142
+ it "can parse the headers into a hash" do
143
+ @response.headers_hash["Status"].should == "200"
144
+ @response.headers_hash["Set-Cookie"].should == ["_some_session=BAh7CDoGciIAOg9zZXNzaW9uX2lkIiU1OTQ2OTcwMjljMWM5ZTQwODU1NjQwYTViMmQxMTkxMjoGcyIKL2NhcnQ%3D--b4c4663932243090c961bb93d4ad5e4327064730; path=/; HttpOnly", "foo=bar; path=/;"]
145
+ @response.headers_hash["Content-Type"].should == "text/html; charset=utf-8"
146
+ end
147
+
148
+ it 'parses the status message' do
149
+ @response.status_message.should == 'OK'
150
+ end
151
+
152
+ it 'parses the HTTP version' do
153
+ @response.http_version.should == '1.1'
154
+ end
155
+
156
+ it 'parses all header keys except HTTP version declaration' do
157
+ @response.headers_hash.keys.should =~ %w[
158
+ X-Powered-By
159
+ P3p
160
+ X-Cache
161
+ Etag
162
+ X-Runtime
163
+ Content-Type
164
+ Content-Length
165
+ Server
166
+ Set-Cookie
167
+ Cache-Control
168
+ Connection
169
+ Status
170
+ ]
171
+ end
172
+ end
173
+
174
+ it "parses a header key that appears multiple times into an array" do
175
+ response = Typhoeus::Response.new(:headers => "HTTP/1.1 302 Found\r\nContent-Type: text/html; charset=utf-8\r\nConnection: close\r\nStatus: 302\r\nX-Powered-By: Phusion Passenger (mod_rails/mod_rack) 2.2.9\r\nLocation: http://mckenzie-greenholt1512.myshopify.com/cart\r\nX-Runtime: 22\r\nCache-Control: no-cache\r\nContent-Length: 114\r\nSet-Cookie: cart=8fdd6a828d9c89a737a52668be0cebaf; path=/; expires=Fri, 12-Mar-2010 18:30:19 GMT\r\nSet-Cookie: _session=BAh7CToPc2Vzc2lvbl9pZCIlZTQzMDQzMDg1YjI3MTQ4MzAzMTZmMWZmMWJjMTU1NmI6CWNhcnQiJThmZGQ2YTgyOGQ5Yzg5YTczN2E1MjY2OGJlMGNlYmFmOgZyIgA6BnMiDi9jYXJ0L2FkZA%3D%3D--6b0a699625caed9597580d8e9b6ca5f5e5954125; path=/; HttpOnly\r\nServer: nginx/0.6.37 + Phusion Passenger 2.2.4 (mod_rails/mod_rack)\r\nP3P: CP=\"NOI DSP COR NID ADMa OPTa OUR NOR\"\r\n\r\n")
176
+ response.headers_hash["Set-Cookie"].should include("cart=8fdd6a828d9c89a737a52668be0cebaf; path=/; expires=Fri, 12-Mar-2010 18:30:19 GMT")
177
+ response.headers_hash["Set-Cookie"].should include("_session=BAh7CToPc2Vzc2lvbl9pZCIlZTQzMDQzMDg1YjI3MTQ4MzAzMTZmMWZmMWJjMTU1NmI6CWNhcnQiJThmZGQ2YTgyOGQ5Yzg5YTczN2E1MjY2OGJlMGNlYmFmOgZyIgA6BnMiDi9jYXJ0L2FkZA%3D%3D--6b0a699625caed9597580d8e9b6ca5f5e5954125; path=/; HttpOnly")
178
+ end
179
+ end
180
+
181
+ describe "status checking" do
182
+ it "is successful if response code is 200-299" do
183
+ Typhoeus::Response.new(:code => 220).success?.should be
184
+ Typhoeus::Response.new(:code => 400).success?.should_not be
185
+ end
186
+
187
+ it "is not modified if the status code is 304" do
188
+ Typhoeus::Response.new(:code => 304).modified?.should_not be
189
+ Typhoeus::Response.new(:code => 200).modified?.should be
190
+ end
191
+ end
192
+ end