httparty 0.17.0 → 0.17.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of httparty might be problematic. Click here for more details.

Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Changelog.md +7 -0
  3. data/Gemfile +1 -0
  4. data/httparty.gemspec +0 -1
  5. data/lib/httparty.rb +2 -18
  6. data/lib/httparty/connection_adapter.rb +10 -0
  7. data/lib/httparty/headers_processor.rb +30 -0
  8. data/lib/httparty/request.rb +4 -4
  9. data/lib/httparty/version.rb +1 -1
  10. metadata +4 -103
  11. data/features/basic_authentication.feature +0 -20
  12. data/features/command_line.feature +0 -95
  13. data/features/deals_with_http_error_codes.feature +0 -26
  14. data/features/digest_authentication.feature +0 -30
  15. data/features/handles_compressed_responses.feature +0 -27
  16. data/features/handles_multiple_formats.feature +0 -57
  17. data/features/steps/env.rb +0 -27
  18. data/features/steps/httparty_response_steps.rb +0 -56
  19. data/features/steps/httparty_steps.rb +0 -43
  20. data/features/steps/mongrel_helper.rb +0 -127
  21. data/features/steps/remote_service_steps.rb +0 -92
  22. data/features/supports_read_timeout_option.feature +0 -13
  23. data/features/supports_redirection.feature +0 -22
  24. data/features/supports_timeout_option.feature +0 -13
  25. data/spec/fixtures/delicious.xml +0 -23
  26. data/spec/fixtures/empty.xml +0 -0
  27. data/spec/fixtures/example.html +0 -10
  28. data/spec/fixtures/ssl/generate.sh +0 -29
  29. data/spec/fixtures/ssl/generated/bogushost.crt +0 -29
  30. data/spec/fixtures/ssl/generated/ca.crt +0 -31
  31. data/spec/fixtures/ssl/generated/ca.key +0 -52
  32. data/spec/fixtures/ssl/generated/selfsigned.crt +0 -29
  33. data/spec/fixtures/ssl/generated/server.crt +0 -30
  34. data/spec/fixtures/ssl/generated/server.key +0 -52
  35. data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
  36. data/spec/fixtures/tiny.gif +0 -0
  37. data/spec/fixtures/twitter.csv +0 -2
  38. data/spec/fixtures/twitter.json +0 -1
  39. data/spec/fixtures/twitter.xml +0 -403
  40. data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
  41. data/spec/httparty/connection_adapter_spec.rb +0 -628
  42. data/spec/httparty/cookie_hash_spec.rb +0 -100
  43. data/spec/httparty/exception_spec.rb +0 -45
  44. data/spec/httparty/hash_conversions_spec.rb +0 -58
  45. data/spec/httparty/logger/apache_formatter_spec.rb +0 -40
  46. data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
  47. data/spec/httparty/logger/logger_spec.rb +0 -43
  48. data/spec/httparty/logger/logstash_formatter_spec.rb +0 -44
  49. data/spec/httparty/net_digest_auth_spec.rb +0 -270
  50. data/spec/httparty/parser_spec.rb +0 -190
  51. data/spec/httparty/request/body_spec.rb +0 -165
  52. data/spec/httparty/request_spec.rb +0 -1389
  53. data/spec/httparty/response_fragment_spec.rb +0 -17
  54. data/spec/httparty/response_spec.rb +0 -374
  55. data/spec/httparty/ssl_spec.rb +0 -82
  56. data/spec/httparty_spec.rb +0 -943
  57. data/spec/spec_helper.rb +0 -57
  58. data/spec/support/ssl_test_helper.rb +0 -47
  59. data/spec/support/ssl_test_server.rb +0 -80
  60. data/spec/support/stub_response.rb +0 -50
