httparty 0.16.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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