uri 0.12.3 → 0.13.1
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/workflows/gh-pages.yml +46 -0
- data/.github/workflows/test.yml +8 -4
- data/.gitignore +1 -0
- data/README.md +1 -0
- data/Rakefile +6 -5
- data/lib/uri/common.rb +256 -132
- data/lib/uri/generic.rb +1 -0
- data/lib/uri/rfc3986_parser.rb +95 -31
- data/lib/uri/version.rb +1 -1
- data/rakelib/sync_tool.rake +17 -0
- data/uri.gemspec +13 -5
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3aa899933652aa155b60babf100c7b892a976a70121c16a408313687b85be675
|
4
|
+
data.tar.gz: 2c1f5cdfa19249b82f3c84f7c090eb389e9079147d22db436265b43c2cf283f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 709ffc67b67a2de85fc86c8317537e6aced97c17abf8111f9c682d0232a46610ef0f769a9fdaf0802689e08a81b83a6cb2d9a9981b0c335513203171966e7251
|
7
|
+
data.tar.gz: f92761f35747c21ed9e5e11d7390c786be62548bc9f83a5de9b7c25fb0b9c3378ee8c20d1938dcc8e88a7d47de2996ed8c7fed6b970e96a9c967e5ce7f27a41a
|
@@ -0,0 +1,46 @@
|
|
1
|
+
name: Deploy RDoc site to Pages
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ 'master' ]
|
6
|
+
workflow_dispatch:
|
7
|
+
|
8
|
+
permissions:
|
9
|
+
contents: read
|
10
|
+
pages: write
|
11
|
+
id-token: write
|
12
|
+
|
13
|
+
concurrency:
|
14
|
+
group: "pages"
|
15
|
+
cancel-in-progress: true
|
16
|
+
|
17
|
+
jobs:
|
18
|
+
build:
|
19
|
+
runs-on: ubuntu-latest
|
20
|
+
steps:
|
21
|
+
- name: Checkout
|
22
|
+
uses: actions/checkout@v4
|
23
|
+
- name: Setup Ruby
|
24
|
+
uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0
|
25
|
+
with:
|
26
|
+
ruby-version: '3.2'
|
27
|
+
bundler-cache: true
|
28
|
+
- name: Setup Pages
|
29
|
+
id: pages
|
30
|
+
uses: actions/configure-pages@v3
|
31
|
+
- name: Build with RDoc
|
32
|
+
# Outputs to the './_site' directory by default
|
33
|
+
run: bundle exec rake rdoc
|
34
|
+
- name: Upload artifact
|
35
|
+
uses: actions/upload-pages-artifact@v2
|
36
|
+
|
37
|
+
deploy:
|
38
|
+
environment:
|
39
|
+
name: github-pages
|
40
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
41
|
+
runs-on: ubuntu-latest
|
42
|
+
needs: build
|
43
|
+
steps:
|
44
|
+
- name: Deploy to GitHub Pages
|
45
|
+
id: deployment
|
46
|
+
uses: actions/deploy-pages@v2
|
data/.github/workflows/test.yml
CHANGED
@@ -3,20 +3,24 @@ name: CI
|
|
3
3
|
on: [push, pull_request]
|
4
4
|
|
5
5
|
jobs:
|
6
|
+
ruby-versions:
|
7
|
+
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
|
8
|
+
with:
|
9
|
+
min_version: 2.5
|
10
|
+
|
6
11
|
build:
|
12
|
+
needs: ruby-versions
|
7
13
|
name: build (${{ matrix.ruby }} / ${{ matrix.os }})
|
8
14
|
strategy:
|
9
15
|
matrix:
|
10
|
-
ruby:
|
16
|
+
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}
|
11
17
|
os: [ ubuntu-latest, macos-latest ]
|
12
18
|
exclude:
|
13
|
-
- ruby: 2.4
|
14
|
-
os: macos-latest
|
15
19
|
- ruby: 2.5
|
16
20
|
os: macos-latest
|
17
21
|
runs-on: ${{ matrix.os }}
|
18
22
|
steps:
|
19
|
-
- uses: actions/checkout@
|
23
|
+
- uses: actions/checkout@v4
|
20
24
|
- name: Set up Ruby
|
21
25
|
uses: ruby/setup-ruby@v1
|
22
26
|
with:
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# URI
|
2
2
|
|
3
3
|
[](https://github.com/ruby/uri/actions/workflows/test.yml)
|
4
|
+
[](https://ruby.github.io/uri/)
|
4
5
|
|
5
6
|
URI is a module providing classes to handle Uniform Resource Identifiers [RFC2396](http://tools.ietf.org/html/rfc2396).
|
6
7
|
|
data/Rakefile
CHANGED
@@ -7,11 +7,12 @@ Rake::TestTask.new(:test) do |t|
|
|
7
7
|
t.test_files = FileList["test/**/test_*.rb"]
|
8
8
|
end
|
9
9
|
|
10
|
-
task
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
require "rdoc/task"
|
11
|
+
RDoc::Task.new do |doc|
|
12
|
+
doc.main = "README.md"
|
13
|
+
doc.title = "URI - handle Uniform Resource Identifiers"
|
14
|
+
doc.rdoc_files = FileList.new %w[lib README.md LICENSE.txt]
|
15
|
+
doc.rdoc_dir = "_site" # for github pages
|
15
16
|
end
|
16
17
|
|
17
18
|
task :default => :test
|
data/lib/uri/common.rb
CHANGED
@@ -70,16 +70,32 @@ module URI
|
|
70
70
|
end
|
71
71
|
private_constant :Schemes
|
72
72
|
|
73
|
+
# Registers the given +klass+ as the class to be instantiated
|
74
|
+
# when parsing a \URI with the given +scheme+:
|
73
75
|
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
# can be registered (no -/+/. allowed).
|
76
|
+
# URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
|
77
|
+
# URI.scheme_list['MS_SEARCH'] # => URI::Generic
|
77
78
|
#
|
79
|
+
# Note that after calling String#upcase on +scheme+, it must be a valid
|
80
|
+
# constant name.
|
78
81
|
def self.register_scheme(scheme, klass)
|
79
82
|
Schemes.const_set(scheme.to_s.upcase, klass)
|
80
83
|
end
|
81
84
|
|
82
|
-
# Returns a
|
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.
|
83
99
|
def self.scheme_list
|
84
100
|
Schemes.constants.map { |name|
|
85
101
|
[name.to_s.upcase, Schemes.const_get(name)]
|
@@ -90,9 +106,21 @@ module URI
|
|
90
106
|
private_constant :INITIAL_SCHEMES
|
91
107
|
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
|
92
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.
|
116
|
+
#
|
117
|
+
# Examples:
|
93
118
|
#
|
94
|
-
#
|
95
|
-
#
|
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>
|
96
124
|
#
|
97
125
|
def self.for(scheme, *arguments, default: Generic)
|
98
126
|
const_name = scheme.to_s.upcase
|
@@ -123,95 +151,49 @@ module URI
|
|
123
151
|
#
|
124
152
|
class BadURIError < Error; end
|
125
153
|
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
#
|
142
|
-
#
|
143
|
-
# * Port
|
144
|
-
# * Registry
|
145
|
-
# * Path
|
146
|
-
# * Opaque
|
147
|
-
# * Query
|
148
|
-
# * Fragment
|
149
|
-
#
|
150
|
-
# == Usage
|
151
|
-
#
|
152
|
-
# require 'uri'
|
153
|
-
#
|
154
|
-
# URI.split("http://www.ruby-lang.org/")
|
155
|
-
# # => ["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"]]
|
156
171
|
#
|
157
172
|
def self.split(uri)
|
158
173
|
RFC3986_PARSER.split(uri)
|
159
174
|
end
|
160
175
|
|
176
|
+
# Returns a new \URI object constructed from the given string +uri+:
|
161
177
|
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
# URI
|
165
|
-
#
|
166
|
-
# == Args
|
167
|
-
#
|
168
|
-
# +uri_str+::
|
169
|
-
# String with URI.
|
170
|
-
#
|
171
|
-
# == Description
|
172
|
-
#
|
173
|
-
# Creates one of the URI's subclasses instance from the string.
|
174
|
-
#
|
175
|
-
# == Raises
|
176
|
-
#
|
177
|
-
# URI::InvalidURIError::
|
178
|
-
# Raised if URI given is not a correct one.
|
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>
|
179
182
|
#
|
180
|
-
#
|
181
|
-
#
|
182
|
-
# require 'uri'
|
183
|
-
#
|
184
|
-
# uri = URI.parse("http://www.ruby-lang.org/")
|
185
|
-
# # => #<URI::HTTP http://www.ruby-lang.org/>
|
186
|
-
# uri.scheme
|
187
|
-
# # => "http"
|
188
|
-
# uri.host
|
189
|
-
# # => "www.ruby-lang.org"
|
190
|
-
#
|
191
|
-
# It's recommended to first ::escape the provided +uri_str+ if there are any
|
192
|
-
# invalid URI characters.
|
183
|
+
# It's recommended to first ::escape string +uri+
|
184
|
+
# if it may contain invalid URI characters.
|
193
185
|
#
|
194
186
|
def self.parse(uri)
|
195
187
|
RFC3986_PARSER.parse(uri)
|
196
188
|
end
|
197
189
|
|
190
|
+
# Merges the given URI strings +str+
|
191
|
+
# per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
|
198
192
|
#
|
199
|
-
#
|
200
|
-
#
|
201
|
-
# URI::join(str[, str, ...])
|
193
|
+
# Each string in +str+ is converted to an
|
194
|
+
# {RFC3986 URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
|
202
195
|
#
|
203
|
-
#
|
204
|
-
#
|
205
|
-
# +str+::
|
206
|
-
# String(s) to work with, will be converted to RFC3986 URIs before merging.
|
207
|
-
#
|
208
|
-
# == Description
|
209
|
-
#
|
210
|
-
# Joins URIs.
|
211
|
-
#
|
212
|
-
# == Usage
|
213
|
-
#
|
214
|
-
# require 'uri'
|
196
|
+
# Examples:
|
215
197
|
#
|
216
198
|
# URI.join("http://example.com/","main.rbx")
|
217
199
|
# # => #<URI::HTTP http://example.com/main.rbx>
|
@@ -256,7 +238,7 @@ module URI
|
|
256
238
|
# URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
|
257
239
|
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
|
258
240
|
#
|
259
|
-
def self.extract(str, schemes = nil, &block)
|
241
|
+
def self.extract(str, schemes = nil, &block) # :nodoc:
|
260
242
|
warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
|
261
243
|
DEFAULT_PARSER.extract(str, schemes, &block)
|
262
244
|
end
|
@@ -293,7 +275,7 @@ module URI
|
|
293
275
|
# p $&
|
294
276
|
# end
|
295
277
|
#
|
296
|
-
def self.regexp(schemes = nil)
|
278
|
+
def self.regexp(schemes = nil)# :nodoc:
|
297
279
|
warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
|
298
280
|
DEFAULT_PARSER.make_regexp(schemes)
|
299
281
|
end
|
@@ -316,40 +298,86 @@ module URI
|
|
316
298
|
TBLDECWWWCOMP_['+'] = ' '
|
317
299
|
TBLDECWWWCOMP_.freeze
|
318
300
|
|
319
|
-
#
|
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:
|
320
312
|
#
|
321
|
-
#
|
322
|
-
#
|
313
|
+
# URI.encode_www_form_component('*.-_azAZ09')
|
314
|
+
# # => "*.-_azAZ09"
|
323
315
|
#
|
324
|
-
#
|
316
|
+
# - Converts:
|
325
317
|
#
|
326
|
-
#
|
327
|
-
#
|
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>.
|
328
321
|
#
|
329
|
-
#
|
322
|
+
# Example:
|
323
|
+
#
|
324
|
+
# URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
|
325
|
+
# # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
|
326
|
+
#
|
327
|
+
# Encoding:
|
328
|
+
#
|
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>).
|
330
337
|
def self.encode_www_form_component(str, enc=nil)
|
331
338
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
|
332
339
|
end
|
333
340
|
|
334
|
-
#
|
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.
|
335
363
|
#
|
336
|
-
#
|
364
|
+
# Example:
|
337
365
|
#
|
338
|
-
#
|
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>).
|
339
370
|
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
340
371
|
_decode_uri_component(/\+|%\h\h/, str, enc)
|
341
372
|
end
|
342
373
|
|
343
|
-
#
|
344
|
-
#
|
345
|
-
# This encodes SP to %20 instead of +.
|
374
|
+
# Like URI.encode_www_form_component, except that <tt>' '</tt> (space)
|
375
|
+
# is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
|
346
376
|
def self.encode_uri_component(str, enc=nil)
|
347
377
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
|
348
378
|
end
|
349
379
|
|
350
|
-
#
|
351
|
-
#
|
352
|
-
# This does not decode + to SP.
|
380
|
+
# Like URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
|
353
381
|
def self.decode_uri_component(str, enc=Encoding::UTF_8)
|
354
382
|
_decode_uri_component(/%\h\h/, str, enc)
|
355
383
|
end
|
@@ -374,33 +402,104 @@ module URI
|
|
374
402
|
end
|
375
403
|
private_class_method :_decode_uri_component
|
376
404
|
|
377
|
-
#
|
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:
|
426
|
+
#
|
427
|
+
# URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
|
428
|
+
# # => "f%23o=%2F&b-r=%24&b+z=%40"
|
429
|
+
#
|
430
|
+
# When +enum+ is Array-like, each element +ele+ is converted to a field:
|
431
|
+
#
|
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):
|
435
|
+
#
|
436
|
+
# name = URI.encode_www_form_component(ele[0], enc)
|
437
|
+
# value = URI.encode_www_form_component(ele[1], enc)
|
438
|
+
# "#{name}=#{value}"
|
378
439
|
#
|
379
|
-
#
|
380
|
-
# from given an Enumerable object.
|
440
|
+
# Examples:
|
381
441
|
#
|
382
|
-
#
|
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"
|
383
446
|
#
|
384
|
-
#
|
385
|
-
#
|
386
|
-
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
|
387
|
-
# ASCII incompatible encoding are converted to UTF-8.)
|
447
|
+
# - If +ele+ is an array of one element,
|
448
|
+
# the field is formed from <tt>ele[0]</tt>:
|
388
449
|
#
|
389
|
-
#
|
390
|
-
# multipart/form-data.
|
450
|
+
# URI.encode_www_form_component(ele[0])
|
391
451
|
#
|
392
|
-
#
|
452
|
+
# Example:
|
393
453
|
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
400
|
-
#
|
401
|
-
#
|
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"
|
402
502
|
#
|
403
|
-
# See URI.encode_www_form_component, URI.decode_www_form.
|
404
503
|
def self.encode_www_form(enum, enc=nil)
|
405
504
|
enum.map do |k,v|
|
406
505
|
if v.nil?
|
@@ -421,22 +520,39 @@ module URI
|
|
421
520
|
end.join('&')
|
422
521
|
end
|
423
522
|
|
424
|
-
#
|
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>.
|
528
|
+
#
|
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].
|
425
534
|
#
|
426
|
-
#
|
427
|
-
# and returns an array of key-value arrays.
|
535
|
+
# A simple example:
|
428
536
|
#
|
429
|
-
#
|
430
|
-
#
|
537
|
+
# URI.decode_www_form('foo=0&bar=1&baz')
|
538
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
431
539
|
#
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
435
|
-
#
|
436
|
-
#
|
437
|
-
#
|
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", ""]]
|
438
555
|
#
|
439
|
-
# See URI.decode_www_form_component, URI.encode_www_form.
|
440
556
|
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
|
441
557
|
raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
|
442
558
|
ary = []
|
@@ -715,7 +831,15 @@ end # module URI
|
|
715
831
|
module Kernel
|
716
832
|
|
717
833
|
#
|
718
|
-
# 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>
|
719
843
|
#
|
720
844
|
def URI(uri)
|
721
845
|
if uri.is_a?(URI::Generic)
|
data/lib/uri/generic.rb
CHANGED
data/lib/uri/rfc3986_parser.rb
CHANGED
@@ -1,9 +1,73 @@
|
|
1
|
-
# frozen_string_literal:
|
1
|
+
# frozen_string_literal: true
|
2
2
|
module URI
|
3
3
|
class RFC3986_Parser # :nodoc:
|
4
4
|
# URI defined in RFC3986
|
5
|
-
|
6
|
-
|
5
|
+
HOST = %r[
|
6
|
+
(?<IP-literal>\[(?:
|
7
|
+
(?<IPv6address>
|
8
|
+
(?:\h{1,4}:){6}
|
9
|
+
(?<ls32>\h{1,4}:\h{1,4}
|
10
|
+
| (?<IPv4address>(?<dec-octet>[1-9]\d|1\d{2}|2[0-4]\d|25[0-5]|\d)
|
11
|
+
\.\g<dec-octet>\.\g<dec-octet>\.\g<dec-octet>)
|
12
|
+
)
|
13
|
+
| ::(?:\h{1,4}:){5}\g<ls32>
|
14
|
+
| \h{1,4}?::(?:\h{1,4}:){4}\g<ls32>
|
15
|
+
| (?:(?:\h{1,4}:)?\h{1,4})?::(?:\h{1,4}:){3}\g<ls32>
|
16
|
+
| (?:(?:\h{1,4}:){,2}\h{1,4})?::(?:\h{1,4}:){2}\g<ls32>
|
17
|
+
| (?:(?:\h{1,4}:){,3}\h{1,4})?::\h{1,4}:\g<ls32>
|
18
|
+
| (?:(?:\h{1,4}:){,4}\h{1,4})?::\g<ls32>
|
19
|
+
| (?:(?:\h{1,4}:){,5}\h{1,4})?::\h{1,4}
|
20
|
+
| (?:(?:\h{1,4}:){,6}\h{1,4})?::
|
21
|
+
)
|
22
|
+
| (?<IPvFuture>v\h++\.[!$&-.0-9:;=A-Z_a-z~]++)
|
23
|
+
)\])
|
24
|
+
| \g<IPv4address>
|
25
|
+
| (?<reg-name>(?:%\h\h|[!$&-.0-9;=A-Z_a-z~])*+)
|
26
|
+
]x
|
27
|
+
|
28
|
+
USERINFO = /(?:%\h\h|[!$&-.0-9:;=A-Z_a-z~])*+/
|
29
|
+
|
30
|
+
SCHEME = %r[[A-Za-z][+\-.0-9A-Za-z]*+].source
|
31
|
+
SEG = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/])].source
|
32
|
+
SEG_NC = %r[(?:%\h\h|[!$&-.0-9;=@A-Z_a-z~])].source
|
33
|
+
FRAGMENT = %r[(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+].source
|
34
|
+
|
35
|
+
RFC3986_URI = %r[\A
|
36
|
+
(?<seg>#{SEG}){0}
|
37
|
+
(?<URI>
|
38
|
+
(?<scheme>#{SCHEME}):
|
39
|
+
(?<hier-part>//
|
40
|
+
(?<authority>
|
41
|
+
(?:(?<userinfo>#{USERINFO.source})@)?
|
42
|
+
(?<host>#{HOST.source.delete(" \n")})
|
43
|
+
(?::(?<port>\d*+))?
|
44
|
+
)
|
45
|
+
(?<path-abempty>(?:/\g<seg>*+)?)
|
46
|
+
| (?<path-absolute>/((?!/)\g<seg>++)?)
|
47
|
+
| (?<path-rootless>(?!/)\g<seg>++)
|
48
|
+
| (?<path-empty>)
|
49
|
+
)
|
50
|
+
(?:\?(?<query>[^\#]*+))?
|
51
|
+
(?:\#(?<fragment>#{FRAGMENT}))?
|
52
|
+
)\z]x
|
53
|
+
|
54
|
+
RFC3986_relative_ref = %r[\A
|
55
|
+
(?<seg>#{SEG}){0}
|
56
|
+
(?<relative-ref>
|
57
|
+
(?<relative-part>//
|
58
|
+
(?<authority>
|
59
|
+
(?:(?<userinfo>#{USERINFO.source})@)?
|
60
|
+
(?<host>#{HOST.source.delete(" \n")}(?<!/))?
|
61
|
+
(?::(?<port>\d*+))?
|
62
|
+
)
|
63
|
+
(?<path-abempty>(?:/\g<seg>*+)?)
|
64
|
+
| (?<path-absolute>/\g<seg>*+)
|
65
|
+
| (?<path-noscheme>#{SEG_NC}++(?:/\g<seg>*+)?)
|
66
|
+
| (?<path-empty>)
|
67
|
+
)
|
68
|
+
(?:\?(?<query>[^#]*+))?
|
69
|
+
(?:\#(?<fragment>#{FRAGMENT}))?
|
70
|
+
)\z]x
|
7
71
|
attr_reader :regexp
|
8
72
|
|
9
73
|
def initialize
|
@@ -19,9 +83,9 @@ module URI
|
|
19
83
|
uri.ascii_only? or
|
20
84
|
raise InvalidURIError, "URI must be ascii only #{uri.dump}"
|
21
85
|
if m = RFC3986_URI.match(uri)
|
22
|
-
query = m["query"
|
23
|
-
scheme = m["scheme"
|
24
|
-
opaque = m["path-rootless"
|
86
|
+
query = m["query"]
|
87
|
+
scheme = m["scheme"]
|
88
|
+
opaque = m["path-rootless"]
|
25
89
|
if opaque
|
26
90
|
opaque << "?#{query}" if query
|
27
91
|
[ scheme,
|
@@ -32,35 +96,35 @@ module URI
|
|
32
96
|
nil, # path
|
33
97
|
opaque,
|
34
98
|
nil, # query
|
35
|
-
m["fragment"
|
99
|
+
m["fragment"]
|
36
100
|
]
|
37
101
|
else # normal
|
38
102
|
[ scheme,
|
39
|
-
m["userinfo"
|
40
|
-
m["host"
|
41
|
-
m["port"
|
103
|
+
m["userinfo"],
|
104
|
+
m["host"],
|
105
|
+
m["port"],
|
42
106
|
nil, # registry
|
43
|
-
(m["path-abempty"
|
44
|
-
m["path-absolute"
|
45
|
-
m["path-empty"
|
107
|
+
(m["path-abempty"] ||
|
108
|
+
m["path-absolute"] ||
|
109
|
+
m["path-empty"]),
|
46
110
|
nil, # opaque
|
47
111
|
query,
|
48
|
-
m["fragment"
|
112
|
+
m["fragment"]
|
49
113
|
]
|
50
114
|
end
|
51
115
|
elsif m = RFC3986_relative_ref.match(uri)
|
52
116
|
[ nil, # scheme
|
53
|
-
m["userinfo"
|
54
|
-
m["host"
|
55
|
-
m["port"
|
117
|
+
m["userinfo"],
|
118
|
+
m["host"],
|
119
|
+
m["port"],
|
56
120
|
nil, # registry,
|
57
|
-
(m["path-abempty"
|
58
|
-
m["path-absolute"
|
59
|
-
m["path-noscheme"
|
60
|
-
m["path-empty"
|
121
|
+
(m["path-abempty"] ||
|
122
|
+
m["path-absolute"] ||
|
123
|
+
m["path-noscheme"] ||
|
124
|
+
m["path-empty"]),
|
61
125
|
nil, # opaque
|
62
|
-
m["query"
|
63
|
-
m["fragment"
|
126
|
+
m["query"],
|
127
|
+
m["fragment"]
|
64
128
|
]
|
65
129
|
else
|
66
130
|
raise InvalidURIError, "bad URI(is not URI?): #{uri.inspect}"
|
@@ -92,14 +156,14 @@ module URI
|
|
92
156
|
|
93
157
|
def default_regexp # :nodoc:
|
94
158
|
{
|
95
|
-
SCHEME:
|
96
|
-
USERINFO:
|
97
|
-
HOST:
|
98
|
-
ABS_PATH:
|
99
|
-
REL_PATH:
|
100
|
-
QUERY:
|
101
|
-
FRAGMENT:
|
102
|
-
OPAQUE:
|
159
|
+
SCHEME: %r[\A#{SCHEME}\z]o,
|
160
|
+
USERINFO: %r[\A#{USERINFO}\z]o,
|
161
|
+
HOST: %r[\A#{HOST}\z]o,
|
162
|
+
ABS_PATH: %r[\A/#{SEG}*+\z]o,
|
163
|
+
REL_PATH: %r[\A(?!/)#{SEG}++\z]o,
|
164
|
+
QUERY: %r[\A(?:%\h\h|[!$&-.0-9:;=@A-Z_a-z~/?])*+\z],
|
165
|
+
FRAGMENT: %r[\A#{FRAGMENT}\z]o,
|
166
|
+
OPAQUE: %r[\A(?:[^/].*)?\z],
|
103
167
|
PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
|
104
168
|
}
|
105
169
|
end
|
data/lib/uri/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
task :sync_tool, [:from] do |t, from: nil|
|
2
|
+
from ||= (File.identical?(__dir__, "rakelib") ? "../ruby/tool" : File.dirname(__dir__))
|
3
|
+
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
{
|
7
|
+
"rakelib/sync_tool.rake" => "rakelib",
|
8
|
+
"lib/core_assertions.rb" => "test/lib",
|
9
|
+
"lib/envutil.rb" => "test/lib",
|
10
|
+
"lib/find_executable.rb" => "test/lib",
|
11
|
+
"lib/helper.rb" => "test/lib",
|
12
|
+
}.each do |src, dest|
|
13
|
+
FileUtils.mkpath(dest)
|
14
|
+
FileUtils.cp "#{from}/#{src}", dest
|
15
|
+
rescue Errno::ENOENT
|
16
|
+
end
|
17
|
+
end
|
data/uri.gemspec
CHANGED
@@ -12,18 +12,26 @@ Gem::Specification.new do |spec|
|
|
12
12
|
|
13
13
|
spec.summary = %q{URI is a module providing classes to handle Uniform Resource Identifiers}
|
14
14
|
spec.description = spec.summary
|
15
|
-
|
15
|
+
|
16
|
+
github_link = "https://github.com/ruby/uri"
|
17
|
+
|
18
|
+
spec.homepage = github_link
|
16
19
|
spec.licenses = ["Ruby", "BSD-2-Clause"]
|
17
20
|
|
18
|
-
spec.required_ruby_version = '>= 2.
|
21
|
+
spec.required_ruby_version = '>= 2.5'
|
19
22
|
|
20
|
-
spec.metadata
|
21
|
-
|
23
|
+
spec.metadata = {
|
24
|
+
"bug_tracker_uri" => "#{github_link}/issues",
|
25
|
+
"changelog_uri" => "#{github_link}/releases",
|
26
|
+
"documentation_uri" => "https://ruby.github.io/uri/",
|
27
|
+
"homepage_uri" => spec.homepage,
|
28
|
+
"source_code_uri" => github_link
|
29
|
+
}
|
22
30
|
|
23
31
|
# Specify which files should be added to the gem when it is released.
|
24
32
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
33
|
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
26
|
-
`git ls-files -z 2
|
34
|
+
`git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
35
|
end
|
28
36
|
spec.bindir = "exe"
|
29
37
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akira Yamada
|
@@ -17,6 +17,7 @@ extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
18
18
|
files:
|
19
19
|
- ".github/dependabot.yml"
|
20
|
+
- ".github/workflows/gh-pages.yml"
|
20
21
|
- ".github/workflows/test.yml"
|
21
22
|
- ".gitignore"
|
22
23
|
- Gemfile
|
@@ -40,12 +41,16 @@ files:
|
|
40
41
|
- lib/uri/version.rb
|
41
42
|
- lib/uri/ws.rb
|
42
43
|
- lib/uri/wss.rb
|
44
|
+
- rakelib/sync_tool.rake
|
43
45
|
- uri.gemspec
|
44
46
|
homepage: https://github.com/ruby/uri
|
45
47
|
licenses:
|
46
48
|
- Ruby
|
47
49
|
- BSD-2-Clause
|
48
50
|
metadata:
|
51
|
+
bug_tracker_uri: https://github.com/ruby/uri/issues
|
52
|
+
changelog_uri: https://github.com/ruby/uri/releases
|
53
|
+
documentation_uri: https://ruby.github.io/uri/
|
49
54
|
homepage_uri: https://github.com/ruby/uri
|
50
55
|
source_code_uri: https://github.com/ruby/uri
|
51
56
|
rdoc_options: []
|
@@ -55,7 +60,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
60
|
requirements:
|
56
61
|
- - ">="
|
57
62
|
- !ruby/object:Gem::Version
|
58
|
-
version: '2.
|
63
|
+
version: '2.5'
|
59
64
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
65
|
requirements:
|
61
66
|
- - ">="
|