httparty 0.16.2 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +18 -0
  3. data/.github/workflows/ci.yml +26 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop_todo.yml +1 -1
  6. data/Changelog.md +78 -0
  7. data/Gemfile +7 -0
  8. data/Guardfile +3 -2
  9. data/README.md +5 -5
  10. data/docs/README.md +90 -5
  11. data/examples/README.md +28 -11
  12. data/examples/aaws.rb +6 -2
  13. data/examples/body_stream.rb +14 -0
  14. data/examples/idn.rb +10 -0
  15. data/examples/microsoft_graph.rb +52 -0
  16. data/examples/multipart.rb +22 -0
  17. data/examples/peer_cert.rb +9 -0
  18. data/examples/stream_download.rb +8 -2
  19. data/httparty.gemspec +3 -3
  20. data/lib/httparty/connection_adapter.rb +59 -16
  21. data/lib/httparty/cookie_hash.rb +10 -8
  22. data/lib/httparty/decompressor.rb +102 -0
  23. data/lib/httparty/exceptions.rb +3 -1
  24. data/lib/httparty/hash_conversions.rb +10 -4
  25. data/lib/httparty/headers_processor.rb +32 -0
  26. data/lib/httparty/logger/apache_formatter.rb +31 -6
  27. data/lib/httparty/logger/curl_formatter.rb +9 -7
  28. data/lib/httparty/logger/logger.rb +5 -1
  29. data/lib/httparty/logger/logstash_formatter.rb +61 -0
  30. data/lib/httparty/module_inheritable_attributes.rb +6 -4
  31. data/lib/httparty/net_digest_auth.rb +15 -15
  32. data/lib/httparty/parser.rb +9 -5
  33. data/lib/httparty/request/body.rb +53 -27
  34. data/lib/httparty/request/multipart_boundary.rb +2 -0
  35. data/lib/httparty/request.rb +79 -96
  36. data/lib/httparty/response/headers.rb +4 -2
  37. data/lib/httparty/response.rb +51 -8
  38. data/lib/httparty/response_fragment.rb +21 -0
  39. data/lib/httparty/text_encoder.rb +72 -0
  40. data/lib/httparty/utils.rb +13 -0
  41. data/lib/httparty/version.rb +3 -1
  42. data/lib/httparty.rb +70 -25
  43. data/website/css/common.css +1 -1
  44. metadata +35 -107
  45. data/.simplecov +0 -1
  46. data/.travis.yml +0 -10
  47. data/features/basic_authentication.feature +0 -20
  48. data/features/command_line.feature +0 -95
  49. data/features/deals_with_http_error_codes.feature +0 -26
  50. data/features/digest_authentication.feature +0 -30
  51. data/features/handles_compressed_responses.feature +0 -27
  52. data/features/handles_multiple_formats.feature +0 -57
  53. data/features/steps/env.rb +0 -27
  54. data/features/steps/httparty_response_steps.rb +0 -56
  55. data/features/steps/httparty_steps.rb +0 -43
  56. data/features/steps/mongrel_helper.rb +0 -127
  57. data/features/steps/remote_service_steps.rb +0 -92
  58. data/features/supports_read_timeout_option.feature +0 -13
  59. data/features/supports_redirection.feature +0 -22
  60. data/features/supports_timeout_option.feature +0 -13
  61. data/spec/fixtures/delicious.xml +0 -23
  62. data/spec/fixtures/empty.xml +0 -0
  63. data/spec/fixtures/google.html +0 -3
  64. data/spec/fixtures/ssl/generate.sh +0 -29
  65. data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
  66. data/spec/fixtures/ssl/generated/ca.crt +0 -16
  67. data/spec/fixtures/ssl/generated/ca.key +0 -15
  68. data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
  69. data/spec/fixtures/ssl/generated/server.crt +0 -13
  70. data/spec/fixtures/ssl/generated/server.key +0 -15
  71. data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
  72. data/spec/fixtures/tiny.gif +0 -0
  73. data/spec/fixtures/twitter.csv +0 -2
  74. data/spec/fixtures/twitter.json +0 -1
  75. data/spec/fixtures/twitter.xml +0 -403
  76. data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
  77. data/spec/httparty/connection_adapter_spec.rb +0 -498
  78. data/spec/httparty/cookie_hash_spec.rb +0 -100
  79. data/spec/httparty/exception_spec.rb +0 -45
  80. data/spec/httparty/hash_conversions_spec.rb +0 -56
  81. data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
  82. data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
  83. data/spec/httparty/logger/logger_spec.rb +0 -38
  84. data/spec/httparty/net_digest_auth_spec.rb +0 -270
  85. data/spec/httparty/parser_spec.rb +0 -190
  86. data/spec/httparty/request/body_spec.rb +0 -60
  87. data/spec/httparty/request_spec.rb +0 -1312
  88. data/spec/httparty/response_spec.rb +0 -347
  89. data/spec/httparty/ssl_spec.rb +0 -74
  90. data/spec/httparty_spec.rb +0 -896
  91. data/spec/spec_helper.rb +0 -51
  92. data/spec/support/ssl_test_helper.rb +0 -47
  93. data/spec/support/ssl_test_server.rb +0 -80
  94. data/spec/support/stub_response.rb +0 -49
@@ -1,347 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '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
- SPECIFIC_CODES.each do |method, klass|
286
- it "responds to #{method}" do
287
- net_response = response_mock(klass)
288
- response = HTTParty::Response.new(@request_object, net_response, '')
289
- expect(response.__send__(method)).to be_truthy
290
- end
291
- end
292
- end
293
- end
294
-
295
- describe "headers" do
296
- let (:empty_headers) { HTTParty::Response::Headers.new }
297
- let (:some_headers_hash) do
298
- {'Cookie' => 'bob',
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
306
- end
307
- end
308
- it "can initialize without headers" do
309
- expect(empty_headers).to eq({})
310
- end
311
-
312
- it 'always equals itself' do
313
- expect(empty_headers).to eq(empty_headers)
314
- expect(some_headers).to eq(some_headers)
315
- end
316
-
317
- it 'does not equal itself when not equivalent' do
318
- expect(empty_headers).to_not eq(some_headers)
319
- end
320
-
321
- it 'does equal a hash' do
322
- expect(empty_headers).to eq({})
323
-
324
- expect(some_headers).to eq(some_headers_hash)
325
- end
326
- end
327
-
328
- describe "#tap" do
329
- it "is possible to tap into a response" do
330
- result = @response.tap(&:code)
331
-
332
- expect(result).to eq @response
333
- end
334
- end
335
-
336
- describe "#inspect" do
337
- it "works" do
338
- inspect = @response.inspect
339
- expect(inspect).to include("HTTParty::Response:0x")
340
- expect(inspect).to include("parsed_response={\"foo\"=>\"bar\"}")
341
- expect(inspect).to include("@response=#<Net::HTTPOK 200 OK readbody=false>")
342
- expect(inspect).to include("@headers={")
343
- expect(inspect).to include("last-modified")
344
- expect(inspect).to include("content-length")
345
- end
346
- end
347
- end
@@ -1,74 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), '..', '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