httparty 0.16.4 → 0.20.0

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 (87) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +23 -0
  3. data/.rubocop_todo.yml +1 -1
  4. data/Changelog.md +55 -0
  5. data/Gemfile +5 -0
  6. data/README.md +4 -4
  7. data/docs/README.md +70 -5
  8. data/examples/README.md +6 -0
  9. data/examples/aaws.rb +6 -2
  10. data/examples/idn.rb +10 -0
  11. data/examples/peer_cert.rb +9 -0
  12. data/httparty.gemspec +1 -2
  13. data/lib/httparty/connection_adapter.rb +41 -10
  14. data/lib/httparty/cookie_hash.rb +10 -8
  15. data/lib/httparty/decompressor.rb +92 -0
  16. data/lib/httparty/exceptions.rb +3 -1
  17. data/lib/httparty/hash_conversions.rb +4 -2
  18. data/lib/httparty/headers_processor.rb +32 -0
  19. data/lib/httparty/logger/apache_formatter.rb +4 -2
  20. data/lib/httparty/logger/curl_formatter.rb +6 -4
  21. data/lib/httparty/logger/logger.rb +2 -0
  22. data/lib/httparty/logger/logstash_formatter.rb +4 -2
  23. data/lib/httparty/module_inheritable_attributes.rb +3 -1
  24. data/lib/httparty/net_digest_auth.rb +9 -10
  25. data/lib/httparty/parser.rb +9 -5
  26. data/lib/httparty/request/body.rb +24 -10
  27. data/lib/httparty/request/multipart_boundary.rb +2 -0
  28. data/lib/httparty/request.rb +67 -96
  29. data/lib/httparty/response/headers.rb +2 -0
  30. data/lib/httparty/response.rb +24 -4
  31. data/lib/httparty/{fragment_with_response.rb → response_fragment.rb} +6 -5
  32. data/lib/httparty/text_encoder.rb +72 -0
  33. data/lib/httparty/utils.rb +2 -0
  34. data/lib/httparty/version.rb +3 -1
  35. data/lib/httparty.rb +58 -35
  36. metadata +12 -108
  37. data/.travis.yml +0 -11
  38. data/features/basic_authentication.feature +0 -20
  39. data/features/command_line.feature +0 -95
  40. data/features/deals_with_http_error_codes.feature +0 -26
  41. data/features/digest_authentication.feature +0 -30
  42. data/features/handles_compressed_responses.feature +0 -27
  43. data/features/handles_multiple_formats.feature +0 -57
  44. data/features/steps/env.rb +0 -27
  45. data/features/steps/httparty_response_steps.rb +0 -56
  46. data/features/steps/httparty_steps.rb +0 -43
  47. data/features/steps/mongrel_helper.rb +0 -127
  48. data/features/steps/remote_service_steps.rb +0 -92
  49. data/features/supports_read_timeout_option.feature +0 -13
  50. data/features/supports_redirection.feature +0 -22
  51. data/features/supports_timeout_option.feature +0 -13
  52. data/spec/fixtures/delicious.xml +0 -23
  53. data/spec/fixtures/empty.xml +0 -0
  54. data/spec/fixtures/example.html +0 -10
  55. data/spec/fixtures/ssl/generate.sh +0 -29
  56. data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
  57. data/spec/fixtures/ssl/generated/ca.crt +0 -16
  58. data/spec/fixtures/ssl/generated/ca.key +0 -15
  59. data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
  60. data/spec/fixtures/ssl/generated/server.crt +0 -13
  61. data/spec/fixtures/ssl/generated/server.key +0 -15
  62. data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
  63. data/spec/fixtures/tiny.gif +0 -0
  64. data/spec/fixtures/twitter.csv +0 -2
  65. data/spec/fixtures/twitter.json +0 -1
  66. data/spec/fixtures/twitter.xml +0 -403
  67. data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
  68. data/spec/httparty/connection_adapter_spec.rb +0 -502
  69. data/spec/httparty/cookie_hash_spec.rb +0 -100
  70. data/spec/httparty/exception_spec.rb +0 -45
  71. data/spec/httparty/fragment_with_response_spec.rb +0 -14
  72. data/spec/httparty/hash_conversions_spec.rb +0 -58
  73. data/spec/httparty/logger/apache_formatter_spec.rb +0 -40
  74. data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
  75. data/spec/httparty/logger/logger_spec.rb +0 -43
  76. data/spec/httparty/logger/logstash_formatter_spec.rb +0 -44
  77. data/spec/httparty/net_digest_auth_spec.rb +0 -270
  78. data/spec/httparty/parser_spec.rb +0 -190
  79. data/spec/httparty/request/body_spec.rb +0 -165
  80. data/spec/httparty/request_spec.rb +0 -1367
  81. data/spec/httparty/response_spec.rb +0 -368
  82. data/spec/httparty/ssl_spec.rb +0 -74
  83. data/spec/httparty_spec.rb +0 -923
  84. data/spec/spec_helper.rb +0 -56
  85. data/spec/support/ssl_test_helper.rb +0 -47
  86. data/spec/support/ssl_test_server.rb +0 -80
  87. data/spec/support/stub_response.rb +0 -49
