httparty 0.16.2 → 0.16.3

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +18 -0
  3. data/.gitignore +1 -0
  4. data/Changelog.md +11 -0
  5. data/README.md +1 -1
  6. data/examples/README.md +22 -11
  7. data/examples/body_stream.rb +14 -0
  8. data/examples/microsoft_graph.rb +52 -0
  9. data/examples/multipart.rb +22 -0
  10. data/features/steps/mongrel_helper.rb +3 -3
  11. data/httparty.gemspec +2 -1
  12. data/lib/httparty.rb +21 -1
  13. data/lib/httparty/connection_adapter.rb +11 -4
  14. data/lib/httparty/hash_conversions.rb +6 -2
  15. data/lib/httparty/logger/apache_formatter.rb +29 -6
  16. data/lib/httparty/logger/curl_formatter.rb +4 -4
  17. data/lib/httparty/logger/logger.rb +3 -1
  18. data/lib/httparty/logger/logstash_formatter.rb +59 -0
  19. data/lib/httparty/module_inheritable_attributes.rb +3 -3
  20. data/lib/httparty/net_digest_auth.rb +6 -5
  21. data/lib/httparty/request.rb +8 -1
  22. data/lib/httparty/request/body.rb +16 -5
  23. data/lib/httparty/response.rb +19 -5
  24. data/lib/httparty/response/headers.rb +2 -2
  25. data/lib/httparty/utils.rb +11 -0
  26. data/lib/httparty/version.rb +1 -1
  27. data/spec/httparty/connection_adapter_spec.rb +7 -3
  28. data/spec/httparty/cookie_hash_spec.rb +1 -1
  29. data/spec/httparty/exception_spec.rb +1 -1
  30. data/spec/httparty/hash_conversions_spec.rb +2 -0
  31. data/spec/httparty/logger/apache_formatter_spec.rb +1 -2
  32. data/spec/httparty/logger/curl_formatter_spec.rb +1 -1
  33. data/spec/httparty/logger/logger_spec.rb +6 -1
  34. data/spec/httparty/logger/logstash_formatter_spec.rb +44 -0
  35. data/spec/httparty/net_digest_auth_spec.rb +22 -22
  36. data/spec/httparty/parser_spec.rb +1 -1
  37. data/spec/httparty/request/body_spec.rb +57 -8
  38. data/spec/httparty/request_spec.rb +68 -13
  39. data/spec/httparty/response_spec.rb +32 -20
  40. data/spec/httparty/ssl_spec.rb +1 -1
  41. data/spec/httparty_spec.rb +28 -7
  42. data/website/css/common.css +1 -1
  43. metadata +25 -3
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  RSpec.describe Net::HTTPHeader::DigestAuthenticator do
4
4
  def setup_digest(response)
@@ -19,7 +19,7 @@ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
19
19
 
20
20
  context 'Net::HTTPHeader#digest_auth' do
21
21
  let(:headers) {
22
- (Class.new do
22
+ (Class.new do
23
23
  include Net::HTTPHeader
24
24
  def initialize
25
25
  @header = {}
@@ -27,25 +27,25 @@ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
27
27
  @method = 'GET'
28
28
  end
29
29
  end).new
30
- }
30
+ }
31
31
 
32
32
  let(:response){
33
- (Class.new do
33
+ (Class.new do
34
34
  include Net::HTTPHeader
35
35
  def initialize
36
36
  @header = {}
37
- self['WWW-Authenticate'] =
37
+ self['WWW-Authenticate'] =
38
38
  'Digest realm="testrealm@host.com", qop="auth,auth-int", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"'
39
39
  end
40
40
  end).new
41
41
  }
42
42
 
43
- it 'should set the authorization header' do
43
+ it 'should set the authorization header' do
44
44
  expect(headers['authorization']).to be_nil
45
45
  headers.digest_auth('user','pass', response)
46
46
  expect(headers['authorization']).to_not be_empty
47
- end
48
- end
47
+ end
48
+ end
49
49
 
50
50
  context "with a cookie value in the response header" do
51
51
  before do
@@ -185,8 +185,8 @@ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
185
185
  context "with http basic auth response when net digest auth expected" do
186
186
  it "should not fail" do
187
187
  @digest = setup_digest({
188
- 'www-authenticate' => 'WWW-Authenticate: Basic realm="testrealm.com""'
189
- })
188
+ 'www-authenticate' => 'WWW-Authenticate: Basic realm="testrealm.com""'
189
+ })
190
190
 