@@ -1,943 +0,0 @@
1
- require_relative 'spec_helper'
2
-
3
- RSpec.describe HTTParty do
4
- before(:each) do
5
- @klass = Class.new
6
- @klass.instance_eval { include HTTParty }
7
- end
8
-
9
- describe "pem" do
10
- it 'should set the pem content' do
11
- @klass.pem 'PEM-CONTENT'
12
- expect(@klass.default_options[:pem]).to eq('PEM-CONTENT')
13
- end
14
-
15
- it "should set the password to nil if it's not provided" do
16
- @klass.pem 'PEM-CONTENT'
17
- expect(@klass.default_options[:pem_password]).to be_nil
18
- end
19
-
20
- it 'should set the password' do
21
- @klass.pem 'PEM-CONTENT', 'PASSWORD'
22
- expect(@klass.default_options[:pem_password]).to eq('PASSWORD')
23
- end
24
- end
25
-
26
- describe "pkcs12" do
27
- it 'should set the p12 content' do
28
- @klass.pkcs12 'P12-CONTENT', 'PASSWORD'
29
- expect(@klass.default_options[:p12]).to eq('P12-CONTENT')
30
- end
31
-
32
- it 'should set the password' do
33
- @klass.pkcs12 'P12-CONTENT', 'PASSWORD'
34
- expect(@klass.default_options[:p12_password]).to eq('PASSWORD')
35
- end
36
- end
37
-
38
- describe 'ssl_version' do
39
- it 'should set the ssl_version content' do
40
- @klass.ssl_version :SSLv3
41
- expect(@klass.default_options[:ssl_version]).to eq(:SSLv3)
42
- end
43
- end
44
-
45
- describe 'ciphers' do
46
- it 'should set the ciphers content' do
47
- expect(@klass.default_options[:ciphers]).to be_nil
48
- @klass.ciphers 'RC4-SHA'
49
- expect(@klass.default_options[:ciphers]).to eq('RC4-SHA')
50
- end
51
- end
52
-
53
- describe 'http_proxy' do
54
- it 'should set the address' do
55
- @klass.http_proxy 'proxy.foo.com', 80
56
- options = @klass.default_options
57
- expect(options[:http_proxyaddr]).to eq('proxy.foo.com')
58
- expect(options[:http_proxyport]).to eq(80)
59
- end
60
-
61
- it 'should set the proxy user and pass when they are provided' do
62
- @klass.http_proxy 'proxy.foo.com', 80, 'user', 'pass'
63
- options = @klass.default_options
64
- expect(options[:http_proxyuser]).to eq('user')
65
- expect(options[:http_proxypass]).to eq('pass')
66
- end
67
- end
68
-
69
- describe "base uri" do
70
- before(:each) do
71
- @klass.base_uri('api.foo.com/v1')
72
- end
73
-
74
- it "should have reader" do
75
- expect(@klass.base_uri).to eq('http://api.foo.com/v1')
76
- end
77
-
78
- it 'should have writer' do
79
- @klass.base_uri('http://api.foobar.com')
80
- expect(@klass.base_uri).to eq('http://api.foobar.com')
81
- end
82
-
83
- it 'should not modify the parameter during assignment' do
84
- uri = 'http://api.foobar.com'
85
- @klass.base_uri(uri)
86
- expect(uri).to eq('http://api.foobar.com')
87
- end
88
- end
89
-
90
- describe ".disable_rails_query_string_format" do
91
- it "sets the query string normalizer to HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER" do
92
- @klass.disable_rails_query_string_format
93
- expect(@klass.default_options[:query_string_normalizer]).to eq(HTTParty::Request::NON_RAILS_QUERY_STRING_NORMALIZER)
94
- end
95
- end
96
-
97
- describe ".normalize_base_uri" do
98
- it "should add http if not present for non ssl requests" do
99
- uri = HTTParty.normalize_base_uri('api.foobar.com')
100
- expect(uri).to eq('http://api.foobar.com')
101
- end
102
-
103
- it "should add https if not present for ssl requests" do
104
- uri = HTTParty.normalize_base_uri('api.foo.com/v1:443')
105
- expect(uri).to eq('https://api.foo.com/v1:443')
106
- end
107
-
108
- it "should not remove https for ssl requests" do
109
- uri = HTTParty.normalize_base_uri('https://api.foo.com/v1:443')
110
- expect(uri).to eq('https://api.foo.com/v1:443')
111
- end
112
-
113
- it 'should not modify the parameter' do
114
- uri = 'http://api.foobar.com'
115
- HTTParty.normalize_base_uri(uri)
116
- expect(uri).to eq('http://api.foobar.com')
117
- end
118
-
119
- it "should not treat uri's with a port of 4430 as ssl" do
120
- uri = HTTParty.normalize_base_uri('http://api.foo.com:4430/v1')
121
- expect(uri).to eq('http://api.foo.com:4430/v1')
122
- end
123
- end
124
-
125
- describe "headers" do
126
- def expect_headers(header = {})
127
- expect(HTTParty::Request).to receive(:new) \
128
- .with(anything, anything, hash_including({ headers: header })) \
129
- .and_return(double("mock response", perform: nil))
130
- end
131
-
132
- it "does not modify default_options when no arguments are passed" do
133
- @klass.headers
134
- expect(@klass.default_options[:headers]).to eq(nil)
135
- end
136
-
137
- it "should default to empty hash" do
138
- expect(@klass.headers).to eq({})
139
- end
140
-
141
- it "should be able to be updated" do
142
- init_headers = {foo: 'bar', baz: 'spax'}
143
- @klass.headers init_headers
144
- expect(@klass.headers).to eq(init_headers)
145
- end
146
-
147
- it "should be able to accept block as header value" do
148
- init_headers = {'foo' => lambda {'bar'}}
149
- @klass.headers init_headers
150
-
151
- stub_request(:get, "http://example.com/").with(headers: {'foo' => 'bar', 'baz' => 'spax'})
152
-
153
- @klass.get('http://example.com/', headers: {'baz' => -> {'spax'}})
154
- expect(@klass.headers).to eq(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 'doesnt modify default headers' do
190
- expect(@klass.headers).to eq({})
191
- expect_headers('cookie' => 'type=snickerdoodle')
192
- @klass.get('', cookies: {type: 'snickerdoodle'})
193
- expect(@klass.headers).to eq({})
194
- end
195
-
196
- it 'adds optional cookies to the optional headers' do
197
- expect_headers('baz' => 'spax', 'cookie' => 'type=snickerdoodle')
198
- @klass.get('', cookies: {type: 'snickerdoodle'}, headers: {baz: 'spax'})
199
- end
200
- end
201
-
202
- context 'when posting file' do
203
- let(:boundary) { '------------------------c772861a5109d5ef' }
204
- let(:headers) do
205
- { 'Content-Type'=>"multipart/form-data; boundary=#{boundary}" }
206
- end
207
-
208
- before do
209
- expect(HTTParty::Request::MultipartBoundary).to receive(:generate).and_return(boundary)
210
- end
211
-
212
- it 'changes content-type headers to multipart/form-data' do
213
- stub_request(:post, "http://example.com/").with(headers: headers)
214
-
215
- @klass.post('http://example.com', body: { file: File.open('spec/fixtures/tiny.gif')})
216
- end
217
- end
218
-
219
- context 'when headers passed as symbols' do
220
- it 'converts them to string' do
221
- expect_headers('foo' => 'application/json', 'bar' => 'example')
222
- headers = { foo: 'application/json', bar: 'example' }
223
- @klass.post('http://example.com', headers: headers)
224
- end
225
-
226
- it 'converts default headers to string' do
227
- expect_headers('foo' => 'application/json', 'bar' => 'example')
228
-
229
- @klass.headers(foo: 'application/json')
230
- @klass.post('http://example.com', headers: { bar: 'example' })
231
- end
232
- end
233
- end
234
-
235
- describe "cookies" do
236
- def expect_cookie_header(s)
237
- expect(HTTParty::Request).to receive(:new) \
238
- .with(anything, anything, hash_including({ headers: { "cookie" => s } })) \
239
- .and_return(double("mock response", perform: nil))
240
- end
241
-
242
- it "should not be in the headers by default" do
243
- allow(HTTParty::Request).to receive(:new).and_return(double(nil, perform: nil))
244
- @klass.get("")
245
- expect(@klass.headers.keys).not_to include("cookie")
246
- end
247
-
248
- it "should raise an ArgumentError if passed a non-Hash" do
249
- expect do
250
- @klass.cookies("nonsense")
251
- end.to raise_error(ArgumentError)
252
- end
253
-
254
- it "should allow a cookie to be specified with a one-off request" do
255
- expect_cookie_header "type=snickerdoodle"
256
- @klass.get("", cookies: { type: "snickerdoodle" })
257
- end
258
-
259
- describe "when a cookie is set at the class level" do
260
- before(:each) do
261
- @klass.cookies({ type: "snickerdoodle" })
262
- end
263
-
264
- it "should include that cookie in the request" do
265
- expect_cookie_header "type=snickerdoodle"
266
- @klass.get("")
267
- end
268
-
269
- it "should pass the proper cookies when requested multiple times" do
270
- 2.times do
271
- expect_cookie_header "type=snickerdoodle"
272
- @klass.get("")
273
- end
274
- end
275
-
276
- it "should allow the class defaults to be overridden" do
277
- expect_cookie_header "type=chocolate_chip"
278
-
279
- @klass.get("", cookies: { type: "chocolate_chip" })
280
- end
281
- end
282
-
283
- describe "in a class with multiple methods that use different cookies" do
284
- before(:each) do
285
- @klass.instance_eval do
286
- def first_method
287
- get("first_method", cookies: { first_method_cookie: "foo" })
288
- end
289
-
290
- def second_method
291
- get("second_method", cookies: { second_method_cookie: "foo" })
292
- end
293
- end
294
- end
295
-
296
- it "should not allow cookies used in one method to carry over into other methods" do
297
- expect_cookie_header "first_method_cookie=foo"
298
- @klass.first_method
299
-
300
- expect_cookie_header "second_method_cookie=foo"
301
- @klass.second_method
302
- end
303
- end
304
- end
305
-
306
- describe "default params" do
307
- it "should default to empty hash" do
308
- expect(@klass.default_params).to eq({})
309
- end
310
-
311
- it "should be able to be updated" do
312
- new_defaults = {foo: 'bar', baz: 'spax'}
313
- @klass.default_params new_defaults
314
- expect(@klass.default_params).to eq(new_defaults)
315
- end
316
- end
317
-
318
- describe "default timeout" do
319
- it "should default to nil" do
320
- expect(@klass.default_options[:timeout]).to eq(nil)
321
- end
322
-
323
- it "should support updating" do
324
- @klass.default_timeout 10
325
- expect(@klass.default_options[:timeout]).to eq(10)
326
- end
327
-
328
- it "should support floats" do
329
- @klass.default_timeout 0.5
330
- expect(@klass.default_options[:timeout]).to eq(0.5)
331
- end
332
-
333
- it "should raise an exception if unsupported type provided" do
334
- expect { @klass.default_timeout "0.5" }.to raise_error ArgumentError
335
- end
336
- end
337
-
338
- describe "debug_output" do
339
- it "stores the given stream as a default_option" do
340
- @klass.debug_output $stdout
341
- expect(@klass.default_options[:debug_output]).to eq($stdout)
342
- end
343
-
344
- it "stores the $stderr stream by default" do
345
- @klass.debug_output
346
- expect(@klass.default_options[:debug_output]).to eq($stderr)
347
- end
348
- end
349
-
350
- describe "basic http authentication" do
351
- it "should work" do
352
- @klass.basic_auth 'foobar', 'secret'
353
- expect(@klass.default_options[:basic_auth]).to eq({username: 'foobar', password: 'secret'})
354
- end
355
- end
356
-
357
- describe "digest http authentication" do
358
- it "should work" do
359
- @klass.digest_auth 'foobar', 'secret'
360
- expect(@klass.default_options[:digest_auth]).to eq({username: 'foobar', password: 'secret'})
361
- end
362
- end
363
-
364
- describe "parser" do
365
- class CustomParser
366
- def self.parse(body)
367
- {sexy: true}
368
- end
369
- end
370
-
371
- let(:parser) do
372
- proc { |data, format| CustomParser.parse(data) }
373
- end
374
-
375
- it "should set parser options" do
376
- @klass.parser parser
377
- expect(@klass.default_options[:parser]).to eq(parser)
378
- end
379
-
380
- it "should be able parse response with custom parser" do
381
- @klass.parser parser
382
- stub_request(:get, 'http://twitter.com/statuses/public_timeline.xml')
383
- .to_return(body: 'tweets')
384
- custom_parsed_response = @klass.get('http://twitter.com/statuses/public_timeline.xml')
385
- expect(custom_parsed_response[:sexy]).to eq(true)
386
- end
387
-
388
- it "raises UnsupportedFormat when the parser cannot handle the format" do
389
- @klass.format :json
390
-
391
- parser_class = Class.new(HTTParty::Parser)
392
- parser_class::SupportedFormats = {}
393
-
394
- expect do
395
- @klass.parser parser_class
396
- end.to raise_error(HTTParty::UnsupportedFormat)
397
- end
398
-
399
- it 'does not validate format whe custom parser is a proc' do
400
- expect do
401
- @klass.format :json
402
- @klass.parser lambda {|body, format|}
403
- end.to_not raise_error
404
- end
405
- end
406
-
407
- describe "uri_adapter" do
408
-
409
- require 'forwardable'
410
- class CustomURIAdaptor
411
- extend Forwardable
412
- def_delegators :@uri, :userinfo, :relative?, :query, :query=, :scheme, :path, :host, :port
413
-
414
- def initialize uri
415
- @uri = uri
416
- end
417
-
418
- def self.parse uri
419
- new URI.parse uri
420
- end
421
- end
422
-
423
- let(:uri_adapter) { CustomURIAdaptor }
424
-
425
- it "should set the uri_adapter" do
426
- @klass.uri_adapter uri_adapter
427
- expect(@klass.default_options[:uri_adapter]).to be uri_adapter
428
- end
429
-
430
- it "should raise an ArgumentError if uri_adapter doesn't implement parse method" do
431
- expect do
432
- @klass.uri_adapter double()
433
- end.to raise_error(ArgumentError)
434
- end
435
-
436
-
437
- it "should process a request with a uri instance parsed from the uri_adapter" do
438
- uri = 'http://foo.com/bar'
439
- stub_request(:get, uri).to_return(body: 'stuff')
440
- @klass.uri_adapter uri_adapter
441
- expect(@klass.get(uri).parsed_response).to eq('stuff')
442
- end
443
-
444
- end
445
-
446
- describe "connection_adapter" do
447
- let(:uri) { 'http://google.com/api.json' }
448
- let(:connection_adapter) { double('CustomConnectionAdapter') }
449
-
450
- it "should set the connection_adapter" do
451
- @klass.connection_adapter connection_adapter
452
- expect(@klass.default_options[:connection_adapter]).to be connection_adapter
453
- end
454
-
455
- it "should set the connection_adapter_options when provided" do
456
- options = {foo: :bar}
457
- @klass.connection_adapter connection_adapter, options
458
- expect(@klass.default_options[:connection_adapter_options]).to be options
459
- end
460
-
461
- it "should not set the connection_adapter_options when not provided" do
462
- @klass.connection_adapter connection_adapter
463
- expect(@klass.default_options[:connection_adapter_options]).to be_nil
464
- end
465
-
466
- it "should process a request with a connection from the adapter" do
467
- connection_adapter_options = {foo: :bar}
468
- expect(connection_adapter).to receive(:call) { |u, o|
469
- expect(o[:connection_adapter_options]).to eq(connection_adapter_options)
470
- HTTParty::ConnectionAdapter.call(u, o)
471
- }.with(URI.parse(uri), kind_of(Hash))
472
- stub_request(:get, uri).to_return(body: 'stuff')
473
- @klass.connection_adapter connection_adapter, connection_adapter_options
474
- expect(@klass.get(uri).parsed_response).to eq('stuff')
475
- end
476
- end
477
-
478
- describe "format" do
479
- it "should allow xml" do
480
- @klass.format :xml
481
- expect(@klass.default_options[:format]).to eq(:xml)
482
- end
483
-
484
- it "should allow csv" do
485
- @klass.format :csv
486
- expect(@klass.default_options[:format]).to eq(:csv)
487
- end
488
-
489
- it "should allow json" do
490
- @klass.format :json
491
- expect(@klass.default_options[:format]).to eq(:json)
492
- end
493
-
494
- it "should allow plain" do
495
- @klass.format :plain
496
- expect(@klass.default_options[:format]).to eq(:plain)
497
- end
498
-
499
- it 'should not allow funky format' do
500
- expect do
501
- @klass.format :foobar
502
- end.to raise_error(HTTParty::UnsupportedFormat)
503
- end
504
-
505
- it 'should only print each format once with an exception' do
506
- expect do
507
- @klass.format :foobar
508
- end.to raise_error(HTTParty::UnsupportedFormat, "':foobar' Must be one of: csv, html, json, plain, xml")
509
- end
510
-
511
- it 'sets the default parser' do
512
- expect(@klass.default_options[:parser]).to be_nil
513
- @klass.format :json
514
- expect(@klass.default_options[:parser]).to eq(HTTParty::Parser)
515
- end
516
-
517
- it 'does not reset parser to the default parser' do
518
- my_parser = lambda {}
519
- @klass.parser my_parser
520
- @klass.format :json
521
- expect(@klass.parser).to eq(my_parser)
522
- end
523
- end
524
-
525
- describe "#no_follow" do
526
- it "sets no_follow to false by default" do
527
- @klass.no_follow
528
- expect(@klass.default_options[:no_follow]).to be_falsey
529
- end
530
-
531
- it "sets the no_follow option to true" do
532
- @klass.no_follow true
533
- expect(@klass.default_options[:no_follow]).to be_truthy
534
- end
535
- end
536
-
537
- describe "#maintain_method_across_redirects" do
538
- it "sets maintain_method_across_redirects to true by default" do
539
- @klass.maintain_method_across_redirects
540
- expect(@klass.default_options[:maintain_method_across_redirects]).to be_truthy
541
- end
542
-
543
- it "sets the maintain_method_across_redirects option to false" do
544
- @klass.maintain_method_across_redirects false
545
- expect(@klass.default_options[:maintain_method_across_redirects]).to be_falsey
546
- end
547
- end
548
-
549
- describe "#resend_on_redirect" do
550
- it "sets resend_on_redirect to true by default" do
551
- @klass.resend_on_redirect
552
- expect(@klass.default_options[:resend_on_redirect]).to be_truthy
553
- end
554
-
555
- it "sets resend_on_redirect option to false" do
556
- @klass.resend_on_redirect false
557
- expect(@klass.default_options[:resend_on_redirect]).to be_falsey
558
- end
559
- end
560
-
561
- describe ".follow_redirects" do
562
- it "sets follow redirects to true by default" do
563
- @klass.follow_redirects
564
- expect(@klass.default_options[:follow_redirects]).to be_truthy
565
- end
566
-
567
- it "sets the follow_redirects option to false" do
568
- @klass.follow_redirects false
569
- expect(@klass.default_options[:follow_redirects]).to be_falsey
570
- end
571
- end
572
-
573
- describe ".query_string_normalizer" do
574
- it "sets the query_string_normalizer option" do
575
- normalizer = proc {}
576
- @klass.query_string_normalizer normalizer
577
- expect(@klass.default_options[:query_string_normalizer]).to eq(normalizer)
578
- end
579
- end
580
-
581
- describe ".raise_on" do
582
- context 'when parameters is an array' do
583
- it 'sets raise_on option' do
584
- @klass.raise_on [500, 404]
585
- expect(@klass.default_options[:raise_on]).to contain_exactly(404, 500)
586
- end
587
- end
588
-
589
- context 'when parameters is a fixnum' do
590
- it 'sets raise_on option' do
591
- @klass.raise_on 404
592
- expect(@klass.default_options[:raise_on]).to contain_exactly(404)
593
- end
594
- end
595
- end
596
-
597
- describe "with explicit override of automatic redirect handling" do
598
- before do
599
- @request = HTTParty::Request.new(Net::HTTP::Get, 'http://api.foo.com/v1', format: :xml, no_follow: true)
600
- @redirect = stub_response 'first redirect', 302
601
- @redirect['location'] = 'http://foo.com/bar'
602
- allow(HTTParty::Request).to receive_messages(new: @request)
603
- end
604
-
605
- it "should fail with redirected GET" do
606
- expect do
607
- @error = @klass.get('/foo', no_follow: true)
608
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
609
- end
610
-
611
- it "should fail with redirected POST" do
612
- expect do
613
- @klass.post('/foo', no_follow: true)
614
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
615
- end
616
-
617
- it "should fail with redirected PATCH" do
618
- expect do
619
- @klass.patch('/foo', no_follow: true)
620
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
621
- end
622
-
623
- it "should fail with redirected DELETE" do
624
- expect do
625
- @klass.delete('/foo', no_follow: true)
626
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
627
- end
628
-
629
- it "should fail with redirected MOVE" do
630
- expect do
631
- @klass.move('/foo', no_follow: true)
632
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
633
- end
634
-
635
- it "should fail with redirected COPY" do
636
- expect do
637
- @klass.copy('/foo', no_follow: true)
638
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
639
- end
640
-
641
- it "should fail with redirected PUT" do
642
- expect do
643
- @klass.put('/foo', no_follow: true)
644
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
645
- end
646
-
647
- it "should fail with redirected HEAD" do
648
- expect do
649
- @klass.head('/foo', no_follow: true)
650
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
651
- end
652
-
653
- it "should fail with redirected OPTIONS" do
654
- expect do
655
- @klass.options('/foo', no_follow: true)
656
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
657
- end
658
-
659
- it "should fail with redirected MKCOL" do
660
- expect do
661
- @klass.mkcol('/foo', no_follow: true)
662
- end.to raise_error(HTTParty::RedirectionTooDeep) {|e| expect(e.response.body).to eq('first redirect')}
663
- end
664
- end
665
-
666
- describe "head requests should follow redirects requesting HEAD only" do
667
- before do
668
- allow(HTTParty::Request).to receive(:new).
669
- and_return(double("mock response", perform: nil))
670
- end
671
-
672
- it "should remain HEAD request across redirects, unless specified otherwise" do
673
- expect(@klass).to receive(:ensure_method_maintained_across_redirects).with({})
674
- @klass.head('/foo')
675
- end
676
-
677
- end
678
-
679
- describe "#ensure_method_maintained_across_redirects" do
680
- it "should set maintain_method_across_redirects option if unspecified" do
681
- options = {}
682
- @klass.send(:ensure_method_maintained_across_redirects, options)
683
- expect(options[:maintain_method_across_redirects]).to be_truthy
684
- end
685
-
686
- it "should not set maintain_method_across_redirects option if value is present" do
687
- options = { maintain_method_across_redirects: false }
688
- @klass.send(:ensure_method_maintained_across_redirects, options)
689
- expect(options[:maintain_method_across_redirects]).to be_falsey
690
- end
691
- end
692
-
693
- describe "with multiple class definitions" do
694
- before(:each) do
695
- @klass.instance_eval do
696
- base_uri "http://first.com"
697
- default_params one: 1
698
- end
699
-
700
- @additional_klass = Class.new
701
- @additional_klass.instance_eval do
702
- include HTTParty
703
- base_uri "http://second.com"
704
- default_params two: 2
705
- end
706
- end
707
-
708
- it "should not run over each others options" do
709
- expect(@klass.default_options).to eq({ base_uri: 'http://first.com', default_params: { one: 1 } })
710
- expect(@additional_klass.default_options).to eq({ base_uri: 'http://second.com', default_params: { two: 2 } })
711
- end
712
- end
713
-
714
- describe "two child classes inheriting from one parent" do
715
- before(:each) do
716
- @parent = Class.new do
717
- include HTTParty
718
- def self.name
719
- "Parent"
720
- end
721
- end
722
-
723
- @child1 = Class.new(@parent)
724
- @child2 = Class.new(@parent)
725
- end
726
-
727
- it "does not modify each others inherited attributes" do
728
- @child1.default_params joe: "alive"
729
- @child2.default_params joe: "dead"
730
-
731
- expect(@child1.default_options).to eq({ default_params: {joe: "alive"} })
732
- expect(@child2.default_options).to eq({ default_params: {joe: "dead"} })
733
-
734
- expect(@parent.default_options).to eq({ })
735
- end
736
-
737
- it "inherits default_options from the superclass" do
738
- @parent.basic_auth 'user', 'password'
739
- expect(@child1.default_options).to eq({basic_auth: {username: 'user', password: 'password'}})
740
- @child1.basic_auth 'u', 'p' # modifying child1 has no effect on child2
741
- expect(@child2.default_options).to eq({basic_auth: {username: 'user', password: 'password'}})
742
- end
743
-
744
- it "doesn't modify the parent's default options" do
745
- @parent.basic_auth 'user', 'password'
746
-
747
- @child1.basic_auth 'u', 'p'
748
- expect(@child1.default_options).to eq({basic_auth: {username: 'u', password: 'p'}})
749
-
750
- @child1.basic_auth 'email', 'token'
751
- expect(@child1.default_options).to eq({basic_auth: {username: 'email', password: 'token'}})
752
-
753
- expect(@parent.default_options).to eq({basic_auth: {username: 'user', password: 'password'}})
754
- end
755
-
756
- it "doesn't modify hashes in the parent's default options" do
757
- @parent.headers 'Accept' => 'application/json'
758
- @child1.headers 'Accept' => 'application/xml'
759
-
760
- expect(@parent.default_options[:headers]).to eq({'Accept' => 'application/json'})
761
- expect(@child1.default_options[:headers]).to eq({'Accept' => 'application/xml'})
762
- end
763
-
764
- it "works with lambda values" do
765
- @child1.default_options[:imaginary_option] = lambda { "This is a new lambda "}
766
- expect(@child1.default_options[:imaginary_option]).to be_a Proc
767
- end
768
-
769
- it 'should dup the proc on the child class' do
770
- imaginary_option = lambda { 2 * 3.14 }
771
- @parent.default_options[:imaginary_option] = imaginary_option
772
- expect(@parent.default_options[:imaginary_option].call).to eq(imaginary_option.call)
773
- @child1.default_options[:imaginary_option]
774
- expect(@child1.default_options[:imaginary_option].call).to eq(imaginary_option.call)
775
- expect(@child1.default_options[:imaginary_option]).not_to be_equal imaginary_option
776
- end
777
-
778
- it "inherits default_cookies from the parent class" do
779
- @parent.cookies 'type' => 'chocolate_chip'
780
- expect(@child1.default_cookies).to eq({"type" => "chocolate_chip"})
781
- @child1.cookies 'type' => 'snickerdoodle'
782
- expect(@child1.default_cookies).to eq({"type" => "snickerdoodle"})
783
- expect(@child2.default_cookies).to eq({"type" => "chocolate_chip"})
784
- end
785
-
786
- it "doesn't modify the parent's default cookies" do
787
- @parent.cookies 'type' => 'chocolate_chip'
788
-
789
- @child1.cookies 'type' => 'snickerdoodle'
790
- expect(@child1.default_cookies).to eq({"type" => "snickerdoodle"})
791
-
792
- expect(@parent.default_cookies).to eq({"type" => "chocolate_chip"})
793
- end
794
- end
795
-
796
- describe "grand parent with inherited callback" do
797
- before do
798
- @grand_parent = Class.new do
799
- def self.inherited(subclass)
800
- subclass.instance_variable_set(:@grand_parent, true)
801
- end
802
- end
803
- @parent = Class.new(@grand_parent) do
804
- include HTTParty
805
- end
806
- end
807
- it "continues running the #inherited on the parent" do
808
- child = Class.new(@parent)
809
- expect(child.instance_variable_get(:@grand_parent)).to be_truthy
810
- end
811
- end
812
-
813
- describe "#get" do
814
- it "should be able to get html" do
815
- stub_http_response_with('example.html')
816
- expect(HTTParty.get('http://www.example.com').parsed_response).to eq(file_fixture('example.html'))
817
- end
818
-
819
- it "should be able to get chunked html" do
820
- chunks = %w(Chunk1 Chunk2 Chunk3 Chunk4)
821
- stub_chunked_http_response_with(chunks)
822
-
823
- expect(
824
- HTTParty.get('http://www.google.com') do |fragment|
825
- expect(chunks).to include(fragment)
826
- end.parsed_response
827
- ).to eq(chunks.join)
828
- end
829
-
830
- it "should return an empty body if stream_body option is turned on" do
831
- chunks = %w(Chunk1 Chunk2 Chunk3 Chunk4)
832
- options = {stream_body: true, format: 'html'}
833
- stub_chunked_http_response_with(chunks, options)
834
-
835
- expect(
836
- HTTParty.get('http://www.google.com', options) do |fragment|
837
- expect(chunks).to include(fragment)
838
- expect(fragment.code).to eql 200
839
- expect(fragment.http_response).to be
840
- end.parsed_response
841
- ).to eq(nil)
842
- end
843
-
844
- context 'when streaming body' do
845
- let(:chunk) { 'Content'.force_encoding('ascii-8bit') }
846
- let(:options) { { stream_body: true } }
847
- before do
848
- stub_chunked_http_response_with([chunk], options) do |response|
849
- allow(response).to receive(:[]).with('content-type').and_return('text/plain; charset = "utf-8"')
850
- end
851
- end
852
-
853
- specify do
854
- HTTParty.get('http://www.google.com', options) do |fragment|
855
- expect(fragment.encoding).to eq(Encoding.find("UTF-8"))
856
- end
857
- end
858
- end
859
-
860
- it "should be able parse response type json automatically" do
861
- stub_http_response_with('twitter.json')
862
- tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.json')
863
- expect(tweets.size).to eq(20)
864
- expect(tweets.first['user']).to eq({
865
- "name" => "Pyk",
866
- "url" => nil,
867
- "id" => "7694602",
868
- "description" => nil,
869
- "protected" => false,
870
- "screen_name" => "Pyk",
871
- "followers_count" => 1,
872
- "location" => "Opera Plaza, California",
873
- "profile_image_url" => "http://static.twitter.com/images/default_profile_normal.png"
874
- })
875
- end
876
-
877
- it "should be able parse response type xml automatically" do
878
- stub_http_response_with('twitter.xml')
879
- tweets = HTTParty.get('http://twitter.com/statuses/public_timeline.xml')
880
- expect(tweets['statuses'].size).to eq(20)
881
- expect(tweets['statuses'].first['user']).to eq({
882
- "name" => "Magic 8 Bot",
883
- "url" => nil,
884
- "id" => "17656026",
885
- "description" => "ask me a question",
886
- "protected" => "false",
887
- "screen_name" => "magic8bot",
888
- "followers_count" => "90",
889
- "profile_image_url" => "http://s3.amazonaws.com/twitter_production/profile_images/65565851/8ball_large_normal.jpg",
890
- "location" => nil
891
- })
892
- end
893
-
894
- it "should be able parse response type csv automatically" do
895
- stub_http_response_with('twitter.csv')
896
- profile = HTTParty.get('http://twitter.com/statuses/profile.csv')
897
- expect(profile.size).to eq(2)
898
- expect(profile[0]).to eq(%w(name url id description protected screen_name followers_count profile_image_url location))
899
- expect(profile[1]).to eq(["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])
900
- end
901
-
902
- it "should not get undefined method add_node for nil class for the following xml" do
903
- stub_http_response_with('undefined_method_add_node_for_nil.xml')
904
- result = HTTParty.get('http://foobar.com')
905
- expect(result.parsed_response).to eq({"Entities" => {"href" => "https://s3-sandbox.parature.com/api/v1/5578/5633/Account", "results" => "0", "total" => "0", "page_size" => "25", "page" => "1"}})
906
- end
907
-
908
- it "should parse empty response fine" do
909
- stub_http_response_with('empty.xml')
910
- result = HTTParty.get('http://foobar.com')
911
- expect(result).to be_nil
912
- end
913
-
914
- it "should accept http URIs" do
915
- stub_http_response_with('example.html')
916
- expect do
917
- HTTParty.get('http://example.com')
918
- end.not_to raise_error
919
- end
920
-
921
- it "should accept https URIs" do
922
- stub_http_response_with('example.html')
923
- expect do
924
- HTTParty.get('https://example.com')
925
- end.not_to raise_error
926
- end
927
-
928
- it "should accept webcal URIs" do
929
- uri = 'http://google.com/'
930
- stub_request(:get, uri).to_return(body: 'stuff')
931
- uri = 'webcal://google.com/'
932
- expect do
933
- HTTParty.get(uri)
934
- end.not_to raise_error
935
- end
936
-
937
- it "should raise an InvalidURIError on URIs that can't be parsed at all" do
938
- expect do
939
- HTTParty.get("It's the one that says 'Bad URI'")
940
- end.to raise_error(URI::InvalidURIError)
941
- end
942
- end
943
- end