@@ -1,368 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe HTTParty::Response do
4
- before do
5
- @last_modified = Date.new(2010, 1, 15).to_s
6
- @content_length = '1024'
7
- @request_object = HTTParty::Request.new Net::HTTP::Get, '/'
8
- @response_object = Net::HTTPOK.new('1.1', 200, 'OK')
9
- allow(@response_object).to receive_messages(body: "{foo:'bar'}")
10
- @response_object['last-modified'] = @last_modified
11
- @response_object['content-length'] = @content_length
12
- @parsed_response = lambda { {"foo" => "bar"} }
13
- @response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
14
- end
15
-
16
- describe ".underscore" do
17
- it "works with one capitalized word" do
18
- expect(HTTParty::Response.underscore("Accepted")).to eq("accepted")
19
- end
20
-
21
- it "works with titlecase" do
22
- expect(HTTParty::Response.underscore("BadGateway")).to eq("bad_gateway")
23
- end
24
-
25
- it "works with all caps" do
26
- expect(HTTParty::Response.underscore("OK")).to eq("ok")
27
- end
28
- end
29
-
30
- describe "initialization" do
31
- it "should set the Net::HTTP Response" do
32
- expect(@response.response).to eq(@response_object)
33
- end
34
-
35
- it "should set body" do
36
- expect(@response.body).to eq(@response_object.body)
37
- end
38
-
39
- it "should set code" do
40
- expect(@response.code).to eq(@response_object.code)
41
- end
42
-
43
- it "should set code as an Integer" do
44
- expect(@response.code).to be_a(Integer)
45
- end
46
-
47
- context 'when raise_on is supplied' do
48
- let(:request) { HTTParty::Request.new(Net::HTTP::Get, '/', raise_on: [404]) }
49
-
50
- context "and response's status code is in range" do
51
- let(:body) { 'Not Found' }
52
- let(:response) { Net::HTTPNotFound.new('1.1', 404, body) }
53
-
54
- before do
55
- allow(response).to receive(:body).and_return(body)
56
- end
57
-
58
- subject { described_class.new(request, response, @parsed_response) }
59
-
60
- it 'throws exception' do
61
- expect{ subject }.to raise_error(HTTParty::ResponseError, "Code 404 - #{body}")
62
- end
63
- end
64
-
65
- context "and response's status code is not in range" do
66
- subject { described_class.new(request, @response_object, @parsed_response) }
67
-
68
- it 'does not throw exception' do
69
- expect{ subject }.not_to raise_error
70
- end
71
- end
72
- end
73
- end
74
-
75
- it 'does raise an error about itself when using #method' do
76
- expect {
77
- HTTParty::Response.new(@request_object, @response_object, @parsed_response).method(:qux)
78
- }.to raise_error(NameError, /HTTParty\:\:Response/)
79
- end
80
-
81
- it 'does raise an error about itself when invoking a method that does not exist' do
82
- expect {
83
- HTTParty::Response.new(@request_object, @response_object, @parsed_response).qux
84
- }.to raise_error(NoMethodError, /HTTParty\:\:Response/)
85
- end
86
-
87
- it "returns response headers" do
88
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
89
- expect(response.headers).to eq({'last-modified' => [@last_modified], 'content-length' => [@content_length]})
90
- end
91
-
92
- it "should send missing methods to delegate" do
93
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
94
- expect(response['foo']).to eq('bar')
95
- end
96
-
97
- it "response to request" do
98
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
99
- expect(response.respond_to?(:request)).to be_truthy
100
- end
101
-
102
- it "responds to response" do
103
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
104
- expect(response.respond_to?(:response)).to be_truthy
105
- end
106
-
107
- it "responds to body" do
108
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
109
- expect(response.respond_to?(:body)).to be_truthy
110
- end
111
-
112
- it "responds to headers" do
113
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
114
- expect(response.respond_to?(:headers)).to be_truthy
115
- end
116
-
117
- it "responds to parsed_response" do
118
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
119
- expect(response.respond_to?(:parsed_response)).to be_truthy
120
- end
121
-
122
- it "responds to predicates" do
123
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
124
- expect(response.respond_to?(:success?)).to be_truthy
125
- end
126
-
127
- it "responds to anything parsed_response responds to" do
128
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
129
- expect(response.respond_to?(:[])).to be_truthy
130
- end
131
-
132
- context 'response is array' do
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
136
- expect(response.size).to eq(2)
137
- expect {
138
- response.each { |item| }
139
- }.to_not raise_error
140
- end
141
-
142
- it 'should respond to array methods' do
143
- expect(response).to respond_to(:bsearch, :compact, :cycle, :delete, :each, :flatten, :flatten!, :compact, :join)
144
- end
145
-
146
- it 'should equal the string response object body' do
147
- expect(response.to_s).to eq(@response_object.body.to_s)
148
- end
149
-
150
- it 'should display the same as an array' do
151
- a = StringIO.new
152
- b = StringIO.new
153
- response_value.display(b)
154
- response.display(a)
155
-
156
- expect(a.string).to eq(b.string)
157
- end
158
- end
159
-
160
- it "allows headers to be accessed by mixed-case names in hash notation" do
161
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
162
- expect(response.headers['Content-LENGTH']).to eq(@content_length)
163
- end
164
-
165
- it "returns a comma-delimited value when multiple values exist" do
166
- @response_object.add_field 'set-cookie', 'csrf_id=12345; path=/'
167
- @response_object.add_field 'set-cookie', '_github_ses=A123CdE; path=/'
168
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
169
- expect(response.headers['set-cookie']).to eq("csrf_id=12345; path=/, _github_ses=A123CdE; path=/")
170
- end
171
-
172
- # Backwards-compatibility - previously, #headers returned a Hash
173
- it "responds to hash methods" do
174
- response = HTTParty::Response.new(@request_object, @response_object, @parsed_response)
175
- hash_methods = {}.methods - response.headers.methods
176
- hash_methods.each do |method_name|
177
- expect(response.headers.respond_to?(method_name)).to be_truthy
178
- end
179
- end
180
-
181
- describe "#is_a?" do
182
- subject { HTTParty::Response.new(@request_object, @response_object, @parsed_response) }
183
-
184
- it { is_expected.to respond_to(:is_a?).with(1).arguments }
185
- it { expect(subject.is_a?(HTTParty::Response)).to be_truthy }
186
- it { expect(subject.is_a?(Object)).to be_truthy }
187
- end
188
-
189
- describe "#kind_of?" do
190
- subject { HTTParty::Response.new(@request_object, @response_object, @parsed_response) }
191
-
192
- it { is_expected.to respond_to(:kind_of?).with(1).arguments }
193
- it { expect(subject.kind_of?(HTTParty::Response)).to be_truthy }
194
- it { expect(subject.kind_of?(Object)).to be_truthy }
195
- end
196
-
197
- describe "semantic methods for response codes" do
198
- def response_mock(klass)
199
- response = klass.new('', '', '')
200
- allow(response).to receive(:body)
201
- response
202
- end
203
-
204
- context "major codes" do
205
- it "is information" do
206
- net_response = response_mock(Net::HTTPInformation)
207
- response = HTTParty::Response.new(@request_object, net_response, '')
208
- expect(response.information?).to be_truthy
209
- end
210
-
211
- it "is success" do
212
- net_response = response_mock(Net::HTTPSuccess)
213
- response = HTTParty::Response.new(@request_object, net_response, '')
214
- expect(response.success?).to be_truthy
215
- end
216
-
217
- it "is redirection" do
218
- net_response = response_mock(Net::HTTPRedirection)
219
- response = HTTParty::Response.new(@request_object, net_response, '')
220
- expect(response.redirection?).to be_truthy
221
- end
222
-
223
- it "is client error" do
224
- net_response = response_mock(Net::HTTPClientError)
225
- response = HTTParty::Response.new(@request_object, net_response, '')
226
- expect(response.client_error?).to be_truthy
227
- end
228
-
229
- it "is server error" do
230
- net_response = response_mock(Net::HTTPServerError)
231
- response = HTTParty::Response.new(@request_object, net_response, '')
232
- expect(response.server_error?).to be_truthy
233
- end
234
- end
235
-
236
- context "for specific codes" do
237
- SPECIFIC_CODES = {
238
- accepted?: Net::HTTPAccepted,
239
- bad_gateway?: Net::HTTPBadGateway,
240
- bad_request?: Net::HTTPBadRequest,
241
- conflict?: Net::HTTPConflict,
242
- continue?: Net::HTTPContinue,
243
- created?: Net::HTTPCreated,
244
- expectation_failed?: Net::HTTPExpectationFailed,
245
- forbidden?: Net::HTTPForbidden,
246
- found?: Net::HTTPFound,
247
- gateway_time_out?: Net::HTTPGatewayTimeOut,
248
- gone?: Net::HTTPGone,
249
- internal_server_error?: Net::HTTPInternalServerError,
250
- length_required?: Net::HTTPLengthRequired,
251
- method_not_allowed?: Net::HTTPMethodNotAllowed,
252
- moved_permanently?: Net::HTTPMovedPermanently,
253
- multiple_choice?: Net::HTTPMultipleChoice,
254
- no_content?: Net::HTTPNoContent,
255
- non_authoritative_information?: Net::HTTPNonAuthoritativeInformation,
256
- not_acceptable?: Net::HTTPNotAcceptable,
257
- not_found?: Net::HTTPNotFound,
258
- not_implemented?: Net::HTTPNotImplemented,
259
- not_modified?: Net::HTTPNotModified,
260
- ok?: Net::HTTPOK,
261
- partial_content?: Net::HTTPPartialContent,
262
- payment_required?: Net::HTTPPaymentRequired,
263
- precondition_failed?: Net::HTTPPreconditionFailed,
264
- proxy_authentication_required?: Net::HTTPProxyAuthenticationRequired,
265
- request_entity_too_large?: Net::HTTPRequestEntityTooLarge,
266
- request_time_out?: Net::HTTPRequestTimeOut,
267
- request_uri_too_long?: Net::HTTPRequestURITooLong,
268
- requested_range_not_satisfiable?: Net::HTTPRequestedRangeNotSatisfiable,
269
- reset_content?: Net::HTTPResetContent,
270
- see_other?: Net::HTTPSeeOther,
271
- service_unavailable?: Net::HTTPServiceUnavailable,
272
- switch_protocol?: Net::HTTPSwitchProtocol,
273
- temporary_redirect?: Net::HTTPTemporaryRedirect,
274
- unauthorized?: Net::HTTPUnauthorized,
275
- unsupported_media_type?: Net::HTTPUnsupportedMediaType,
276
- use_proxy?: Net::HTTPUseProxy,
277
- version_not_supported?: Net::HTTPVersionNotSupported
278
- }
279
-
280
- # Ruby 2.0, new name for this response.
281
- if RUBY_VERSION >= "2.0.0" && ::RUBY_PLATFORM != "java"
282
- SPECIFIC_CODES[:multiple_choices?] = Net::HTTPMultipleChoices
283
- end
284
-
285
- # Ruby 2.6, those status codes have been updated.
286
- if RUBY_VERSION >= "2.6.0" && ::RUBY_PLATFORM != "java"
287
- SPECIFIC_CODES[:gateway_timeout?] = Net::HTTPGatewayTimeout
288
- SPECIFIC_CODES[:payload_too_large?] = Net::HTTPPayloadTooLarge
289
- SPECIFIC_CODES[:request_timeout?] = Net::HTTPRequestTimeout
290
- SPECIFIC_CODES[:uri_too_long?] = Net::HTTPURITooLong
291
- SPECIFIC_CODES[:range_not_satisfiable?] = Net::HTTPRangeNotSatisfiable
292
- end
293
-
294
- SPECIFIC_CODES.each do |method, klass|
295
- it "responds to #{method}" do
296
- net_response = response_mock(klass)
297
- response = HTTParty::Response.new(@request_object, net_response, '')
298
- expect(response.__send__(method)).to be_truthy
299
- end
300
- end
301
- end
302
- end
303
-
304
- describe "headers" do
305
- let (:empty_headers) { HTTParty::Response::Headers.new }
306
- let (:some_headers_hash) do
307
- {'Cookie' => 'bob',
308
- 'Content-Encoding' => 'meow'}
309
- end
310
- let (:some_headers) do
311
- HTTParty::Response::Headers.new.tap do |h|
312
- some_headers_hash.each_pair do |k,v|
313
- h[k] = v
314
- end
315
- end
316
- end
317
- it "can initialize without headers" do
318
- expect(empty_headers).to eq({})
319
- end
320
-
321
- it 'always equals itself' do
322
- expect(empty_headers).to eq(empty_headers)
323
- expect(some_headers).to eq(some_headers)
324
- end
325
-
326
- it 'does not equal itself when not equivalent' do
327
- expect(empty_headers).to_not eq(some_headers)
328
- end
329
-
330
- it 'does equal a hash' do
331
- expect(empty_headers).to eq({})
332
-
333
- expect(some_headers).to eq(some_headers_hash)
334
- end
335
- end
336
-
337
- describe "#tap" do
338
- it "is possible to tap into a response" do
339
- result = @response.tap(&:code)
340
-
341
- expect(result).to eq @response
342
- end
343
- end
344
-
345
- describe "#inspect" do
346
- it "works" do
347
- inspect = @response.inspect
348
- expect(inspect).to include("HTTParty::Response:0x")
349
- expect(inspect).to include("parsed_response={\"foo\"=>\"bar\"}")
350
- expect(inspect).to include("@response=#<Net::HTTPOK 200 OK readbody=false>")
351
- expect(inspect).to include("@headers={")
352
- expect(inspect).to include("last-modified")
353
- expect(inspect).to include("content-length")
354
- end
355
- end
356
-
357
- describe 'marshalling' do
358
- before { RSpec::Mocks.space.proxy_for(@response_object).remove_stub(:body) }
359
-
360
- specify do
361
- marshalled = Marshal.load(Marshal.dump(@response))
362
-
363
- expect(marshalled.headers).to eq @response.headers
364
- expect(marshalled.body).to eq @response.body
365
- expect(marshalled.code).to eq @response.code
366
- end
367
- end
368
- end
@@ -1,74 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe HTTParty::Request do
4
- context "SSL certificate verification" do
5
- before do
6
- WebMock.allow_net_connect!
7
- end
8
-
9
- after do
10
- WebMock.disable_net_connect!
11
- end
12
-
13
- it "should fail when no trusted CA list is specified, by default" do
14
- expect do
15
- ssl_verify_test(nil, nil, "selfsigned.crt")
16
- end.to raise_error OpenSSL::SSL::SSLError
17
- end
18
-
19
- it "should work when no trusted CA list is specified, when the verify option is set to false" do
20
- expect(ssl_verify_test(nil, nil, "selfsigned.crt", verify: false).parsed_response).to eq({'success' => true})
21
- end
22
-
23
- it "should fail when no trusted CA list is specified, with a bogus hostname, by default" do
24
- expect do
25
- ssl_verify_test(nil, nil, "bogushost.crt")
26
- end.to raise_error OpenSSL::SSL::SSLError
27
- end
28
-
29
- it "should work when no trusted CA list is specified, even with a bogus hostname, when the verify option is set to true" do
30
- expect(ssl_verify_test(nil, nil, "bogushost.crt", verify: false).parsed_response).to eq({'success' => true})
31
- end
32
-
33
- it "should work when using ssl_ca_file with a self-signed CA" do
34
- expect(ssl_verify_test(:ssl_ca_file, "selfsigned.crt", "selfsigned.crt").parsed_response).to eq({'success' => true})
35
- end
36
-
37
- it "should work when using ssl_ca_file with a certificate authority" do
38
- expect(ssl_verify_test(:ssl_ca_file, "ca.crt", "server.crt").parsed_response).to eq({'success' => true})
39
- end
40
-
41
- it "should work when using ssl_ca_path with a certificate authority" do
42
- http = Net::HTTP.new('www.google.com', 443)
43
- response = double(Net::HTTPResponse, :[] => '', body: '', to_hash: {})
44
- allow(http).to receive(:request).and_return(response)
45
- expect(Net::HTTP).to receive(:new).with('www.google.com', 443).and_return(http)
46
- expect(http).to receive(:ca_path=).with('/foo/bar')
47
- HTTParty.get('https://www.google.com', ssl_ca_path: '/foo/bar')
48
- end
49
-
50
- it "should fail when using ssl_ca_file and the server uses an unrecognized certificate authority" do
51
- expect do
52
- ssl_verify_test(:ssl_ca_file, "ca.crt", "selfsigned.crt")
53
- end.to raise_error(OpenSSL::SSL::SSLError)
54
- end
55
-
56
- it "should fail when using ssl_ca_path and the server uses an unrecognized certificate authority" do
57
- expect do
58
- ssl_verify_test(:ssl_ca_path, ".", "selfsigned.crt")
59
- end.to raise_error(OpenSSL::SSL::SSLError)
60
- end
61
-
62
- it "should fail when using ssl_ca_file and the server uses a bogus hostname" do
63
- expect do
64
- ssl_verify_test(:ssl_ca_file, "ca.crt", "bogushost.crt")
65
- end.to raise_error(OpenSSL::SSL::SSLError)
66
- end
67
-
68
- it "should fail when using ssl_ca_path and the server uses a bogus hostname" do
69
- expect do
70
- ssl_verify_test(:ssl_ca_path, ".", "bogushost.crt")
71
- end.to raise_error(OpenSSL::SSL::SSLError)
72
- end
73
- end
74
- end