httparty 0.13.0 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +18 -0
  3. data/.github/workflows/ci.yml +26 -0
  4. data/.gitignore +4 -0
  5. data/.rubocop.yml +92 -0
  6. data/.rubocop_todo.yml +124 -0
  7. data/CONTRIBUTING.md +23 -0
  8. data/Changelog.md +557 -0
  9. data/Gemfile +15 -3
  10. data/Guardfile +4 -3
  11. data/README.md +24 -25
  12. data/Rakefile +5 -7
  13. data/bin/httparty +20 -14
  14. data/docs/README.md +191 -0
  15. data/examples/README.md +89 -0
  16. data/examples/aaws.rb +10 -6
  17. data/examples/basic.rb +6 -10
  18. data/examples/body_stream.rb +14 -0
  19. data/examples/crack.rb +2 -2
  20. data/examples/custom_parsers.rb +6 -5
  21. data/examples/delicious.rb +8 -8
  22. data/examples/google.rb +2 -2
  23. data/examples/headers_and_user_agents.rb +7 -3
  24. data/examples/idn.rb +10 -0
  25. data/examples/logging.rb +36 -0
  26. data/examples/microsoft_graph.rb +52 -0
  27. data/examples/multipart.rb +22 -0
  28. data/examples/nokogiri_html_parser.rb +0 -3
  29. data/examples/peer_cert.rb +9 -0
  30. data/examples/rescue_json.rb +17 -0
  31. data/examples/rubyurl.rb +3 -3
  32. data/examples/stackexchange.rb +24 -0
  33. data/examples/stream_download.rb +26 -0
  34. data/examples/tripit_sign_in.rb +20 -9
  35. data/examples/twitter.rb +7 -7
  36. data/examples/whoismyrep.rb +1 -1
  37. data/httparty.gemspec +13 -9
  38. data/lib/httparty/connection_adapter.rb +105 -25
  39. data/lib/httparty/cookie_hash.rb +10 -9
  40. data/lib/httparty/decompressor.rb +102 -0
  41. data/lib/httparty/exceptions.rb +8 -2
  42. data/lib/httparty/hash_conversions.rb +39 -19
  43. data/lib/httparty/headers_processor.rb +32 -0
  44. data/lib/httparty/logger/apache_formatter.rb +47 -0
  45. data/lib/httparty/logger/curl_formatter.rb +93 -0
  46. data/lib/httparty/logger/logger.rb +22 -10
  47. data/lib/httparty/logger/logstash_formatter.rb +61 -0
  48. data/lib/httparty/module_inheritable_attributes.rb +6 -4
  49. data/lib/httparty/net_digest_auth.rb +76 -25
  50. data/lib/httparty/parser.rb +28 -15
  51. data/lib/httparty/request/body.rb +105 -0
  52. data/lib/httparty/request/multipart_boundary.rb +13 -0
  53. data/lib/httparty/request.rb +218 -130
  54. data/lib/httparty/response/headers.rb +23 -19
  55. data/lib/httparty/response.rb +99 -15
  56. data/lib/httparty/response_fragment.rb +21 -0
  57. data/lib/httparty/text_encoder.rb +72 -0
  58. data/lib/httparty/utils.rb +13 -0
  59. data/lib/httparty/version.rb +3 -1
  60. data/lib/httparty.rb +191 -83
  61. data/website/css/common.css +1 -1
  62. data/website/index.html +3 -3
  63. metadata +50 -120
  64. data/.travis.yml +0 -7
  65. data/History +0 -303
  66. data/features/basic_authentication.feature +0 -20
  67. data/features/command_line.feature +0 -7
  68. data/features/deals_with_http_error_codes.feature +0 -26
  69. data/features/digest_authentication.feature +0 -20
  70. data/features/handles_compressed_responses.feature +0 -27
  71. data/features/handles_multiple_formats.feature +0 -57
  72. data/features/steps/env.rb +0 -22
  73. data/features/steps/httparty_response_steps.rb +0 -52
  74. data/features/steps/httparty_steps.rb +0 -35
  75. data/features/steps/mongrel_helper.rb +0 -94
  76. data/features/steps/remote_service_steps.rb +0 -74
  77. data/features/supports_redirection.feature +0 -22
  78. data/features/supports_timeout_option.feature +0 -13
  79. data/lib/httparty/core_extensions.rb +0 -32
  80. data/lib/httparty/logger/apache_logger.rb +0 -22
  81. data/lib/httparty/logger/curl_logger.rb +0 -48
  82. data/spec/fixtures/delicious.xml +0 -23
  83. data/spec/fixtures/empty.xml +0 -0
  84. data/spec/fixtures/google.html +0 -3
  85. data/spec/fixtures/ssl/generate.sh +0 -29
  86. data/spec/fixtures/ssl/generated/1fe462c2.0 +0 -16
  87. data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
  88. data/spec/fixtures/ssl/generated/ca.crt +0 -16
  89. data/spec/fixtures/ssl/generated/ca.key +0 -15
  90. data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
  91. data/spec/fixtures/ssl/generated/server.crt +0 -13
  92. data/spec/fixtures/ssl/generated/server.key +0 -15
  93. data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
  94. data/spec/fixtures/twitter.csv +0 -2
  95. data/spec/fixtures/twitter.json +0 -1
  96. data/spec/fixtures/twitter.xml +0 -403
  97. data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
  98. data/spec/httparty/connection_adapter_spec.rb +0 -298
  99. data/spec/httparty/cookie_hash_spec.rb +0 -83
  100. data/spec/httparty/exception_spec.rb +0 -23
  101. data/spec/httparty/logger/apache_logger_spec.rb +0 -26
  102. data/spec/httparty/logger/curl_logger_spec.rb +0 -18
  103. data/spec/httparty/logger/logger_spec.rb +0 -22
  104. data/spec/httparty/net_digest_auth_spec.rb +0 -152
  105. data/spec/httparty/parser_spec.rb +0 -165
  106. data/spec/httparty/request_spec.rb +0 -631
  107. data/spec/httparty/response_spec.rb +0 -221
  108. data/spec/httparty/ssl_spec.rb +0 -74
  109. data/spec/httparty_spec.rb +0 -764
  110. data/spec/spec.opts +0 -2
  111. data/spec/spec_helper.rb +0 -37
  112. data/spec/support/ssl_test_helper.rb +0 -47
  113. data/spec/support/ssl_test_server.rb +0 -80
  114. data/spec/support/stub_response.rb +0 -43