191
191
  expect(authorization_header).to include("Digest")
192
192
  end
@@ -228,18 +228,18 @@ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
228
228
  expect(authorization_header).to include(%(response="#{request_digest}"))
229
229
  end
230
230
  end
231
-
231
+
232
232
  context "with algorithm specified" do
233
233
  before do
234
234
  @digest = setup_digest({
235
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5'
236
- })
235
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5'
236
+ })
237
237
  end
238
-
238
+
239
239
  it "should recognise algorithm was specified" do
240
240
  expect( @digest.send :algorithm_present? ).to be(true)
241
241
  end
242
-
242
+
243
243
  it "should set the algorithm header" do
244
244
  expect(authorization_header).to include('algorithm="MD5"')
245
245
  end
@@ -248,23 +248,23 @@ RSpec.describe Net::HTTPHeader::DigestAuthenticator do
248
248
  context "with md5-sess algorithm specified" do
249
249
  before do
250
250
  @digest = setup_digest({
251
- 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5-sess'
252
- })
251
+ 'www-authenticate' => 'Digest realm="myhost@testrealm.com", nonce="NONCE", qop="auth", algorithm=MD5-sess'
252
+ })
253
253
  end
254
-
254
+
255
255
  it "should recognise algorithm was specified" do
256
256
  expect( @digest.send :algorithm_present? ).to be(true)
257
257
  end
258
-
258
+
259
259
  it "should set the algorithm header" do
260
260
  expect(authorization_header).to include('algorithm="MD5-sess"')
261
261
  end
262
-
262
+
263
263
  it "should set response using md5-sess algorithm" do
264
264
  request_digest = "md5(md5(md5(Mufasa:myhost@testrealm.com:Circle Of Life):NONCE:md5(deadbeef)):NONCE:00000001:md5(deadbeef):auth:md5(GET:/dir/index.html))"
265
265
  expect(authorization_header).to include(%(response="#{request_digest}"))
266
266
  end
267
-
267
+
268
268
  end
269
-
269
+
270
270
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  RSpec.describe HTTParty::Parser do
4
4
  describe ".SupportedFormats" do
@@ -1,8 +1,11 @@
1
- require_relative '../../spec_helper'
1
+ require 'spec_helper'
2
+ require 'tempfile'
2
3
 
3
4
  RSpec.describe HTTParty::Request::Body do
4
5
  describe '#call' do
5
- subject { described_class.new(params).call }
6
+ let(:options) { {} }
7
+
8
+ subject { described_class.new(params, options).call }
6
9
 
7
10
  context 'when params is string' do
8
11
  let(:params) { 'name=Bob%20Jones' }
@@ -18,26 +21,30 @@ RSpec.describe HTTParty::Request::Body do
18
21
 
19
22
  context 'when params has file' do
20
23
  before do
21
- allow(HTTParty::Request::MultipartBoundary).
22
- to receive(:generate).and_return("------------------------c772861a5109d5ef")
24
+ allow(HTTParty::Request::MultipartBoundary)
25
+ .to receive(:generate).and_return("------------------------c772861a5109d5ef")
23
26
  end
24
27
 
28
+ let(:file) { File.open('spec/fixtures/tiny.gif') }
25
29
  let(:params) do
26
30
  {
27
31
  user: {
28
- avatar: File.open('spec/fixtures/tiny.gif'),
32
+ avatar: file,
29
33
  first_name: 'John',
30
34
  last_name: 'Doe',
31
35
  enabled: true
32
36
  }
33
37
  }
34
38
  end
39
+ let(:expected_file_name) { 'tiny.gif' }
40
+ let(:expected_file_contents) { "GIF89a\u0001\u0000\u0001\u0000\u0000\xFF\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0000;" }
41
+ let(:expected_content_type) { 'image/gif' }
35
42
  let(:multipart_params) do
36
43
  "--------------------------c772861a5109d5ef\r\n" \
