uri 0.10.3 → 0.13.3
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 +4 -4
- data/.github/dependabot.yml +6 -0
- data/.github/workflows/gh-pages.yml +46 -0
- data/.github/workflows/test.yml +13 -7
- data/.gitignore +1 -0
- data/README.md +4 -2
- data/Rakefile +6 -5
- data/lib/uri/common.rb +310 -136
- data/lib/uri/file.rb +7 -1
- data/lib/uri/ftp.rb +2 -1
- data/lib/uri/generic.rb +53 -20
- data/lib/uri/http.rb +40 -2
- data/lib/uri/https.rb +2 -1
- data/lib/uri/ldap.rb +1 -1
- data/lib/uri/ldaps.rb +2 -1
- data/lib/uri/mailto.rb +2 -2
- data/lib/uri/rfc2396_parser.rb +13 -7
- data/lib/uri/rfc3986_parser.rb +103 -34
- data/lib/uri/version.rb +1 -1
- data/lib/uri/ws.rb +1 -2
- data/lib/uri/wss.rb +2 -1
- data/lib/uri.rb +3 -2
- data/rakelib/sync_tool.rake +17 -0
- data/uri.gemspec +14 -4
- metadata +10 -7
data/lib/uri/common.rb
CHANGED
@@ -13,9 +13,14 @@ require_relative "rfc2396_parser"
|
|
13
13
|
require_relative "rfc3986_parser"
|
14
14
|
|
15
15
|
module URI
|
16
|
+
include RFC2396_REGEXP
|
17
|
+
|
16
18
|
REGEXP = RFC2396_REGEXP
|
17
19
|
Parser = RFC2396_Parser
|
18
20
|
RFC3986_PARSER = RFC3986_Parser.new
|
21
|
+
Ractor.make_shareable(RFC3986_PARSER) if defined?(Ractor)
|
22
|
+
RFC2396_PARSER = RFC2396_Parser.new
|
23
|
+
Ractor.make_shareable(RFC2396_PARSER) if defined?(Ractor)
|
19
24
|
|
20
25
|
# URI::Parser.new
|
21
26
|
DEFAULT_PARSER = Parser.new
|
@@ -27,6 +32,7 @@ module URI
|
|
27
32
|
DEFAULT_PARSER.regexp.each_pair do |sym, str|
|
28
33
|
const_set(sym, str)
|
29
34
|
end
|
35
|
+
Ractor.make_shareable(DEFAULT_PARSER) if defined?(Ractor)
|
30
36
|
|
31
37
|
module Util # :nodoc:
|
32
38
|
def make_components_hash(klass, array_hash)
|
@@ -60,24 +66,70 @@ module URI
|
|
60
66
|
module_function :make_components_hash
|
61
67
|
end
|
62
68
|
|
63
|
-
|
69
|
+
module Schemes
|
70
|
+
end
|
71
|
+
private_constant :Schemes
|
72
|
+
|
73
|
+
# Registers the given +klass+ as the class to be instantiated
|
74
|
+
# when parsing a \URI with the given +scheme+:
|
75
|
+
#
|
76
|
+
# URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
|
77
|
+
# URI.scheme_list['MS_SEARCH'] # => URI::Generic
|
78
|
+
#
|
79
|
+
# Note that after calling String#upcase on +scheme+, it must be a valid
|
80
|
+
# constant name.
|
81
|
+
def self.register_scheme(scheme, klass)
|
82
|
+
Schemes.const_set(scheme.to_s.upcase, klass)
|
83
|
+
end
|
64
84
|
|
65
|
-
|
66
|
-
#
|
85
|
+
# Returns a hash of the defined schemes:
|
86
|
+
#
|
87
|
+
# URI.scheme_list
|
88
|
+
# # =>
|
89
|
+
# {"MAILTO"=>URI::MailTo,
|
90
|
+
# "LDAPS"=>URI::LDAPS,
|
91
|
+
# "WS"=>URI::WS,
|
92
|
+
# "HTTP"=>URI::HTTP,
|
93
|
+
# "HTTPS"=>URI::HTTPS,
|
94
|
+
# "LDAP"=>URI::LDAP,
|
95
|
+
# "FILE"=>URI::File,
|
96
|
+
# "FTP"=>URI::FTP}
|
97
|
+
#
|
98
|
+
# Related: URI.register_scheme.
|
67
99
|
def self.scheme_list
|
68
|
-
|
100
|
+
Schemes.constants.map { |name|
|
101
|
+
[name.to_s.upcase, Schemes.const_get(name)]
|
102
|
+
}.to_h
|
69
103
|
end
|
70
104
|
|
105
|
+
INITIAL_SCHEMES = scheme_list
|
106
|
+
private_constant :INITIAL_SCHEMES
|
107
|
+
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
|
108
|
+
|
109
|
+
# Returns a new object constructed from the given +scheme+, +arguments+,
|
110
|
+
# and +default+:
|
111
|
+
#
|
112
|
+
# - The new object is an instance of <tt>URI.scheme_list[scheme.upcase]</tt>.
|
113
|
+
# - The object is initialized by calling the class initializer
|
114
|
+
# using +scheme+ and +arguments+.
|
115
|
+
# See URI::Generic.new.
|
71
116
|
#
|
72
|
-
#
|
73
|
-
#
|
117
|
+
# Examples:
|
118
|
+
#
|
119
|
+
# values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
|
120
|
+
# URI.for('https', *values)
|
121
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
122
|
+
# URI.for('foo', *values, default: URI::HTTP)
|
123
|
+
# # => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
74
124
|
#
|
75
125
|
def self.for(scheme, *arguments, default: Generic)
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
126
|
+
const_name = scheme.to_s.upcase
|
127
|
+
|
128
|
+
uri_class = INITIAL_SCHEMES[const_name]
|
129
|
+
uri_class ||= if /\A[A-Z]\w*\z/.match?(const_name) && Schemes.const_defined?(const_name, false)
|
130
|
+
Schemes.const_get(const_name, false)
|
80
131
|
end
|
132
|
+
uri_class ||= default
|
81
133
|
|
82
134
|
return uri_class.new(scheme, *arguments)
|
83
135
|
end
|
@@ -99,95 +151,49 @@ module URI
|
|
99
151
|
#
|
100
152
|
class BadURIError < Error; end
|
101
153
|
|
102
|
-
#
|
103
|
-
#
|
104
|
-
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
#
|
108
|
-
#
|
109
|
-
#
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
# * Port
|
120
|
-
# * Registry
|
121
|
-
# * Path
|
122
|
-
# * Opaque
|
123
|
-
# * Query
|
124
|
-
# * Fragment
|
125
|
-
#
|
126
|
-
# == Usage
|
127
|
-
#
|
128
|
-
# require 'uri'
|
129
|
-
#
|
130
|
-
# URI.split("http://www.ruby-lang.org/")
|
131
|
-
# # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
|
154
|
+
# Returns a 9-element array representing the parts of the \URI
|
155
|
+
# formed from the string +uri+;
|
156
|
+
# each array element is a string or +nil+:
|
157
|
+
#
|
158
|
+
# names = %w[scheme userinfo host port registry path opaque query fragment]
|
159
|
+
# values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
160
|
+
# names.zip(values)
|
161
|
+
# # =>
|
162
|
+
# [["scheme", "https"],
|
163
|
+
# ["userinfo", "john.doe"],
|
164
|
+
# ["host", "www.example.com"],
|
165
|
+
# ["port", "123"],
|
166
|
+
# ["registry", nil],
|
167
|
+
# ["path", "/forum/questions/"],
|
168
|
+
# ["opaque", nil],
|
169
|
+
# ["query", "tag=networking&order=newest"],
|
170
|
+
# ["fragment", "top"]]
|
132
171
|
#
|
133
172
|
def self.split(uri)
|
134
173
|
RFC3986_PARSER.split(uri)
|
135
174
|
end
|
136
175
|
|
176
|
+
# Returns a new \URI object constructed from the given string +uri+:
|
137
177
|
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
# URI
|
141
|
-
#
|
142
|
-
# == Args
|
143
|
-
#
|
144
|
-
# +uri_str+::
|
145
|
-
# String with URI.
|
146
|
-
#
|
147
|
-
# == Description
|
148
|
-
#
|
149
|
-
# Creates one of the URI's subclasses instance from the string.
|
178
|
+
# URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
179
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
180
|
+
# URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
181
|
+
# # => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
150
182
|
#
|
151
|
-
#
|
152
|
-
#
|
153
|
-
# URI::InvalidURIError::
|
154
|
-
# Raised if URI given is not a correct one.
|
155
|
-
#
|
156
|
-
# == Usage
|
157
|
-
#
|
158
|
-
# require 'uri'
|
159
|
-
#
|
160
|
-
# uri = URI.parse("http://www.ruby-lang.org/")
|
161
|
-
# # => #<URI::HTTP http://www.ruby-lang.org/>
|
162
|
-
# uri.scheme
|
163
|
-
# # => "http"
|
164
|
-
# uri.host
|
165
|
-
# # => "www.ruby-lang.org"
|
166
|
-
#
|
167
|
-
# It's recommended to first ::escape the provided +uri_str+ if there are any
|
168
|
-
# invalid URI characters.
|
183
|
+
# It's recommended to first ::escape string +uri+
|
184
|
+
# if it may contain invalid URI characters.
|
169
185
|
#
|
170
186
|
def self.parse(uri)
|
171
187
|
RFC3986_PARSER.parse(uri)
|
172
188
|
end
|
173
189
|
|
190
|
+
# Merges the given URI strings +str+
|
191
|
+
# per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
|
174
192
|
#
|
175
|
-
#
|
176
|
-
#
|
177
|
-
# URI::join(str[, str, ...])
|
178
|
-
#
|
179
|
-
# == Args
|
180
|
-
#
|
181
|
-
# +str+::
|
182
|
-
# String(s) to work with, will be converted to RFC3986 URIs before merging.
|
183
|
-
#
|
184
|
-
# == Description
|
185
|
-
#
|
186
|
-
# Joins URIs.
|
187
|
-
#
|
188
|
-
# == Usage
|
193
|
+
# Each string in +str+ is converted to an
|
194
|
+
# {RFC3986 URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
|
189
195
|
#
|
190
|
-
#
|
196
|
+
# Examples:
|
191
197
|
#
|
192
198
|
# URI.join("http://example.com/","main.rbx")
|
193
199
|
# # => #<URI::HTTP http://example.com/main.rbx>
|
@@ -232,7 +238,7 @@ module URI
|
|
232
238
|
# URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
|
233
239
|
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
|
234
240
|
#
|
235
|
-
def self.extract(str, schemes = nil, &block)
|
241
|
+
def self.extract(str, schemes = nil, &block) # :nodoc:
|
236
242
|
warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
|
237
243
|
DEFAULT_PARSER.extract(str, schemes, &block)
|
238
244
|
end
|
@@ -269,7 +275,7 @@ module URI
|
|
269
275
|
# p $&
|
270
276
|
# end
|
271
277
|
#
|
272
|
-
def self.regexp(schemes = nil)
|
278
|
+
def self.regexp(schemes = nil)# :nodoc:
|
273
279
|
warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
|
274
280
|
DEFAULT_PARSER.make_regexp(schemes)
|
275
281
|
end
|
@@ -278,6 +284,7 @@ module URI
|
|
278
284
|
256.times do |i|
|
279
285
|
TBLENCWWWCOMP_[-i.chr] = -('%%%02X' % i)
|
280
286
|
end
|
287
|
+
TBLENCURICOMP_ = TBLENCWWWCOMP_.dup.freeze
|
281
288
|
TBLENCWWWCOMP_[' '] = '+'
|
282
289
|
TBLENCWWWCOMP_.freeze
|
283
290
|
TBLDECWWWCOMP_ = {} # :nodoc:
|
@@ -291,18 +298,91 @@ module URI
|
|
291
298
|
TBLDECWWWCOMP_['+'] = ' '
|
292
299
|
TBLDECWWWCOMP_.freeze
|
293
300
|
|
294
|
-
#
|
301
|
+
# Returns a URL-encoded string derived from the given string +str+.
|
302
|
+
#
|
303
|
+
# The returned string:
|
304
|
+
#
|
305
|
+
# - Preserves:
|
306
|
+
#
|
307
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
308
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
309
|
+
# and <tt>'0'..'9'</tt>.
|
310
|
+
#
|
311
|
+
# Example:
|
312
|
+
#
|
313
|
+
# URI.encode_www_form_component('*.-_azAZ09')
|
314
|
+
# # => "*.-_azAZ09"
|
315
|
+
#
|
316
|
+
# - Converts:
|
317
|
+
#
|
318
|
+
# - Character <tt>' '</tt> to character <tt>'+'</tt>.
|
319
|
+
# - Any other character to "percent notation";
|
320
|
+
# the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>.
|
295
321
|
#
|
296
|
-
#
|
297
|
-
# (ASCII space) to + and converts others to %XX.
|
322
|
+
# Example:
|
298
323
|
#
|
299
|
-
#
|
324
|
+
# URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
|
325
|
+
# # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
|
300
326
|
#
|
301
|
-
#
|
302
|
-
# https://www.w3.org/TR/2013/CR-html5-20130806/forms.html#url-encoded-form-data.
|
327
|
+
# Encoding:
|
303
328
|
#
|
304
|
-
#
|
329
|
+
# - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored.
|
330
|
+
# - Otherwise +str+ is converted first to Encoding::UTF_8
|
331
|
+
# (with suitable character replacements),
|
332
|
+
# and then to encoding +enc+.
|
333
|
+
#
|
334
|
+
# In either case, the returned string has forced encoding Encoding::US_ASCII.
|
335
|
+
#
|
336
|
+
# Related: URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>).
|
305
337
|
def self.encode_www_form_component(str, enc=nil)
|
338
|
+
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Returns a string decoded from the given \URL-encoded string +str+.
|
342
|
+
#
|
343
|
+
# The given string is first encoded as Encoding::ASCII-8BIT (using String#b),
|
344
|
+
# then decoded (as below), and finally force-encoded to the given encoding +enc+.
|
345
|
+
#
|
346
|
+
# The returned string:
|
347
|
+
#
|
348
|
+
# - Preserves:
|
349
|
+
#
|
350
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
351
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
352
|
+
# and <tt>'0'..'9'</tt>.
|
353
|
+
#
|
354
|
+
# Example:
|
355
|
+
#
|
356
|
+
# URI.decode_www_form_component('*.-_azAZ09')
|
357
|
+
# # => "*.-_azAZ09"
|
358
|
+
#
|
359
|
+
# - Converts:
|
360
|
+
#
|
361
|
+
# - Character <tt>'+'</tt> to character <tt>' '</tt>.
|
362
|
+
# - Each "percent notation" to an ASCII character.
|
363
|
+
#
|
364
|
+
# Example:
|
365
|
+
#
|
366
|
+
# URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
|
367
|
+
# # => "Here are some punctuation characters: ,;?:"
|
368
|
+
#
|
369
|
+
# Related: URI.decode_uri_component (preserves <tt>'+'</tt>).
|
370
|
+
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
371
|
+
_decode_uri_component(/\+|%\h\h/, str, enc)
|
372
|
+
end
|
373
|
+
|
374
|
+
# Like URI.encode_www_form_component, except that <tt>' '</tt> (space)
|
375
|
+
# is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
|
376
|
+
def self.encode_uri_component(str, enc=nil)
|
377
|
+
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
|
378
|
+
end
|
379
|
+
|
380
|
+
# Like URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
|
381
|
+
def self.decode_uri_component(str, enc=Encoding::UTF_8)
|
382
|
+
_decode_uri_component(/%\h\h/, str, enc)
|
383
|
+
end
|
384
|
+
|
385
|
+
def self._encode_uri_component(regexp, table, str, enc)
|
306
386
|
str = str.to_s.dup
|
307
387
|
if str.encoding != Encoding::ASCII_8BIT
|
308
388
|
if enc && enc != Encoding::ASCII_8BIT
|
@@ -311,47 +391,115 @@ module URI
|
|
311
391
|
end
|
312
392
|
str.force_encoding(Encoding::ASCII_8BIT)
|
313
393
|
end
|
314
|
-
str.gsub!(
|
394
|
+
str.gsub!(regexp, table)
|
315
395
|
str.force_encoding(Encoding::US_ASCII)
|
316
396
|
end
|
397
|
+
private_class_method :_encode_uri_component
|
317
398
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
#
|
322
|
-
# See URI.encode_www_form_component, URI.decode_www_form.
|
323
|
-
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
324
|
-
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str
|
325
|
-
str.b.gsub(/\+|%\h\h/, TBLDECWWWCOMP_).force_encoding(enc)
|
399
|
+
def self._decode_uri_component(regexp, str, enc)
|
400
|
+
raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/.match?(str)
|
401
|
+
str.b.gsub(regexp, TBLDECWWWCOMP_).force_encoding(enc)
|
326
402
|
end
|
403
|
+
private_class_method :_decode_uri_component
|
327
404
|
|
328
|
-
#
|
405
|
+
# Returns a URL-encoded string derived from the given
|
406
|
+
# {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes]
|
407
|
+
# +enum+.
|
408
|
+
#
|
409
|
+
# The result is suitable for use as form data
|
410
|
+
# for an \HTTP request whose <tt>Content-Type</tt> is
|
411
|
+
# <tt>'application/x-www-form-urlencoded'</tt>.
|
412
|
+
#
|
413
|
+
# The returned string consists of the elements of +enum+,
|
414
|
+
# each converted to one or more URL-encoded strings,
|
415
|
+
# and all joined with character <tt>'&'</tt>.
|
416
|
+
#
|
417
|
+
# Simple examples:
|
418
|
+
#
|
419
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
|
420
|
+
# # => "foo=0&bar=1&baz=2"
|
421
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
422
|
+
# # => "foo=0&bar=1&baz=2"
|
423
|
+
#
|
424
|
+
# The returned string is formed using method URI.encode_www_form_component,
|
425
|
+
# which converts certain characters:
|
329
426
|
#
|
330
|
-
#
|
331
|
-
#
|
427
|
+
# URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
|
428
|
+
# # => "f%23o=%2F&b-r=%24&b+z=%40"
|
332
429
|
#
|
333
|
-
#
|
430
|
+
# When +enum+ is Array-like, each element +ele+ is converted to a field:
|
334
431
|
#
|
335
|
-
#
|
336
|
-
#
|
337
|
-
#
|
338
|
-
# ASCII incompatible encoding are converted to UTF-8.)
|
432
|
+
# - If +ele+ is an array of two or more elements,
|
433
|
+
# the field is formed from its first two elements
|
434
|
+
# (and any additional elements are ignored):
|
339
435
|
#
|
340
|
-
#
|
341
|
-
#
|
436
|
+
# name = URI.encode_www_form_component(ele[0], enc)
|
437
|
+
# value = URI.encode_www_form_component(ele[1], enc)
|
438
|
+
# "#{name}=#{value}"
|
342
439
|
#
|
343
|
-
#
|
440
|
+
# Examples:
|
344
441
|
#
|
345
|
-
#
|
346
|
-
#
|
347
|
-
#
|
348
|
-
#
|
349
|
-
#
|
350
|
-
#
|
351
|
-
#
|
352
|
-
#
|
442
|
+
# URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
|
443
|
+
# # => "foo=bar&baz=bat"
|
444
|
+
# URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
|
445
|
+
# # => "foo=0&bar=baz"
|
446
|
+
#
|
447
|
+
# - If +ele+ is an array of one element,
|
448
|
+
# the field is formed from <tt>ele[0]</tt>:
|
449
|
+
#
|
450
|
+
# URI.encode_www_form_component(ele[0])
|
451
|
+
#
|
452
|
+
# Example:
|
453
|
+
#
|
454
|
+
# URI.encode_www_form([['foo'], [:bar], [0]])
|
455
|
+
# # => "foo&bar&0"
|
456
|
+
#
|
457
|
+
# - Otherwise the field is formed from +ele+:
|
458
|
+
#
|
459
|
+
# URI.encode_www_form_component(ele)
|
460
|
+
#
|
461
|
+
# Example:
|
462
|
+
#
|
463
|
+
# URI.encode_www_form(['foo', :bar, 0])
|
464
|
+
# # => "foo&bar&0"
|
465
|
+
#
|
466
|
+
# The elements of an Array-like +enum+ may be mixture:
|
467
|
+
#
|
468
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
|
469
|
+
# # => "foo=0&bar=1&baz&bat"
|
470
|
+
#
|
471
|
+
# When +enum+ is Hash-like,
|
472
|
+
# each +key+/+value+ pair is converted to one or more fields:
|
473
|
+
#
|
474
|
+
# - If +value+ is
|
475
|
+
# {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects],
|
476
|
+
# each element +ele+ in +value+ is paired with +key+ to form a field:
|
477
|
+
#
|
478
|
+
# name = URI.encode_www_form_component(key, enc)
|
479
|
+
# value = URI.encode_www_form_component(ele, enc)
|
480
|
+
# "#{name}=#{value}"
|
481
|
+
#
|
482
|
+
# Example:
|
483
|
+
#
|
484
|
+
# URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
|
485
|
+
# # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
|
486
|
+
#
|
487
|
+
# - Otherwise, +key+ and +value+ are paired to form a field:
|
488
|
+
#
|
489
|
+
# name = URI.encode_www_form_component(key, enc)
|
490
|
+
# value = URI.encode_www_form_component(value, enc)
|
491
|
+
# "#{name}=#{value}"
|
492
|
+
#
|
493
|
+
# Example:
|
494
|
+
#
|
495
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
496
|
+
# # => "foo=0&bar=1&baz=2"
|
497
|
+
#
|
498
|
+
# The elements of a Hash-like +enum+ may be mixture:
|
499
|
+
#
|
500
|
+
# URI.encode_www_form({foo: [0, 1], bar: 2})
|
501
|
+
# # => "foo=0&foo=1&bar=2"
|
353
502
|
#
|
354
|
-
# See URI.encode_www_form_component, URI.decode_www_form.
|
355
503
|
def self.encode_www_form(enum, enc=nil)
|
356
504
|
enum.map do |k,v|
|
357
505
|
if v.nil?
|
@@ -372,22 +520,39 @@ module URI
|
|
372
520
|
end.join('&')
|
373
521
|
end
|
374
522
|
|
375
|
-
#
|
523
|
+
# Returns name/value pairs derived from the given string +str+,
|
524
|
+
# which must be an ASCII string.
|
525
|
+
#
|
526
|
+
# The method may be used to decode the body of Net::HTTPResponse object +res+
|
527
|
+
# for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>.
|
376
528
|
#
|
377
|
-
#
|
378
|
-
#
|
529
|
+
# The returned data is an array of 2-element subarrays;
|
530
|
+
# each subarray is a name/value pair (both are strings).
|
531
|
+
# Each returned string has encoding +enc+,
|
532
|
+
# and has had invalid characters removed via
|
533
|
+
# {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub].
|
379
534
|
#
|
380
|
-
#
|
381
|
-
# so this supports only &-separator, and doesn't support ;-separator.
|
535
|
+
# A simple example:
|
382
536
|
#
|
383
|
-
#
|
384
|
-
#
|
385
|
-
#
|
386
|
-
#
|
387
|
-
#
|
388
|
-
#
|
537
|
+
# URI.decode_www_form('foo=0&bar=1&baz')
|
538
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
539
|
+
#
|
540
|
+
# The returned strings have certain conversions,
|
541
|
+
# similar to those performed in URI.decode_www_form_component:
|
542
|
+
#
|
543
|
+
# URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
|
544
|
+
# # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]
|
545
|
+
#
|
546
|
+
# The given string may contain consecutive separators:
|
547
|
+
#
|
548
|
+
# URI.decode_www_form('foo=0&&bar=1&&baz=2')
|
549
|
+
# # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]
|
550
|
+
#
|
551
|
+
# A different separator may be specified:
|
552
|
+
#
|
553
|
+
# URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
|
554
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
389
555
|
#
|
390
|
-
# See URI.decode_www_form_component, URI.encode_www_form.
|
391
556
|
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
|
392
557
|
raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
|
393
558
|
ary = []
|
@@ -653,6 +818,7 @@ module URI
|
|
653
818
|
"utf-16"=>"utf-16le",
|
654
819
|
"utf-16le"=>"utf-16le",
|
655
820
|
} # :nodoc:
|
821
|
+
Ractor.make_shareable(WEB_ENCODINGS_) if defined?(Ractor)
|
656
822
|
|
657
823
|
# :nodoc:
|
658
824
|
# return encoding or nil
|
@@ -665,7 +831,15 @@ end # module URI
|
|
665
831
|
module Kernel
|
666
832
|
|
667
833
|
#
|
668
|
-
# Returns
|
834
|
+
# Returns a \URI object derived from the given +uri+,
|
835
|
+
# which may be a \URI string or an existing \URI object:
|
836
|
+
#
|
837
|
+
# # Returns a new URI.
|
838
|
+
# uri = URI('http://github.com/ruby/ruby')
|
839
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
840
|
+
# # Returns the given URI.
|
841
|
+
# URI(uri)
|
842
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
669
843
|
#
|
670
844
|
def URI(uri)
|
671
845
|
if uri.is_a?(URI::Generic)
|
data/lib/uri/file.rb
CHANGED
@@ -33,6 +33,9 @@ module URI
|
|
33
33
|
# If an Array is used, the components must be passed in the
|
34
34
|
# order <code>[host, path]</code>.
|
35
35
|
#
|
36
|
+
# A path from e.g. the File class should be escaped before
|
37
|
+
# being passed.
|
38
|
+
#
|
36
39
|
# Examples:
|
37
40
|
#
|
38
41
|
# require 'uri'
|
@@ -44,6 +47,9 @@ module URI
|
|
44
47
|
# :path => '/ruby/src'})
|
45
48
|
# uri2.to_s # => "file://host.example.com/ruby/src"
|
46
49
|
#
|
50
|
+
# uri3 = URI::File.build({:path => URI::escape('/path/my file.txt')})
|
51
|
+
# uri3.to_s # => "file:///path/my%20file.txt"
|
52
|
+
#
|
47
53
|
def self.build(args)
|
48
54
|
tmp = Util::make_components_hash(self, args)
|
49
55
|
super(tmp)
|
@@ -90,5 +96,5 @@ module URI
|
|
90
96
|
end
|
91
97
|
end
|
92
98
|
|
93
|
-
|
99
|
+
register_scheme 'FILE', File
|
94
100
|
end
|