@@ -1,764 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
2
-
3
- describe HTTParty do
4
- before(:each) do
5
- @klass = Class.new
6
- @klass.instance_eval { include HTTParty }
7
- end
8
-
9
- describe "AllowedFormats deprecated" do
10
- before do
11
- Kernel.stub(:warn)
12
- end
13
-
14
- it "warns with a deprecation message" do
15
- Kernel.should_receive(:warn).with("Deprecated: Use HTTParty::Parser::SupportedFormats")
16
- HTTParty::AllowedFormats
17
- end
18
-
19
- it "returns HTTPart::Parser::SupportedFormats" do
20
- HTTParty::AllowedFormats.should == HTTParty::Parser::SupportedFormats
21
- end
22
- end
23
-
24
- describe "pem" do
25
- it 'should set the pem content' do
26
- @klass.pem 'PEM-CONTENT'
27
- @klass.default_options[:pem].should == 'PEM-CONTENT'
28
- end
29
-
30
- it "should set the password to nil if it's not provided" do
31
- @klass.pem 'PEM-CONTENT'
32
- @klass.default_options[:pem_password].should be_nil
33
- end
34
-
35
- it 'should set the password' do
36
- @klass.pem 'PEM-CONTENT', 'PASSWORD'
37
- @klass.default_options[:pem_password].should == 'PASSWORD'
38
- end
39
- end
40
-
41
- describe "pkcs12" do
42
- it 'should set the p12 content' do
43
- @klass.pkcs12 'P12-CONTENT', 'PASSWORD'
44
- @klass.default_options[:p12].should == 'P12-CONTENT'
45
- end
46
-
47
- it 'should set the password' do
48
- @klass.pkcs12 'P12-CONTENT', 'PASSWORD'
49
- @klass.default_options[:p12_password].should == 'PASSWORD'
50
- end
51
- end
52
-
53
- describe 'ssl_version' do
54
- it 'should set the ssl_version content' do
55
- @klass.ssl_version :SSLv3
56
- @klass.default_options[:ssl_version].should == :SSLv3
57
- end
58
- end
59
-
60
- describe 'ciphers' do
61
- it 'should set the ciphers content' do
62
- @klass.default_options[:ciphers].should be_nil
63
- @klass.ciphers 'RC4-SHA'
64
- @klass.default_options[:ciphers].should == 'RC4-SHA'
65
- end
66
- end
67
-
68
- describe 'http_proxy' do
69
- it 'should set the address' do
70
- @klass.http_proxy 'proxy.foo.com', 80
71
- options = @klass.default_options
72
- options[:http_proxyaddr].should == 'proxy.foo.com'
73
- options[:http_proxyport].should == 80
74
- end
75
-
76
- it 'should set the proxy user and pass when they are provided' do
77
- @klass.http_proxy 'proxy.foo.com', 80, 'user', 'pass'
78
- options = @klass.default_options
79
- options[:http_proxyuser].should == 'user'
80
- options[:http_proxypass].should == 'pass'
81
- end
82
- end
83
-
84
- describe "base uri" do
85
- before(:each) do
86
- @klass.base_uri('api.foo.com/v1')
87
- end
88
-
89
- it "should have reader" do
90
- @klass.base_uri.should == 'http://api.foo.com/v1'
91
- end
92
-
93
- it 'should have writer' do
94
- @klass.base_uri('http://api.foobar.com')
95
- @klass.base_uri.should == 'http://api.foobar.com'
96
- end
97
-
98
- it 'should not modify the parameter during assignment' do
99
- uri = 'http://api.foobar.com'
100
- @klass.base_uri(uri)
101
- uri.should == 'http://api.foobar.com'
102
- end
103
- end
104
-
105
- describe ".disable_rails_query_string_format" do
106
- it "sets the query string normalizer to HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER" do
107
- @klass.disable_rails_query_string_format
108
- @klass.default_options[:query_string_normalizer].should == HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER
109
- end
110
- end
111
-
112
- describe ".normalize_base_uri" do
113
- it "should add http if not present for non ssl requests" do
114
- uri = HTTParty.normalize_base_uri('api.foobar.com')
115
- uri.should == 'http://api.foobar.com'
116
- end
117
-
118
- it "should add https if not present for ssl requests" do
119
- uri = HTTParty.normalize_base_uri('api.foo.com/v1:443')
120
- uri.should == 'https://api.foo.com/v1:443'
121
- end
122
-
123
- it "should not remove https for ssl requests" do
124
- uri = HTTParty.normalize_base_uri('https://api.foo.com/v1:443')
125
- uri.should == 'https://api.foo.com/v1:443'
126
- end
127
-
128
- it 'should not modify the parameter' do
129
- uri = 'http://api.foobar.com'
130
- HTTParty.normalize_base_uri(uri)
131
- uri.should == 'http://api.foobar.com'
132
- end
133
-
134
- it "should not treat uri's with a port of 4430 as ssl" do
135
- uri = HTTParty.normalize_base_uri('http://api.foo.com:4430/v1')
136
- uri.should == 'http://api.foo.com:4430/v1'
137
- end
138
- end
139
-
140
- describe "headers" do
141
- def expect_headers(header={})
142
- HTTParty::Request.should_receive(:new) \
143
- .with(anything, anything, hash_including({ :headers => header })) \
144
- .and_return(mock("mock response", :perform => nil))
145
- end
146
-
147
- it "should default to empty hash" do
148
- @klass.headers.should == {}
149
- end
150
-
151
- it "should be able to be updated" do
152
- init_headers = {:foo => 'bar', :baz => 'spax'}
153
- @klass.headers init_headers
154
- @klass.headers.should == init_headers
155
- end
156
-
157
- it "uses the class headers when sending a request" do
158
- expect_headers(:foo => 'bar')
159
- @klass.headers(:foo => 'bar')
160
- @klass.get('')
161
- end
162
-
163
- it "merges class headers with request headers" do
164
- expect_headers(:baz => 'spax', :foo => 'bar')
165
- @klass.headers(:foo => 'bar')
166
- @klass.get('', :headers => {:baz => 'spax'})
167
- end
168
-
169
- it 'overrides class headers with request headers' do
170
- expect_headers(:baz => 'spax', :foo => 'baz')
171
- @klass.headers(:foo => 'bar')
172
- @klass.get('', :headers => {:baz => 'spax', :foo => 'baz'})
173
- end
174
-
175
- context "with cookies" do
176
- it 'utilizes the class-level cookies' do
177
- expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle')
178
- @klass.headers(:foo => 'bar')
179
- @klass.cookies(:type => 'snickerdoodle')
180
- @klass.get('')
181
- end
182
-
183
- it 'adds cookies to the headers' do
184
- expect_headers(:foo => 'bar', 'cookie' => 'type=snickerdoodle')
185
- @klass.headers(:foo => 'bar')
186
- @klass.get('', :cookies => {:type => 'snickerdoodle'})
187
- end
188
-
189
- it 'adds optional cookies to the optional headers' do
190
- expect_headers(:baz => 'spax', 'cookie' => 'type=snickerdoodle')
191
- @klass.get('', :cookies => {:type => 'snickerdoodle'}, :headers => {:baz => 'spax'})
192
- end
193
- end
194
- end
195
-
196
- describe "cookies" do
197
- def expect_cookie_header(s)
198
- HTTParty::Request.should_receive(:new) \
199
- .with(anything, anything, hash_including({ :headers => { "cookie" => s } })) \
200
- .and_return(mock("mock response", :perform => nil))
201
- end
202
-
203
- it "should not be in the headers by default" do
204
- HTTParty::Request.stub!(:new).and_return(stub(nil, :perform => nil))
205
- @klass.get("")
206
- @klass.headers.keys.should_not include("cookie")
207
- end
208
-
209
- it "should raise an ArgumentError if passed a non-Hash" do
210
- lambda do
211
- @klass.cookies("nonsense")
212
- end.should raise_error(ArgumentError)
213
- end
214
-
215
- it "should allow a cookie to be specified with a one-off request" do
216
- expect_cookie_header "type=snickerdoodle"
217
- @klass.get("", :cookies => { :type => "snickerdoodle" })
218
- end
219
-
220
- describe "when a cookie is set at the class level" do
221
- before(:each) do
222
- @klass.cookies({ :type => "snickerdoodle" })
223
- end
224
-
225
- it "should include that cookie in the request" do
226
- expect_cookie_header "type=snickerdoodle"
227
- @klass.get("")
228
- end
229
-
230
- it "should pass the proper cookies when requested multiple times" do
231
- 2.times do
232
- expect_cookie_header "type=snickerdoodle"
233
- @klass.get("")
234
- end
235
- end
236
-
237
- it "should allow the class defaults to be overridden" do
238
- expect_cookie_header "type=chocolate_chip"
239
-
240
- @klass.get("", :cookies => { :type => "chocolate_chip" })
241
- end
242
- end
243
-
244
- describe "in a class with multiple methods that use different cookies" do
245
- before(:each) do
246
- @klass.instance_eval do
247
- def first_method
248
- get("first_method", :cookies => { :first_method_cookie => "foo" })
249
- end
250
-
251
- def second_method
252
- get("second_method", :cookies => { :second_method_cookie => "foo" })
253
- end
254
- end
255
- end
256
-
257
- it "should not allow cookies used in one method to carry over into other methods" do
258
- expect_cookie_header "first_method_cookie=foo"
259
- @klass.first_method
260
-
261
- expect_cookie_header "second_method_cookie=foo"
262
- @klass.second_method
263
- end
264
- end
265
- end
266
-
267
- describe "default params" do
268
- it "should default to empty hash" do
269
- @klass.default_params.should == {}
270
- end
271
-
272
- it "should be able to be updated" do
273
- new_defaults = {:foo => 'bar', :baz => 'spax'}
274
- @klass.default_params new_defaults
275
- @klass.default_params.should == new_defaults
276
- end
277
- end
278
-
279
- describe "default timeout" do
280
- it "should default to nil" do
281
- @klass.default_options[:timeout].should == nil
282
- end
283
-
284
- it "should support updating" do
285
- @klass.default_timeout 10
286
- @klass.default_options[:timeout].should == 10
287
- end
288
-
289
- it "should support floats" do
290
- @klass.default_timeout 0.5
291
- @klass.default_options[:timeout].should == 0.5
292
- end
293
- end
294
-
295
- describe "debug_output" do
296
- it "stores the given stream as a default_option" do
297
- @klass.debug_output $stdout
298
- @klass.default_options[:debug_output].should == $stdout
299
- end
300
-
301
- it "stores the $stderr stream by default" do
302
- @klass.debug_output
303
- @klass.default_options[:debug_output].should == $stderr
304
- end
305
- end
306
-
307
- describe "basic http authentication" do
308
- it "should work" do
309
- @klass.basic_auth 'foobar', 'secret'
310
- @klass.default_options[:basic_auth].should == {:username => 'foobar', :password => 'secret'}
311
- end
312
- end
313
-
314
- describe "digest http authentication" do
315
- it "should work" do
316
- @klass.digest_auth 'foobar', 'secret'
317
- @klass.default_options[:digest_auth].should == {:username => 'foobar', :password => 'secret'}
318
- end
319
- end
320
-
321
- describe "parser" do
322
- class CustomParser
323
- def self.parse(body)
324
- return {:sexy => true}
325
- end
326
- end
327
-
328
- let(:parser) do
329
- Proc.new{ |data, format| CustomParser.parse(data) }
330
- end
331
-
332
- it "should set parser options" do
333
- @klass.parser parser
334
- @klass.default_options[:parser].should == parser
335
- end
336
-
337
- it "should be able parse response with custom parser" do
338
- @klass.parser parser
339
- FakeWeb.register_uri(:get, 'http://twitter.com/statuses/public_timeline.xml', :body => 'tweets')
340
- custom_parsed_response = @klass.get('http://twitter.com/statuses/public_timeline.xml')
341
- custom_parsed_response[:sexy].should == true
342
- end
343
-
344
- it "raises UnsupportedFormat when the parser cannot handle the format" do
345
- @klass.format :json
346
- class MyParser < HTTParty::Parser
347
- SupportedFormats = {}
348
- end unless defined?(MyParser)
349
- expect do
350
- @klass.parser MyParser
351
- end.to raise_error(HTTParty::UnsupportedFormat)
352
- end
353
-
354
- it 'does not validate format whe custom parser is a proc' do
355
- expect do
356
- @klass.format :json
357
- @klass.parser lambda {|body, format|}
358
- end.to_not raise_error(HTTParty::UnsupportedFormat)
359
- end
360
- end
361
-
362
- describe "connection_adapter" do
363
- let(:uri) { 'http://google.com/api.json' }
364
- let(:connection_adapter) { mock('CustomConnectionAdapter') }
365
-
366
- it "should set the connection_adapter" do
367
- @klass.connection_adapter connection_adapter
368
- @klass.default_options[:connection_adapter].should be connection_adapter
369
- end
370
-
371
- it "should set the connection_adapter_options when provided" do
372
- options = {:foo => :bar}
373
- @klass.connection_adapter connection_adapter, options
374
- @klass.default_options[:connection_adapter_options].should be options
375
- end
376
-
377
- it "should not set the connection_adapter_options when not provided" do
378
- @klass.connection_adapter connection_adapter
379
- @klass.default_options[:connection_adapter_options].should be_nil
380
- end
381
-
382
- it "should process a request with a connection from the adapter" do
383
- connection_adapter_options = {:foo => :bar}
384
- connection_adapter.should_receive(:call) do |u,o|
385
- o[:connection_adapter_options].should == connection_adapter_options
386
- HTTParty::ConnectionAdapter.call(u,o)
387
- end.with(URI.parse(uri), kind_of(Hash))
388
- FakeWeb.register_uri(:get, uri, :body => 'stuff')
389
- @klass.connection_adapter connection_adapter, connection_adapter_options
390
- @klass.get(uri).should == 'stuff'
391
- end
392
- end
393
-
394
- describe "format" do
395
- it "should allow xml" do
396
- @klass.format :xml
397
- @klass.default_options[:format].should == :xml
398
- end
399
-
400
- it "should allow csv" do
401
- @klass.format :csv
402
- @klass.default_options[:format].should == :csv
403
- end
404
-
405
- it "should allow json" do
406
- @klass.format :json
407
- @klass.default_options[:format].should == :json
408
- end
409
-
410
- it "should allow plain" do
411
- @klass.format :plain
412
- @klass.default_options[:format].should == :plain
413
- end
414
-
415
- it 'should not allow funky format' do
416
- lambda do
417
- @klass.format :foobar
418
- end.should raise_error(HTTParty::UnsupportedFormat)
419
- end
420
-
421
- it 'should only print each format once with an exception' do
422
- lambda do
423
- @klass.format :foobar
424
- end.should raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: csv, html, json, plain, xml")
425
- end
426
-
427
- it 'sets the default parser' do
428
- @klass.default_options[:parser].should be_nil
429
- @klass.format :json
430
- @klass.default_options[:parser].should == HTTParty::Parser
431
- end
432
-
433
- it 'does not reset parser to the default parser' do
434
- my_parser = lambda {}
435
- @klass.parser my_parser
436
- @klass.format :json
437
- @klass.parser.should == my_parser
438
- end
439
- end
440
-
441
- describe "#no_follow" do
442
- it "sets no_follow to false by default" do
443
- @klass.no_follow
444
- @klass.default_options[:no_follow].should be_false
445
- end
446
-
447
- it "sets the no_follow option to true" do
448
- @klass.no_follow true
449
- @klass.default_options[:no_follow].should be_true
450
- end
451
- end
452
-
453
- describe "#maintain_method_across_redirects" do
454
- it "sets maintain_method_across_redirects to true by default" do
455
- @klass.maintain_method_across_redirects
456
- @klass.default_options[:maintain_method_across_redirects].should be_true
457
- end
458
-
459
- it "sets the maintain_method_across_redirects option to false" do
460
- @klass.maintain_method_across_redirects false
461
- @klass.default_options[:maintain_method_across_redirects].should be_false
462
- end
463
- end
464
-
465
- describe ".follow_redirects" do
466
- it "sets follow redirects to true by default" do
467
- @klass.follow_redirects
468
- @klass.default_options[:follow_redirects].should be_true
469
- end
470
-
471
- it "sets the follow_redirects option to false" do
472
- @klass.follow_redirects false
473
- @klass.default_options[:follow_redirects].should be_false
474
- end
475
- end
476
-
477
- describe ".query_string_normalizer" do
478
- it "sets the query_string_normalizer option" do
479
- normalizer = proc {}
480
- @klass.query_string_normalizer normalizer
481
- @klass.default_options[:query_string_normalizer].should == normalizer
482
- end
483
- end
484
-
485
- describe "with explicit override of automatic redirect handling" do
486
- before do
487
- @request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', :format => :xml, :no_follow => true)
488
- @redirect = stub_response 'first redirect', 302
489
- @redirect['location'] = 'http://foo.com/bar'
490
- HTTParty::Request.stub(:new => @request)
491
- end
492
-
493
- it "should fail with redirected GET" do
494
- lambda do
495
- @error = @klass.get('/foo', :no_follow => true)
496
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
497
- end
498
-
499
- it "should fail with redirected POST" do
500
- lambda do
501
- @klass.post('/foo', :no_follow => true)
502
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
503
- end
504
-
505
- it "should fail with redirected PATCH" do
506
- lambda do
507
- @klass.patch('/foo', :no_follow => true)
508
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
509
- end
510
-
511
- it "should fail with redirected DELETE" do
512
- lambda do
513
- @klass.delete('/foo', :no_follow => true)
514
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
515
- end
516
-
517
- it "should fail with redirected MOVE" do
518
- lambda do
519
- @klass.move('/foo', :no_follow => true)
520
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
521
- end
522
-
523
- it "should fail with redirected COPY" do
524
- lambda do
525
- @klass.copy('/foo', :no_follow => true)
526
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
527
- end
528
-
529
- it "should fail with redirected PUT" do
530
- lambda do
531
- @klass.put('/foo', :no_follow => true)
532
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
533
- end
534
-
535
- it "should fail with redirected HEAD" do
536
- lambda do
537
- @klass.head('/foo', :no_follow => true)
538
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
539
- end
540
-
541
- it "should fail with redirected OPTIONS" do
542
- lambda do
543
- @klass.options('/foo', :no_follow => true)
544
- end.should raise_error(HTTParty::RedirectionTooDeep) {|e| e.response.body.should == 'first redirect'}
545
- end
546
- end
547
-
548
- describe "with multiple class definitions" do
549
- before(:each) do
550
- @klass.instance_eval do
551
- base_uri "http://first.com"
552
- default_params :one => 1
553
- end
554
-
555
- @additional_klass = Class.new
556
- @additional_klass.instance_eval do
557
- include HTTParty
558
- base_uri "http://second.com"
559
- default_params :two => 2
560
- end
561
- end
562
-
563
- it "should not run over each others options" do
564
- @klass.default_options.should == { :base_uri => 'http://first.com', :default_params => { :one => 1 } }
565
- @additional_klass.default_options.should == { :base_uri => 'http://second.com', :default_params => { :two => 2 } }
566
- end
567
- end
568
-
569
- describe "two child classes inheriting from one parent" do
570
- before(:each) do
571
- @parent = Class.new do
572
- include HTTParty
573
- def self.name
574
- "Parent"
575
- end
576
- end
577
-
578
- @child1 = Class.new(@parent)
579
- @child2 = Class.new(@parent)
580
- end
581
-
582
- it "does not modify each others inherited attributes" do
583
- @child1.default_params :joe => "alive"
584
- @child2.default_params :joe => "dead"
585
-
586
- @child1.default_options.should == { :default_params => {:joe => "alive"} }
587
- @child2.default_options.should == { :default_params => {:joe => "dead"} }
588
-
589
- @parent.default_options.should == { }
590
- end
591
-
592
- it "inherits default_options from the superclass" do
593
- @parent.basic_auth 'user', 'password'
594
- @child1.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}}
595
- @child1.basic_auth 'u', 'p' # modifying child1 has no effect on child2
596
- @child2.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}}
597
- end
598
-
599
- it "doesn't modify the parent's default options" do
600
- @parent.basic_auth 'user', 'password'
601
-
602
- @child1.basic_auth 'u', 'p'
603
- @child1.default_options.should == {:basic_auth => {:username => 'u', :password => 'p'}}
604
-
605
- @child1.basic_auth 'email', 'token'
606
- @child1.default_options.should == {:basic_auth => {:username => 'email', :password => 'token'}}
607
-
608
- @parent.default_options.should == {:basic_auth => {:username => 'user', :password => 'password'}}
609
- end
610
-
611
- it "doesn't modify hashes in the parent's default options" do
612
- @parent.headers 'Accept' => 'application/json'
613
- @child1.headers 'Accept' => 'application/xml'
614
-
615
- @parent.default_options[:headers].should == {'Accept' => 'application/json'}
616
- @child1.default_options[:headers].should == {'Accept' => 'application/xml'}
617
- end
618
-
619
- it "works with lambda values" do
620
- @child1.default_options[:imaginary_option] = lambda { "This is a new lambda "}
621
- @child1.default_options[:imaginary_option].should be_a Proc
622
- end
623
-
624
- it 'should dup the proc on the child class' do
625
- imaginary_option = lambda { 2 * 3.14 }
626
- @parent.default_options[:imaginary_option] = imaginary_option
627
- @parent.default_options[:imaginary_option].call.should == imaginary_option.call
628
- @child1.default_options[:imaginary_option]
629
- @child1.default_options[:imaginary_option].call.should == imaginary_option.call
630
- @child1.default_options[:imaginary_option].should_not be_equal imaginary_option
631
- end
632
-
633
- it "inherits default_cookies from the parent class" do
634
- @parent.cookies 'type' => 'chocolate_chip'
635
- @child1.default_cookies.should == {"type" => "chocolate_chip"}
636
- @child1.cookies 'type' => 'snickerdoodle'
637
- @child1.default_cookies.should == {"type" => "snickerdoodle"}
638
- @child2.default_cookies.should == {"type" => "chocolate_chip"}
639
- end
640
-
641
- it "doesn't modify the parent's default cookies" do
642
- @parent.cookies 'type' => 'chocolate_chip'
643
-
644
- @child1.cookies 'type' => 'snickerdoodle'
645
- @child1.default_cookies.should == {"type" => "snickerdoodle"}
646
-
647
- @parent.default_cookies.should == {"type" => "chocolate_chip"}
648
- end
649
- end
650
-
651
- describe "grand parent with inherited callback" do
652
- before do
653
- @grand_parent = Class.new do
654
- def self.inherited(subclass)
655
- subclass.instance_variable_set(:@grand_parent, true)
656
- end
657
- end
658
- @parent = Class.new(@grand_parent) do
659
- include HTTParty
660
- end
661
- end
662
- it "continues running the #inherited on the parent" do
663
- child = Class.new(@parent)
664
- child.instance_variable_get(:@grand_parent).should be_true
665
- end
666
- end
667
-
668
- describe "#get" do
669
- it "should be able to get html" do
670
- stub_http_response_with('google.html')
671
- HTTParty.get('http://www.google.com').should == file_fixture('google.html')
672
- end
673
-
674
- it "should be able to get chunked html" do
675
- chunks = ["Chunk1", "Chunk2", "Chunk3", "Chunk4"]
676
- stub_chunked_http_response_with(chunks)
677
-
678
- HTTParty.get('http://www.google.com') do |fragment|
679
- chunks.should include(fragment)
680
- end.should == chunks.join
681
- end
682
-
683
- it "should be able parse response type json automatically" do
684
- stub_http_response_with('twitter.json')
685
- tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
686
- tweets.size.should == 20
687
- tweets.first['user'].should == {
688
- "name" => "Pyk",
689
- "url" => nil,
690
- "id" => "7694602",
691
- "description" => nil,
692
- "protected" => false,
693
- "screen_name" => "Pyk",
694
- "followers_count" => 1,
695
- "location" => "Opera Plaza, California",
696
- "profile_image_url" => "http://static.twitter.com/images/default_profile_normal.png"
697
- }
698
- end
699
-
700
- it "should be able parse response type xml automatically" do
701
- stub_http_response_with('twitter.xml')
702
- tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.xml')
703
- tweets['statuses'].size.should == 20
704
- tweets['statuses'].first['user'].should == {
705
- "name" => "Magic 8 Bot",
706
- "url" => nil,
707
- "id" => "17656026",
708
- "description" => "ask me a question",
709
- "protected" => "false",
710
- "screen_name" => "magic8bot",
711
- "followers_count" => "90",
712
- "profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
713
- "location" => nil
714
- }
715
- end
716
-
717
- it "should be able parse response type csv automatically" do
718
- stub_http_response_with('twitter.csv')
719
- profile = HTTParty.get('http://twitter.com/statuses/profile.csv')
720
- profile.size.should == 2
721
- profile[0].should == ["name","url","id","description","protected","screen_name","followers_count","profile_image_url","location"]
722
- profile[1].should == ["Magic 8 Bot",nil,"17656026","ask me a question","false","magic8bot","90","http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",nil]
723
- end
724
-
725
- it "should not get undefined method add_node for nil class for the following xml" do
726
- stub_http_response_with('undefined_method_add_node_for_nil.xml')
727
- result = HTTParty.get('http://foobar.com')
728
- result.should == {"Entities"=>{"href"=>"https://s3-sandbox.parature.com/api/v1/5578/5633/Account", "results"=>"0", "total"=>"0", "page_size"=>"25", "page"=>"1"}}
729
- end
730
-
731
- it "should parse empty response fine" do
732
- stub_http_response_with('empty.xml')
733
- result = HTTParty.get('http://foobar.com')
734
- result.should be_nil
735
- end
736
-
737
- it "should accept http URIs" do
738
- stub_http_response_with('google.html')
739
- lambda do
740
- HTTParty.get('http://google.com')
741
- end.should_not raise_error(HTTParty::UnsupportedURIScheme)
742
- end
743
-
744
- it "should accept https URIs" do
745
- stub_http_response_with('google.html')
746
- lambda do
747
- HTTParty.get('https://google.com')
748
- end.should_not raise_error(HTTParty::UnsupportedURIScheme)
749
- end
750
-
751
- it "should accept webcal URIs" do
752
- stub_http_response_with('google.html')
753
- lambda do
754
- HTTParty.get('webcal://google.com')
755
- end.should_not raise_error(HTTParty::UnsupportedURIScheme)
756
- end
757
-
758
- it "should raise an InvalidURIError on URIs that can't be parsed at all" do
759
- lambda do
760
- HTTParty.get("It's the one that says 'Bad URI'")
761
- end.should raise_error(URI::InvalidURIError)
762
- end
763
- end
764
- end