37
- "Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"tiny.gif\"\r\n" \
38
- "Content-Type: application/octet-stream\r\n" \
44
+ "Content-Disposition: form-data; name=\"user[avatar]\"; filename=\"#{expected_file_name}\"\r\n" \
45
+ "Content-Type: #{expected_content_type}\r\n" \
39
46
  "\r\n" \
40
- "GIF89a\u0001\u0000\u0001\u0000\u0000\xFF\u0000,\u0000\u0000\u0000\u0000\u0001\u0000\u0001\u0000\u0000\u0002\u0000;\r\n" \
47
+ "#{expected_file_contents}\r\n" \
41
48
  "--------------------------c772861a5109d5ef\r\n" \
42
49
  "Content-Disposition: form-data; name=\"user[first_name]\"\r\n" \
43
50
  "\r\n" \
@@ -54,6 +61,48 @@ RSpec.describe HTTParty::Request::Body do
54
61
  end
55
62
 
56
63
  it { is_expected.to eq multipart_params }
64
+
65
+ context 'when passing multipart as an option' do
66
+ let(:options) { { force_multipart: true } }
67
+ let(:params) do
68
+ {
69
+ user: {
70
+ first_name: 'John',
71
+ last_name: 'Doe',
72
+ enabled: true
73
+ }
74
+ }
75
+ end
76
+ let(:multipart_params) do
77
+ "--------------------------c772861a5109d5ef\r\n" \
78
+ "Content-Disposition: form-data; name=\"user[first_name]\"\r\n" \
79
+ "\r\n" \
80
+ "John\r\n" \
81
+ "--------------------------c772861a5109d5ef\r\n" \
82
+ "Content-Disposition: form-data; name=\"user[last_name]\"\r\n" \
83
+ "\r\n" \
84
+ "Doe\r\n" \
85
+ "--------------------------c772861a5109d5ef\r\n" \
86
+ "Content-Disposition: form-data; name=\"user[enabled]\"\r\n" \
87
+ "\r\n" \
88
+ "true\r\n" \
89
+ "--------------------------c772861a5109d5ef--\r\n"
90
+ end
91
+
92
+ it { is_expected.to eq multipart_params }
93
+
94
+ end
95
+
96
+ context 'file object responds to original_filename' do
97
+ let(:some_temp_file) { Tempfile.new(['some_temp_file','.gif']) }
98
+ let(:expected_file_name) { "some_temp_file.gif" }
99
+ let(:expected_file_contents) { "Hello" }
100
+ let(:file) { double(:mocked_action_dispatch, path: some_temp_file.path, original_filename: 'some_temp_file.gif', read: expected_file_contents) }
101
+
102
+ before { some_temp_file.write('Hello') }
103
+
104
+ it { is_expected.to eq multipart_params }
105
+ end
57
106
  end
58
107
  end
59
108
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  RSpec.describe HTTParty::Request do
4
4
  before do
@@ -73,7 +73,7 @@ RSpec.describe HTTParty::Request do
73
73
  expect(request.parser).to eq(my_parser)
74
74
  end
75
75
 
76
- it "sets connection_adapter to HTTPParty::ConnectionAdapter" do
76
+ it "sets connection_adapter to HTTParty::ConnectionAdapter" do
77
77
  request = HTTParty::Request.new(Net::HTTP::Get, 'http://google.com')
78
78
  expect(request.connection_adapter).to eq(HTTParty::ConnectionAdapter)
79
79
  end
@@ -343,22 +343,35 @@ RSpec.describe HTTParty::Request do
343
343
  end
344
344
  end
345
345
 
346
- context "when body is multipart" do
347
- it "sets header Content-Type: multipart/form-data; boundary=" do
348
- @request.options[:body] = {file: File.open(File::NULL, 'r')}
346
+ context "when mulipart" do
347
+ subject(:headers) do
349
348
  @request.send(:setup_raw_request)
350
349
  headers = @request.instance_variable_get(:@raw_request).each_header.to_a
351
- headers = Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h
352
- expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
350
+ Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h
353
351
  end
354
352
 
355
- context "and header Content-Type is provided" do
356
- it "overwrites the header to: multipart/form-data; boundary=" do
353
+ context "when body contains file" do
354
+ it "sets header Content-Type: multipart/form-data; boundary=" do
357
355
  @request.options[:body] = {file: File.open(File::NULL, 'r')}
