httparty 0.16.2 → 0.22.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.editorconfig +18 -0
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/ci.yml +23 -0
- data/.gitignore +2 -0
- data/.rubocop_todo.yml +1 -1
- data/Changelog.md +425 -280
- data/Gemfile +7 -0
- data/Guardfile +3 -2
- data/README.md +5 -5
- data/docs/README.md +90 -5
- data/examples/README.md +28 -11
- data/examples/aaws.rb +6 -2
- data/examples/body_stream.rb +14 -0
- data/examples/idn.rb +10 -0
- data/examples/microsoft_graph.rb +52 -0
- data/examples/multipart.rb +22 -0
- data/examples/peer_cert.rb +9 -0
- data/examples/stream_download.rb +8 -2
- data/httparty.gemspec +4 -3
- data/lib/httparty/connection_adapter.rb +44 -20
- data/lib/httparty/cookie_hash.rb +10 -8
- data/lib/httparty/decompressor.rb +102 -0
- data/lib/httparty/exceptions.rb +3 -1
- data/lib/httparty/hash_conversions.rb +10 -4
- data/lib/httparty/headers_processor.rb +32 -0
- data/lib/httparty/logger/apache_formatter.rb +31 -6
- data/lib/httparty/logger/curl_formatter.rb +9 -7
- data/lib/httparty/logger/logger.rb +5 -1
- data/lib/httparty/logger/logstash_formatter.rb +62 -0
- data/lib/httparty/module_inheritable_attributes.rb +9 -9
- data/lib/httparty/net_digest_auth.rb +15 -15
- data/lib/httparty/parser.rb +12 -5
- data/lib/httparty/request/body.rb +54 -27
- data/lib/httparty/request/multipart_boundary.rb +2 -0
- data/lib/httparty/request.rb +105 -107
- data/lib/httparty/response/headers.rb +4 -2
- data/lib/httparty/response.rb +52 -9
- data/lib/httparty/response_fragment.rb +21 -0
- data/lib/httparty/text_encoder.rb +72 -0
- data/lib/httparty/utils.rb +13 -0
- data/lib/httparty/version.rb +3 -1
- data/lib/httparty.rb +81 -33
- data/script/release +4 -4
- data/website/css/common.css +1 -1
- metadata +50 -107
- data/.simplecov +0 -1
- data/.travis.yml +0 -10
- data/features/basic_authentication.feature +0 -20
- data/features/command_line.feature +0 -95
- data/features/deals_with_http_error_codes.feature +0 -26
- data/features/digest_authentication.feature +0 -30
- data/features/handles_compressed_responses.feature +0 -27
- data/features/handles_multiple_formats.feature +0 -57
- data/features/steps/env.rb +0 -27
- data/features/steps/httparty_response_steps.rb +0 -56
- data/features/steps/httparty_steps.rb +0 -43
- data/features/steps/mongrel_helper.rb +0 -127
- data/features/steps/remote_service_steps.rb +0 -92
- data/features/supports_read_timeout_option.feature +0 -13
- data/features/supports_redirection.feature +0 -22
- data/features/supports_timeout_option.feature +0 -13
- data/spec/fixtures/delicious.xml +0 -23
- data/spec/fixtures/empty.xml +0 -0
- data/spec/fixtures/google.html +0 -3
- data/spec/fixtures/ssl/generate.sh +0 -29
- data/spec/fixtures/ssl/generated/bogushost.crt +0 -13
- data/spec/fixtures/ssl/generated/ca.crt +0 -16
- data/spec/fixtures/ssl/generated/ca.key +0 -15
- data/spec/fixtures/ssl/generated/selfsigned.crt +0 -14
- data/spec/fixtures/ssl/generated/server.crt +0 -13
- data/spec/fixtures/ssl/generated/server.key +0 -15
- data/spec/fixtures/ssl/openssl-exts.cnf +0 -9
- data/spec/fixtures/tiny.gif +0 -0
- data/spec/fixtures/twitter.csv +0 -2
- data/spec/fixtures/twitter.json +0 -1
- data/spec/fixtures/twitter.xml +0 -403
- data/spec/fixtures/undefined_method_add_node_for_nil.xml +0 -2
- data/spec/httparty/connection_adapter_spec.rb +0 -498
- data/spec/httparty/cookie_hash_spec.rb +0 -100
- data/spec/httparty/exception_spec.rb +0 -45
- data/spec/httparty/hash_conversions_spec.rb +0 -56
- data/spec/httparty/logger/apache_formatter_spec.rb +0 -41
- data/spec/httparty/logger/curl_formatter_spec.rb +0 -119
- data/spec/httparty/logger/logger_spec.rb +0 -38
- data/spec/httparty/net_digest_auth_spec.rb +0 -270
- data/spec/httparty/parser_spec.rb +0 -190
- data/spec/httparty/request/body_spec.rb +0 -60
- data/spec/httparty/request_spec.rb +0 -1312
- data/spec/httparty/response_spec.rb +0 -347
- data/spec/httparty/ssl_spec.rb +0 -74
- data/spec/httparty_spec.rb +0 -896
- data/spec/spec_helper.rb +0 -51
- data/spec/support/ssl_test_helper.rb +0 -47
- data/spec/support/ssl_test_server.rb +0 -80
- data/spec/support/stub_response.rb +0 -49
data/lib/httparty/request.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'erb'
|
2
|
-
require 'httparty/request/body'
|
3
4
|
|
4
5
|
module HTTParty
|
5
6
|
class Request #:nodoc:
|
@@ -14,6 +15,8 @@ module HTTParty
|
|
14
15
|
Net::HTTP::Move,
|
15
16
|
Net::HTTP::Copy,
|
16
17
|
Net::HTTP::Mkcol,
|
18
|
+
Net::HTTP::Lock,
|
19
|
+
Net::HTTP::Unlock,
|
17
20
|
]
|
18
21
|
|
19
22
|
SupportedURISchemes = ['http', 'https', 'webcal', nil]
|
@@ -43,6 +46,15 @@ module HTTParty
|
|
43
46
|
end.flatten.join('&')
|
44
47
|
end
|
45
48
|
|
49
|
+
def self._load(data)
|
50
|
+
http_method, path, options, last_response, last_uri, raw_request = Marshal.load(data)
|
51
|
+
instance = new(http_method, path, options)
|
52
|
+
instance.last_response = last_response
|
53
|
+
instance.last_uri = last_uri
|
54
|
+
instance.instance_variable_set("@raw_request", raw_request)
|
55
|
+
instance
|
56
|
+
end
|
57
|
+
|
46
58
|
attr_accessor :http_method, :options, :last_response, :redirect, :last_uri
|
47
59
|
attr_reader :path
|
48
60
|
|
@@ -70,7 +82,7 @@ module HTTParty
|
|
70
82
|
@path = if uri.is_a?(uri_adapter)
|
71
83
|
uri
|
72
84
|
elsif String.try_convert(uri)
|
73
|
-
uri_adapter.parse
|
85
|
+
uri_adapter.parse(uri).normalize
|
74
86
|
else
|
75
87
|
raise ArgumentError,
|
76
88
|
"bad argument (expected #{uri_adapter} object or URI string)"
|
@@ -86,17 +98,17 @@ module HTTParty
|
|
86
98
|
end
|
87
99
|
|
88
100
|
def uri
|
89
|
-
if redirect && path.relative? && path.path[0] !=
|
90
|
-
last_uri_host = @last_uri.path.gsub(/[^\/]+$/,
|
101
|
+
if redirect && path.relative? && path.path[0] != '/'
|
102
|
+
last_uri_host = @last_uri.path.gsub(/[^\/]+$/, '')
|
91
103
|
|
92
|
-
path.path = "/#{path.path}" if last_uri_host[-1] !=
|
93
|
-
path.path = last_uri_host
|
104
|
+
path.path = "/#{path.path}" if last_uri_host[-1] != '/'
|
105
|
+
path.path = "#{last_uri_host}#{path.path}"
|
94
106
|
end
|
95
107
|
|
96
108
|
if path.relative? && path.host
|
97
|
-
new_uri = options[:uri_adapter].parse("#{@last_uri.scheme}:#{path}")
|
109
|
+
new_uri = options[:uri_adapter].parse("#{@last_uri.scheme}:#{path}").normalize
|
98
110
|
elsif path.relative?
|
99
|
-
new_uri = options[:uri_adapter].parse("#{base_uri}#{path}")
|
111
|
+
new_uri = options[:uri_adapter].parse("#{base_uri}#{path}").normalize
|
100
112
|
else
|
101
113
|
new_uri = path.clone
|
102
114
|
end
|
@@ -116,7 +128,7 @@ module HTTParty
|
|
116
128
|
def base_uri
|
117
129
|
if redirect
|
118
130
|
base_uri = "#{@last_uri.scheme}://#{@last_uri.host}"
|
119
|
-
base_uri
|
131
|
+
base_uri = "#{base_uri}:#{@last_uri.port}" if @last_uri.port != 80
|
120
132
|
base_uri
|
121
133
|
else
|
122
134
|
options[:base_uri] && HTTParty.normalize_base_uri(options[:base_uri])
|
@@ -139,21 +151,22 @@ module HTTParty
|
|
139
151
|
validate
|
140
152
|
setup_raw_request
|
141
153
|
chunked_body = nil
|
154
|
+
current_http = http
|
142
155
|
|
143
|
-
self.last_response =
|
156
|
+
self.last_response = current_http.request(@raw_request) do |http_response|
|
144
157
|
if block
|
145
158
|
chunks = []
|
146
159
|
|
147
160
|
http_response.read_body do |fragment|
|
148
|
-
|
149
|
-
|
161
|
+
encoded_fragment = encode_text(fragment, http_response['content-type'])
|
162
|
+
chunks << encoded_fragment if !options[:stream_body]
|
163
|
+
block.call ResponseFragment.new(encoded_fragment, http_response, current_http)
|
150
164
|
end
|
151
165
|
|
152
166
|
chunked_body = chunks.join
|
153
167
|
end
|
154
168
|
end
|
155
169
|
|
156
|
-
|
157
170
|
handle_host_redirection if response_redirects?
|
158
171
|
result = handle_unauthorized
|
159
172
|
result ||= handle_response(chunked_body, &block)
|
@@ -171,6 +184,13 @@ module HTTParty
|
|
171
184
|
@raw_request.body
|
172
185
|
end
|
173
186
|
|
187
|
+
def _dump(_level)
|
188
|
+
opts = options.dup
|
189
|
+
opts.delete(:logger)
|
190
|
+
opts.delete(:parser) if opts[:parser] && opts[:parser].is_a?(Proc)
|
191
|
+
Marshal.dump([http_method, path, opts, last_response, @last_uri, @raw_request])
|
192
|
+
end
|
193
|
+
|
174
194
|
private
|
175
195
|
|
176
196
|
def http
|
@@ -202,24 +222,22 @@ module HTTParty
|
|
202
222
|
end
|
203
223
|
|
204
224
|
def setup_raw_request
|
205
|
-
@raw_request = http_method.new(request_uri(uri))
|
206
|
-
@raw_request.body_stream = options[:body_stream] if options[:body_stream]
|
207
|
-
|
208
225
|
if options[:headers].respond_to?(:to_hash)
|
209
226
|
headers_hash = options[:headers].to_hash
|
210
|
-
|
211
|
-
|
212
|
-
# If the caller specified a header of 'Accept-Encoding', assume they want to
|
213
|
-
# deal with encoding of content. Disable the internal logic in Net:HTTP
|
214
|
-
# that handles encoding, if the platform supports it.
|
215
|
-
if @raw_request.respond_to?(:decode_content) && (headers_hash.key?('Accept-Encoding') || headers_hash.key?('accept-encoding'))
|
216
|
-
# Using the '[]=' sets decode_content to false
|
217
|
-
@raw_request['accept-encoding'] = @raw_request['accept-encoding']
|
218
|
-
end
|
227
|
+
else
|
228
|
+
headers_hash = nil
|
219
229
|
end
|
220
230
|
|
231
|
+
@raw_request = http_method.new(request_uri(uri), headers_hash)
|
232
|
+
@raw_request.body_stream = options[:body_stream] if options[:body_stream]
|
233
|
+
|
221
234
|
if options[:body]
|
222
|
-
body = Body.new(
|
235
|
+
body = Body.new(
|
236
|
+
options[:body],
|
237
|
+
query_string_normalizer: query_string_normalizer,
|
238
|
+
force_multipart: options[:multipart]
|
239
|
+
)
|
240
|
+
|
223
241
|
if body.multipart?
|
224
242
|
content_type = "multipart/form-data; boundary=#{body.boundary}"
|
225
243
|
@raw_request['Content-Type'] = content_type
|
@@ -227,6 +245,8 @@ module HTTParty
|
|
227
245
|
@raw_request.body = body.call
|
228
246
|
end
|
229
247
|
|
248
|
+
@raw_request.instance_variable_set(:@decode_content, decompress_content?)
|
249
|
+
|
230
250
|
if options[:basic_auth] && send_authorization_header?
|
231
251
|
@raw_request.basic_auth(username, password)
|
232
252
|
@credentials_sent = true
|
@@ -238,6 +258,10 @@ module HTTParty
|
|
238
258
|
!!options[:digest_auth]
|
239
259
|
end
|
240
260
|
|
261
|
+
def decompress_content?
|
262
|
+
!options[:skip_decompression]
|
263
|
+
end
|
264
|
+
|
241
265
|
def response_unauthorized?
|
242
266
|
!!last_response && last_response.code == '401'
|
243
267
|
end
|
@@ -261,109 +285,63 @@ module HTTParty
|
|
261
285
|
query_string_parts << options[:query] unless options[:query].nil?
|
262
286
|
end
|
263
287
|
|
264
|
-
query_string_parts.reject!(&:empty?) unless query_string_parts == [
|
288
|
+
query_string_parts.reject!(&:empty?) unless query_string_parts == ['']
|
265
289
|
query_string_parts.size > 0 ? query_string_parts.join('&') : nil
|
266
290
|
end
|
267
291
|
|
268
|
-
def get_charset
|
269
|
-
content_type = last_response["content-type"]
|
270
|
-
if content_type.nil?
|
271
|
-
return nil
|
272
|
-
end
|
273
|
-
|
274
|
-
if content_type =~ /;\s*charset\s*=\s*([^=,;"\s]+)/i
|
275
|
-
return $1
|
276
|
-
end
|
277
|
-
|
278
|
-
if content_type =~ /;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i
|
279
|
-
return $1.gsub(/\\(.)/, '\1')
|
280
|
-
end
|
281
|
-
|
282
|
-
nil
|
283
|
-
end
|
284
|
-
|
285
|
-
def encode_with_ruby_encoding(body, charset)
|
286
|
-
# NOTE: This will raise an argument error if the
|
287
|
-
# charset does not exist
|
288
|
-
encoding = Encoding.find(charset)
|
289
|
-
body.force_encoding(encoding.to_s)
|
290
|
-
rescue ArgumentError
|
291
|
-
body
|
292
|
-
end
|
293
|
-
|
294
292
|
def assume_utf16_is_big_endian
|
295
293
|
options[:assume_utf16_is_big_endian]
|
296
294
|
end
|
297
295
|
|
298
|
-
def
|
299
|
-
if
|
300
|
-
|
301
|
-
return body.force_encoding("UTF-16LE")
|
302
|
-
elsif body.getbyte(0) == 0xFE && body.getbyte(1) == 0xFF
|
303
|
-
return body.force_encoding("UTF-16BE")
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
if assume_utf16_is_big_endian
|
308
|
-
body.force_encoding("UTF-16BE")
|
296
|
+
def handle_response(raw_body, &block)
|
297
|
+
if response_redirects?
|
298
|
+
handle_redirection(&block)
|
309
299
|
else
|
310
|
-
body
|
311
|
-
end
|
312
|
-
end
|
300
|
+
raw_body ||= last_response.body
|
313
301
|
|
314
|
-
|
315
|
-
charset = get_charset
|
302
|
+
body = decompress(raw_body, last_response['content-encoding']) unless raw_body.nil?
|
316
303
|
|
317
|
-
|
318
|
-
|
319
|
-
end
|
304
|
+
unless body.nil?
|
305
|
+
body = encode_text(body, last_response['content-type'])
|
320
306
|
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
end
|
307
|
+
if decompress_content?
|
308
|
+
last_response.delete('content-encoding')
|
309
|
+
raw_body = body
|
310
|
+
end
|
311
|
+
end
|
327
312
|
|
328
|
-
|
329
|
-
if "".respond_to?(:encoding)
|
330
|
-
_encode_body(body)
|
331
|
-
else
|
332
|
-
body
|
313
|
+
Response.new(self, last_response, lambda { parse_response(body) }, body: raw_body)
|
333
314
|
end
|
334
315
|
end
|
335
316
|
|
336
|
-
def
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
317
|
+
def handle_redirection(&block)
|
318
|
+
options[:limit] -= 1
|
319
|
+
if options[:logger]
|
320
|
+
logger = HTTParty::Logger.build(options[:logger], options[:log_level], options[:log_format])
|
321
|
+
logger.format(self, last_response)
|
322
|
+
end
|
323
|
+
self.path = last_response['location']
|
324
|
+
self.redirect = true
|
325
|
+
if last_response.class == Net::HTTPSeeOther
|
326
|
+
unless options[:maintain_method_across_redirects] && options[:resend_on_redirect]
|
327
|
+
self.http_method = Net::HTTP::Get
|
342
328
|
end
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
unless options[:maintain_method_across_redirects] && options[:resend_on_redirect]
|
347
|
-
self.http_method = Net::HTTP::Get
|
348
|
-
end
|
349
|
-
elsif last_response.code != '307' && last_response.code != '308'
|
350
|
-
unless options[:maintain_method_across_redirects]
|
351
|
-
self.http_method = Net::HTTP::Get
|
352
|
-
end
|
329
|
+
elsif last_response.code != '307' && last_response.code != '308'
|
330
|
+
unless options[:maintain_method_across_redirects]
|
331
|
+
self.http_method = Net::HTTP::Get
|
353
332
|
end
|
354
|
-
capture_cookies(last_response)
|
355
|
-
perform(&block)
|
356
|
-
else
|
357
|
-
body ||= last_response.body
|
358
|
-
body = body.nil? ? body : encode_body(body)
|
359
|
-
Response.new(self, last_response, lambda { parse_response(body) }, body: body)
|
360
333
|
end
|
334
|
+
if http_method == Net::HTTP::Get
|
335
|
+
clear_body
|
336
|
+
end
|
337
|
+
capture_cookies(last_response)
|
338
|
+
perform(&block)
|
361
339
|
end
|
362
340
|
|
363
341
|
def handle_host_redirection
|
364
342
|
check_duplicate_location_header
|
365
|
-
redirect_path = options[:uri_adapter].parse
|
366
|
-
return if redirect_path.relative? || path.host == redirect_path.host
|
343
|
+
redirect_path = options[:uri_adapter].parse(last_response['location']).normalize
|
344
|
+
return if redirect_path.relative? || path.host == redirect_path.host || uri.host == redirect_path.host
|
367
345
|
@changed_hosts = true
|
368
346
|
end
|
369
347
|
|
@@ -391,6 +369,14 @@ module HTTParty
|
|
391
369
|
parser.call(body, format)
|
392
370
|
end
|
393
371
|
|
372
|
+
# Some Web Application Firewalls reject incoming GET requests that have a body
|
373
|
+
# if we redirect, and the resulting verb is GET then we will clear the body that
|
374
|
+
# may be left behind from the initiating request
|
375
|
+
def clear_body
|
376
|
+
options[:body] = nil
|
377
|
+
@raw_request.body = nil
|
378
|
+
end
|
379
|
+
|
394
380
|
def capture_cookies(response)
|
395
381
|
return unless response['Set-Cookie']
|
396
382
|
cookies_hash = HTTParty::CookieHash.new
|
@@ -431,5 +417,17 @@ module HTTParty
|
|
431
417
|
@credentials_sent = true
|
432
418
|
end
|
433
419
|
end
|
420
|
+
|
421
|
+
def decompress(body, encoding)
|
422
|
+
Decompressor.new(body, encoding).decompress
|
423
|
+
end
|
424
|
+
|
425
|
+
def encode_text(text, content_type)
|
426
|
+
TextEncoder.new(
|
427
|
+
text,
|
428
|
+
content_type: content_type,
|
429
|
+
assume_utf16_is_big_endian: assume_utf16_is_big_endian
|
430
|
+
).call
|
431
|
+
end
|
434
432
|
end
|
435
433
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'delegate'
|
2
4
|
|
3
5
|
module HTTParty
|
@@ -22,10 +24,10 @@ module HTTParty
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def ==(other)
|
25
|
-
if other.is_a?(::Net::HTTPHeader)
|
27
|
+
if other.is_a?(::Net::HTTPHeader)
|
26
28
|
@header == other.instance_variable_get(:@header)
|
27
29
|
elsif other.is_a?(Hash)
|
28
|
-
@header == other || @header == Headers.new(other).instance_variable_get(:@header)
|
30
|
+
@header == other || @header == Headers.new(other).instance_variable_get(:@header)
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
data/lib/httparty/response.rb
CHANGED
@@ -1,9 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module HTTParty
|
2
4
|
class Response < Object
|
3
5
|
def self.underscore(string)
|
4
6
|
string.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').gsub(/([a-z])([A-Z])/, '\1_\2').downcase
|
5
7
|
end
|
6
8
|
|
9
|
+
def self._load(data)
|
10
|
+
req, resp, parsed_resp, resp_body = Marshal.load(data)
|
11
|
+
|
12
|
+
new(req, resp, -> { parsed_resp }, body: resp_body)
|
13
|
+
end
|
14
|
+
|
7
15
|
attr_reader :request, :response, :body, :headers
|
8
16
|
|
9
17
|
def initialize(request, response, parsed_block, options = {})
|
@@ -14,7 +22,11 @@ module HTTParty
|
|
14
22
|
@headers = Headers.new(response.to_hash)
|
15
23
|
|
16
24
|
if request.options[:logger]
|
17
|
-
logger = ::HTTParty::Logger.build(
|
25
|
+
logger = ::HTTParty::Logger.build(
|
26
|
+
request.options[:logger],
|
27
|
+
request.options[:log_level],
|
28
|
+
request.options[:log_format]
|
29
|
+
)
|
18
30
|
logger.format(request, self)
|
19
31
|
end
|
20
32
|
|
@@ -29,20 +41,24 @@ module HTTParty
|
|
29
41
|
response.code.to_i
|
30
42
|
end
|
31
43
|
|
44
|
+
def http_version
|
45
|
+
response.http_version
|
46
|
+
end
|
47
|
+
|
32
48
|
def tap
|
33
49
|
yield self
|
34
50
|
self
|
35
51
|
end
|
36
52
|
|
37
53
|
def inspect
|
38
|
-
inspect_id = ::Kernel::format
|
54
|
+
inspect_id = ::Kernel::format '%x', (object_id * 2)
|
39
55
|
%(#<#{self.class}:0x#{inspect_id} parsed_response=#{parsed_response.inspect}, @response=#{response.inspect}, @headers=#{headers.inspect}>)
|
40
56
|
end
|
41
57
|
|
42
58
|
CODES_TO_OBJ = ::Net::HTTPResponse::CODE_CLASS_TO_OBJ.merge ::Net::HTTPResponse::CODE_TO_OBJ
|
43
59
|
|
44
60
|
CODES_TO_OBJ.each do |response_code, klass|
|
45
|
-
name = klass.name.sub(
|
61
|
+
name = klass.name.sub('Net::HTTP', '')
|
46
62
|
name = "#{underscore(name)}?".to_sym
|
47
63
|
|
48
64
|
define_method(name) do
|
@@ -51,18 +67,28 @@ module HTTParty
|
|
51
67
|
end
|
52
68
|
|
53
69
|
# Support old multiple_choice? method from pre 2.0.0 era.
|
54
|
-
if ::
|
70
|
+
if ::RUBY_PLATFORM != 'java'
|
55
71
|
alias_method :multiple_choice?, :multiple_choices?
|
56
72
|
end
|
57
73
|
|
74
|
+
# Support old status codes method from pre 2.6.0 era.
|
75
|
+
if ::RUBY_PLATFORM != 'java'
|
76
|
+
alias_method :gateway_time_out?, :gateway_timeout?
|
77
|
+
alias_method :request_entity_too_large?, :payload_too_large?
|
78
|
+
alias_method :request_time_out?, :request_timeout?
|
79
|
+
alias_method :request_uri_too_long?, :uri_too_long?
|
80
|
+
alias_method :requested_range_not_satisfiable?, :range_not_satisfiable?
|
81
|
+
end
|
82
|
+
|
58
83
|
def nil?
|
84
|
+
warn_about_nil_deprecation
|
59
85
|
response.nil? || response.body.nil? || response.body.empty?
|
60
86
|
end
|
61
87
|
|
62
|
-
def to_s
|
88
|
+
def to_s
|
63
89
|
if !response.nil? && !response.body.nil? && response.body.respond_to?(:to_s)
|
64
90
|
response.body.to_s
|
65
|
-
else
|
91
|
+
else
|
66
92
|
inspect
|
67
93
|
end
|
68
94
|
end
|
@@ -80,7 +106,7 @@ module HTTParty
|
|
80
106
|
parsed_response.display(port)
|
81
107
|
elsif !response.nil? && !response.body.nil? && response.body.respond_to?(:display)
|
82
108
|
response.body.display(port)
|
83
|
-
else
|
109
|
+
else
|
84
110
|
port.write(inspect)
|
85
111
|
end
|
86
112
|
end
|
@@ -89,7 +115,11 @@ module HTTParty
|
|
89
115
|
return true if super
|
90
116
|
parsed_response.respond_to?(name) || response.respond_to?(name)
|
91
117
|
end
|
92
|
-
|
118
|
+
|
119
|
+
def _dump(_level)
|
120
|
+
Marshal.dump([request, response, parsed_response, body])
|
121
|
+
end
|
122
|
+
|
93
123
|
protected
|
94
124
|
|
95
125
|
def method_missing(name, *args, &block)
|
@@ -103,10 +133,23 @@ module HTTParty
|
|
103
133
|
end
|
104
134
|
|
105
135
|
def throw_exception
|
106
|
-
if @request.options[:raise_on]
|
136
|
+
if @request.options[:raise_on].to_a.detect { |c| code.to_s.match(/#{c.to_s}/) }
|
107
137
|
::Kernel.raise ::HTTParty::ResponseError.new(@response), "Code #{code} - #{body}"
|
108
138
|
end
|
109
139
|
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def warn_about_nil_deprecation
|
144
|
+
trace_line = caller.reject { |line| line.include?('httparty') }.first
|
145
|
+
warning = "[DEPRECATION] HTTParty will no longer override `response#nil?`. " \
|
146
|
+
"This functionality will be removed in future versions. " \
|
147
|
+
"Please, add explicit check `response.body.nil? || response.body.empty?`. " \
|
148
|
+
"For more info refer to: https://github.com/jnunemaker/httparty/issues/568\n" \
|
149
|
+
"#{trace_line}"
|
150
|
+
|
151
|
+
warn(warning)
|
152
|
+
end
|
110
153
|
end
|
111
154
|
end
|
112
155
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'delegate'
|
4
|
+
|
5
|
+
module HTTParty
|
6
|
+
# Allow access to http_response and code by delegation on fragment
|
7
|
+
class ResponseFragment < SimpleDelegator
|
8
|
+
attr_reader :http_response, :connection
|
9
|
+
|
10
|
+
def code
|
11
|
+
@http_response.code.to_i
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(fragment, http_response, connection)
|
15
|
+
@fragment = fragment
|
16
|
+
@http_response = http_response
|
17
|
+
@connection = connection
|
18
|
+
super fragment
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTParty
|
4
|
+
class TextEncoder
|
5
|
+
attr_reader :text, :content_type, :assume_utf16_is_big_endian
|
6
|
+
|
7
|
+
def initialize(text, assume_utf16_is_big_endian: true, content_type: nil)
|
8
|
+
@text = +text
|
9
|
+
@content_type = content_type
|
10
|
+
@assume_utf16_is_big_endian = assume_utf16_is_big_endian
|
11
|
+
end
|
12
|
+
|
13
|
+
def call
|
14
|
+
if can_encode?
|
15
|
+
encoded_text
|
16
|
+
else
|
17
|
+
text
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def can_encode?
|
24
|
+
''.respond_to?(:encoding) && charset
|
25
|
+
end
|
26
|
+
|
27
|
+
def encoded_text
|
28
|
+
if 'utf-16'.casecmp(charset) == 0
|
29
|
+
encode_utf_16
|
30
|
+
else
|
31
|
+
encode_with_ruby_encoding
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def encode_utf_16
|
36
|
+
if text.bytesize >= 2
|
37
|
+
if text.getbyte(0) == 0xFF && text.getbyte(1) == 0xFE
|
38
|
+
return text.force_encoding('UTF-16LE')
|
39
|
+
elsif text.getbyte(0) == 0xFE && text.getbyte(1) == 0xFF
|
40
|
+
return text.force_encoding('UTF-16BE')
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
if assume_utf16_is_big_endian # option
|
45
|
+
text.force_encoding('UTF-16BE')
|
46
|
+
else
|
47
|
+
text.force_encoding('UTF-16LE')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def encode_with_ruby_encoding
|
52
|
+
# NOTE: This will raise an argument error if the
|
53
|
+
# charset does not exist
|
54
|
+
encoding = Encoding.find(charset)
|
55
|
+
text.force_encoding(encoding.to_s)
|
56
|
+
rescue ArgumentError
|
57
|
+
text
|
58
|
+
end
|
59
|
+
|
60
|
+
def charset
|
61
|
+
return nil if content_type.nil?
|
62
|
+
|
63
|
+
if (matchdata = content_type.match(/;\s*charset\s*=\s*([^=,;"\s]+)/i))
|
64
|
+
return matchdata.captures.first
|
65
|
+
end
|
66
|
+
|
67
|
+
if (matchdata = content_type.match(/;\s*charset\s*=\s*"((\\.|[^\\"])+)"/i))
|
68
|
+
return matchdata.captures.first.gsub(/\\(.)/, '\1')
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HTTParty
|
4
|
+
module Utils
|
5
|
+
def self.stringify_keys(hash)
|
6
|
+
return hash.transform_keys(&:to_s) if hash.respond_to?(:transform_keys)
|
7
|
+
|
8
|
+
hash.each_with_object({}) do |(key, value), new_hash|
|
9
|
+
new_hash[key.to_s] = value
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/lib/httparty/version.rb
CHANGED