358
- @request.options[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
359
- @request.send(:setup_raw_request)
360
- headers = @request.instance_variable_get(:@raw_request).each_header.to_a
361
- headers = Hash[*headers.flatten] # Ruby 2.0 doesn't have Array#to_h
356
+
357
+ expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
358
+ end
359
+
360
+ context "and header Content-Type is provided" do
361
+ it "overwrites the header to: multipart/form-data; boundary=" do
362
+ @request.options[:body] = {file: File.open(File::NULL, 'r')}
363
+ @request.options[:headers] = {'Content-Type' => 'application/x-www-form-urlencoded'}
364
+
365
+ expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
366
+ end
367
+ end
368
+ end
369
+
370
+ context 'when mulipart option is provided' do
371
+ it "sets header Content-Type: multipart/form-data; boundary=" do
372
+ @request.options[:body] = { text: 'something' }
373
+ @request.options[:multipart] = true
374
+
362
375
  expect(headers['content-type']).to match(%r{^multipart/form-data; boundary=---})
363
376
  end
364
377
  end
@@ -788,6 +801,16 @@ RSpec.describe HTTParty::Request do
788
801
  expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
789
802
  end
790
803
 
804
+ it "should be handled by LOCK transparently" do
805
+ @request.http_method = Net::HTTP::Lock
806
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
807
+ end
808
+
809
+ it "should be handled by UNLOCK transparently" do
810
+ @request.http_method = Net::HTTP::Unlock
811
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
812
+ end
813
+
791
814
  it "should keep track of cookies between redirects" do
792
815
  @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
793
816
  @request.perform
@@ -914,6 +937,16 @@ RSpec.describe HTTParty::Request do
914
937
  expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
915
938
  end
916
939
 
940
+ it "should be handled by LOCK transparently" do
941
+ @request.http_method = Net::HTTP::Lock
942
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
943
+ end
944
+
945
+ it "should be handled by UNLOCK transparently" do
946
+ @request.http_method = Net::HTTP::Unlock
947
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
948
+ end
949
+
917
950
  it "should keep track of cookies between redirects" do
918
951
  @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
919
952
  @request.perform
@@ -1052,6 +1085,16 @@ RSpec.describe HTTParty::Request do
1052
1085
  expect(@request.perform.code).to eq(304)
1053
1086
  end
1054
1087
 
1088
+ it "should be handled by LOCK transparently" do
1089
+ @request.http_method = Net::HTTP::Lock
1090
+ expect(@request.perform.code).to eq(304)
1091
+ end
1092
+
1093
+ it "should be handled by UNLOCK transparently" do
1094
+ @request.http_method = Net::HTTP::Unlock
1095
+ expect(@request.perform.code).to eq(304)
1096
+ end
1097
+
1055
1098
  it 'should not log the redirection' do
1056
1099
  logger_double = double
1057
1100
  expect(logger_double).to receive(:info).once
@@ -1123,6 +1166,18 @@ RSpec.describe HTTParty::Request do
1123
1166
  expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
1124
1167
  end
1125
1168
 
1169
+ it "should be handled by LOCK transparently" do
1170
+ @request.http_method = Net::HTTP::Lock
1171
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
1172
+ end
1173
+
1174
+ it "should be handled by UNLOCK transparently" do
1175
+ @request.http_method = Net::HTTP::Unlock
1176
+ expect(@request.perform.parsed_response).to eq({"hash" => {"foo" => "bar"}})
1177
+ end
1178
+
1179
+
1180
+
1126
1181
  it "should keep track of cookies between redirects" do
1127
1182
  @redirect['Set-Cookie'] = 'foo=bar; name=value; HTTPOnly'
1128
1183
  @request.perform
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
1
+ require 'spec_helper'
2
2
 
3
3
  RSpec.describe HTTParty::Response do
4
4
  before do
@@ -78,11 +78,11 @@ RSpec.describe HTTParty::Response do
78
78
  }.to raise_error(NameError, /HTTParty\:\:Response/)
79
79
  end
80
80
 
81
- it 'does raise an error about itself when invoking a method that does not exist' do
81
+ it 'does raise an error about itself when invoking a method that does not exist' do
82
82
  expect {
83
83
  HTTParty::Response.new(@request_object, @response_object, @parsed_response).qux
84
84
  }.to raise_error(NoMethodError, /HTTParty\:\:Response/)
85
- end
85
+ end
86
86
 
87
87
  it "returns response headers" do
88
88
  response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
@@ -131,21 +131,21 @@ RSpec.describe HTTParty::Response do
131
131
 
132
132
  context 'response is array' do
133
133
  let(:response_value) { [{'foo' => 'bar'}, {'foo' => 'baz'}] }
134
- let(:response) { HTTParty::Response.new(@request_object, @response_object, lambda { response_value }) }
135
- it "should be able to iterate" do
134
+ let(:response) { HTTParty::Response.new(@request_object, @response_object, lambda { response_value }) }
135
+ it "should be able to iterate" do
136
136
  expect(response.size).to eq(2)
137
137
  expect {
138
138
  response.each { |item| }
139
139
  }.to_not raise_error
140
140
  end
141
141
 
142
- it 'should respond to array methods' do
143
- expect(response).to respond_to(:bsearch, :compact, :cycle, :delete, :each, :flatten, :flatten!, :compact, :join)
142
+ it 'should respond to array methods' do
143
+ expect(response).to respond_to(:bsearch, :compact, :cycle, :delete, :each, :flatten, :flatten!, :compact, :join)
144
144
  end
145
145
 
146
146
  it 'should equal the string response object body' do
147
- expect(response.to_s).to eq(@response_object.body.to_s)
148
- end
147
+ expect(response.to_s).to eq(@response_object.body.to_s)
148
+ end
149
149
 
150
150
  it 'should display the same as an array' do
151
151
  a = StringIO.new
@@ -153,7 +153,7 @@ RSpec.describe HTTParty::Response do
153
153
  response_value.display(b)
154
154
  response.display(a)
155
155
 
156
- expect(a.string).to eq(b.string)
156
+ expect(a.string).to eq(b.string)
157
157
  end
158
158
  end
159
159
 
@@ -294,27 +294,27 @@ RSpec.describe HTTParty::Response do
294
294
 
295
295
  describe "headers" do
296
296
  let (:empty_headers) { HTTParty::Response::Headers.new }
297
- let (:some_headers_hash) do
297
+ let (:some_headers_hash) do
298
298
  {'Cookie' => 'bob',
299
299
  'Content-Encoding' => 'meow'}
300
- end
301
- let (:some_headers) do
302
- HTTParty::Response::Headers.new.tap do |h|
303
- some_headers_hash.each_pair do |k,v|
304
- h[k] = v
305
- end
300
+ end
301
+ let (:some_headers) do
302
+ HTTParty::Response::Headers.new.tap do |h|
303
+ some_headers_hash.each_pair do |k,v|
304
+ h[k] = v
305
+ end
306
306
  end
307
307
  end
308
- it "can initialize without headers" do
308
+ it "can initialize without headers" do
309
309
  expect(empty_headers).to eq({})
310
310
  end
311
311
 
312
312
  it 'always equals itself' do
313
- expect(empty_headers).to eq(empty_headers)
313
+ expect(empty_headers).to eq(empty_headers)
314
314
  expect(some_headers).to eq(some_headers)
315
315
  end
316
316
 
317
- it 'does not equal itself when not equivalent' do
317
+ it 'does not equal itself when not equivalent' do
318
318
  expect(empty_headers).to_not eq(some_headers)
319
319
  end
320
320
 
@@ -344,4 +344,16 @@ RSpec.describe HTTParty::Response do
344
344
  expect(inspect).to include("content-length")
345
345
  end
346
346
  end
347
+
348
+ describe 'marshalling' do
349
+ before { RSpec::Mocks.space.proxy_for(@response_object).remove_stub(:body) }
350
+
351
+ specify do
352
+ marshalled = Marshal.load(Marshal.dump(@response))
353
+
354
+ expect(marshalled.headers).to eq @response.headers
355
+ expect(marshalled.body).to eq @response.body
356
+ expect(marshalled.code).to eq @response.code
357
+ end
358
+ end
347
359
  end