uri 0.12.1 → 0.13.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 +4 -4
- data/.github/workflows/gh-pages.yml +46 -0
- data/.github/workflows/test.yml +9 -3
- data/.gitignore +1 -0
- data/Gemfile +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/rfc2396_parser.rb +2 -2
- data/lib/uri/rfc3986_parser.rb +96 -32
- data/lib/uri/version.rb +1 -1
- data/rakelib/sync_tool.rake +17 -0
- data/uri.gemspec +13 -5
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8f4eaea3d45b9a860a4a1765dfa211d195929e01ea90e2ff25405fea90948098
|
4
|
+
data.tar.gz: 5f962ae3a2b0c56f589df823edf89560420d8c2dced50ac7332e5a6322a772bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fb0be9745374a552f34d58d834e206adabc9a81bfc15bc7179c4143b639f0f62dd73ab46637023147e10be72b61ffdb2b18ac32a697d185244026a51560dc54
|
7
|
+
data.tar.gz: 6961a3339bfa178cd339a14828cbb4be6d79249fc1d262da0ea7d68095435efe801ef71642866ab0de2e7a5edc759a168e8b54a006f038e446d755c9781dbf49
|
@@ -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,19 +3,25 @@ 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
|
runs-on: ${{ matrix.os }}
|
13
19
|
steps:
|
14
|
-
- uses: actions/checkout@
|
20
|
+
- uses: actions/checkout@v4
|
15
21
|
- name: Set up Ruby
|
16
22
|
uses: ruby/setup-ruby@v1
|
17
23
|
with:
|
18
24
|
ruby-version: ${{ matrix.ruby }}
|
19
|
-
|
25
|
+
- run: bundle install --jobs 4 --retry 3
|
20
26
|
- name: Run test
|
21
27
|
run: rake test
|
data/.gitignore
CHANGED
data/Gemfile
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
@@ -68,16 +68,32 @@ module URI
|
|
68
68
|
end
|
69
69
|
private_constant :Schemes
|
70
70
|
|
71
|
+
# Registers the given +klass+ as the class to be instantiated
|
72
|
+
# when parsing a \URI with the given +scheme+:
|
71
73
|
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
# can be registered (no -/+/. allowed).
|
74
|
+
# URI.register_scheme('MS_SEARCH', URI::Generic) # => URI::Generic
|
75
|
+
# URI.scheme_list['MS_SEARCH'] # => URI::Generic
|
75
76
|
#
|
77
|
+
# Note that after calling String#upcase on +scheme+, it must be a valid
|
78
|
+
# constant name.
|
76
79
|
def self.register_scheme(scheme, klass)
|
77
80
|
Schemes.const_set(scheme.to_s.upcase, klass)
|
78
81
|
end
|
79
82
|
|
80
|
-
# Returns a
|
83
|
+
# Returns a hash of the defined schemes:
|
84
|
+
#
|
85
|
+
# URI.scheme_list
|
86
|
+
# # =>
|
87
|
+
# {"MAILTO"=>URI::MailTo,
|
88
|
+
# "LDAPS"=>URI::LDAPS,
|
89
|
+
# "WS"=>URI::WS,
|
90
|
+
# "HTTP"=>URI::HTTP,
|
91
|
+
# "HTTPS"=>URI::HTTPS,
|
92
|
+
# "LDAP"=>URI::LDAP,
|
93
|
+
# "FILE"=>URI::File,
|
94
|
+
# "FTP"=>URI::FTP}
|
95
|
+
#
|
96
|
+
# Related: URI.register_scheme.
|
81
97
|
def self.scheme_list
|
82
98
|
Schemes.constants.map { |name|
|
83
99
|
[name.to_s.upcase, Schemes.const_get(name)]
|
@@ -88,9 +104,21 @@ module URI
|
|
88
104
|
private_constant :INITIAL_SCHEMES
|
89
105
|
Ractor.make_shareable(INITIAL_SCHEMES) if defined?(Ractor)
|
90
106
|
|
107
|
+
# Returns a new object constructed from the given +scheme+, +arguments+,
|
108
|
+
# and +default+:
|
109
|
+
#
|
110
|
+
# - The new object is an instance of <tt>URI.scheme_list[scheme.upcase]</tt>.
|
111
|
+
# - The object is initialized by calling the class initializer
|
112
|
+
# using +scheme+ and +arguments+.
|
113
|
+
# See URI::Generic.new.
|
114
|
+
#
|
115
|
+
# Examples:
|
91
116
|
#
|
92
|
-
#
|
93
|
-
#
|
117
|
+
# values = ['john.doe', 'www.example.com', '123', nil, '/forum/questions/', nil, 'tag=networking&order=newest', 'top']
|
118
|
+
# URI.for('https', *values)
|
119
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
120
|
+
# URI.for('foo', *values, default: URI::HTTP)
|
121
|
+
# # => #<URI::HTTP foo://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
94
122
|
#
|
95
123
|
def self.for(scheme, *arguments, default: Generic)
|
96
124
|
const_name = scheme.to_s.upcase
|
@@ -121,95 +149,49 @@ module URI
|
|
121
149
|
#
|
122
150
|
class BadURIError < Error; end
|
123
151
|
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
133
|
-
#
|
134
|
-
#
|
135
|
-
#
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
#
|
141
|
-
# * Port
|
142
|
-
# * Registry
|
143
|
-
# * Path
|
144
|
-
# * Opaque
|
145
|
-
# * Query
|
146
|
-
# * Fragment
|
147
|
-
#
|
148
|
-
# == Usage
|
149
|
-
#
|
150
|
-
# require 'uri'
|
151
|
-
#
|
152
|
-
# URI.split("http://www.ruby-lang.org/")
|
153
|
-
# # => ["http", nil, "www.ruby-lang.org", nil, nil, "/", nil, nil, nil]
|
152
|
+
# Returns a 9-element array representing the parts of the \URI
|
153
|
+
# formed from the string +uri+;
|
154
|
+
# each array element is a string or +nil+:
|
155
|
+
#
|
156
|
+
# names = %w[scheme userinfo host port registry path opaque query fragment]
|
157
|
+
# values = URI.split('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
158
|
+
# names.zip(values)
|
159
|
+
# # =>
|
160
|
+
# [["scheme", "https"],
|
161
|
+
# ["userinfo", "john.doe"],
|
162
|
+
# ["host", "www.example.com"],
|
163
|
+
# ["port", "123"],
|
164
|
+
# ["registry", nil],
|
165
|
+
# ["path", "/forum/questions/"],
|
166
|
+
# ["opaque", nil],
|
167
|
+
# ["query", "tag=networking&order=newest"],
|
168
|
+
# ["fragment", "top"]]
|
154
169
|
#
|
155
170
|
def self.split(uri)
|
156
171
|
RFC3986_PARSER.split(uri)
|
157
172
|
end
|
158
173
|
|
174
|
+
# Returns a new \URI object constructed from the given string +uri+:
|
159
175
|
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
# URI
|
163
|
-
#
|
164
|
-
# == Args
|
165
|
-
#
|
166
|
-
# +uri_str+::
|
167
|
-
# String with URI.
|
168
|
-
#
|
169
|
-
# == Description
|
170
|
-
#
|
171
|
-
# Creates one of the URI's subclasses instance from the string.
|
172
|
-
#
|
173
|
-
# == Raises
|
174
|
-
#
|
175
|
-
# URI::InvalidURIError::
|
176
|
-
# Raised if URI given is not a correct one.
|
176
|
+
# URI.parse('https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
177
|
+
# # => #<URI::HTTPS https://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
178
|
+
# URI.parse('http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top')
|
179
|
+
# # => #<URI::HTTP http://john.doe@www.example.com:123/forum/questions/?tag=networking&order=newest#top>
|
177
180
|
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
# require 'uri'
|
181
|
-
#
|
182
|
-
# uri = URI.parse("http://www.ruby-lang.org/")
|
183
|
-
# # => #<URI::HTTP http://www.ruby-lang.org/>
|
184
|
-
# uri.scheme
|
185
|
-
# # => "http"
|
186
|
-
# uri.host
|
187
|
-
# # => "www.ruby-lang.org"
|
188
|
-
#
|
189
|
-
# It's recommended to first ::escape the provided +uri_str+ if there are any
|
190
|
-
# invalid URI characters.
|
181
|
+
# It's recommended to first ::escape string +uri+
|
182
|
+
# if it may contain invalid URI characters.
|
191
183
|
#
|
192
184
|
def self.parse(uri)
|
193
185
|
RFC3986_PARSER.parse(uri)
|
194
186
|
end
|
195
187
|
|
188
|
+
# Merges the given URI strings +str+
|
189
|
+
# per {RFC 2396}[https://www.rfc-editor.org/rfc/rfc2396.html].
|
196
190
|
#
|
197
|
-
#
|
198
|
-
#
|
199
|
-
# URI::join(str[, str, ...])
|
191
|
+
# Each string in +str+ is converted to an
|
192
|
+
# {RFC3986 URI}[https://www.rfc-editor.org/rfc/rfc3986.html] before being merged.
|
200
193
|
#
|
201
|
-
#
|
202
|
-
#
|
203
|
-
# +str+::
|
204
|
-
# String(s) to work with, will be converted to RFC3986 URIs before merging.
|
205
|
-
#
|
206
|
-
# == Description
|
207
|
-
#
|
208
|
-
# Joins URIs.
|
209
|
-
#
|
210
|
-
# == Usage
|
211
|
-
#
|
212
|
-
# require 'uri'
|
194
|
+
# Examples:
|
213
195
|
#
|
214
196
|
# URI.join("http://example.com/","main.rbx")
|
215
197
|
# # => #<URI::HTTP http://example.com/main.rbx>
|
@@ -254,7 +236,7 @@ module URI
|
|
254
236
|
# URI.extract("text here http://foo.example.org/bla and here mailto:test@example.com and here also.")
|
255
237
|
# # => ["http://foo.example.com/bla", "mailto:test@example.com"]
|
256
238
|
#
|
257
|
-
def self.extract(str, schemes = nil, &block)
|
239
|
+
def self.extract(str, schemes = nil, &block) # :nodoc:
|
258
240
|
warn "URI.extract is obsolete", uplevel: 1 if $VERBOSE
|
259
241
|
DEFAULT_PARSER.extract(str, schemes, &block)
|
260
242
|
end
|
@@ -291,7 +273,7 @@ module URI
|
|
291
273
|
# p $&
|
292
274
|
# end
|
293
275
|
#
|
294
|
-
def self.regexp(schemes = nil)
|
276
|
+
def self.regexp(schemes = nil)# :nodoc:
|
295
277
|
warn "URI.regexp is obsolete", uplevel: 1 if $VERBOSE
|
296
278
|
DEFAULT_PARSER.make_regexp(schemes)
|
297
279
|
end
|
@@ -314,40 +296,86 @@ module URI
|
|
314
296
|
TBLDECWWWCOMP_['+'] = ' '
|
315
297
|
TBLDECWWWCOMP_.freeze
|
316
298
|
|
317
|
-
#
|
299
|
+
# Returns a URL-encoded string derived from the given string +str+.
|
300
|
+
#
|
301
|
+
# The returned string:
|
302
|
+
#
|
303
|
+
# - Preserves:
|
304
|
+
#
|
305
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
306
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
307
|
+
# and <tt>'0'..'9'</tt>.
|
308
|
+
#
|
309
|
+
# Example:
|
318
310
|
#
|
319
|
-
#
|
320
|
-
#
|
311
|
+
# URI.encode_www_form_component('*.-_azAZ09')
|
312
|
+
# # => "*.-_azAZ09"
|
321
313
|
#
|
322
|
-
#
|
314
|
+
# - Converts:
|
323
315
|
#
|
324
|
-
#
|
325
|
-
#
|
316
|
+
# - Character <tt>' '</tt> to character <tt>'+'</tt>.
|
317
|
+
# - Any other character to "percent notation";
|
318
|
+
# the percent notation for character <i>c</i> is <tt>'%%%X' % c.ord</tt>.
|
326
319
|
#
|
327
|
-
#
|
320
|
+
# Example:
|
321
|
+
#
|
322
|
+
# URI.encode_www_form_component('Here are some punctuation characters: ,;?:')
|
323
|
+
# # => "Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A"
|
324
|
+
#
|
325
|
+
# Encoding:
|
326
|
+
#
|
327
|
+
# - If +str+ has encoding Encoding::ASCII_8BIT, argument +enc+ is ignored.
|
328
|
+
# - Otherwise +str+ is converted first to Encoding::UTF_8
|
329
|
+
# (with suitable character replacements),
|
330
|
+
# and then to encoding +enc+.
|
331
|
+
#
|
332
|
+
# In either case, the returned string has forced encoding Encoding::US_ASCII.
|
333
|
+
#
|
334
|
+
# Related: URI.encode_uri_component (encodes <tt>' '</tt> as <tt>'%20'</tt>).
|
328
335
|
def self.encode_www_form_component(str, enc=nil)
|
329
336
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCWWWCOMP_, str, enc)
|
330
337
|
end
|
331
338
|
|
332
|
-
#
|
339
|
+
# Returns a string decoded from the given \URL-encoded string +str+.
|
340
|
+
#
|
341
|
+
# The given string is first encoded as Encoding::ASCII-8BIT (using String#b),
|
342
|
+
# then decoded (as below), and finally force-encoded to the given encoding +enc+.
|
343
|
+
#
|
344
|
+
# The returned string:
|
345
|
+
#
|
346
|
+
# - Preserves:
|
347
|
+
#
|
348
|
+
# - Characters <tt>'*'</tt>, <tt>'.'</tt>, <tt>'-'</tt>, and <tt>'_'</tt>.
|
349
|
+
# - Character in ranges <tt>'a'..'z'</tt>, <tt>'A'..'Z'</tt>,
|
350
|
+
# and <tt>'0'..'9'</tt>.
|
351
|
+
#
|
352
|
+
# Example:
|
353
|
+
#
|
354
|
+
# URI.decode_www_form_component('*.-_azAZ09')
|
355
|
+
# # => "*.-_azAZ09"
|
356
|
+
#
|
357
|
+
# - Converts:
|
358
|
+
#
|
359
|
+
# - Character <tt>'+'</tt> to character <tt>' '</tt>.
|
360
|
+
# - Each "percent notation" to an ASCII character.
|
333
361
|
#
|
334
|
-
#
|
362
|
+
# Example:
|
335
363
|
#
|
336
|
-
#
|
364
|
+
# URI.decode_www_form_component('Here+are+some+punctuation+characters%3A+%2C%3B%3F%3A')
|
365
|
+
# # => "Here are some punctuation characters: ,;?:"
|
366
|
+
#
|
367
|
+
# Related: URI.decode_uri_component (preserves <tt>'+'</tt>).
|
337
368
|
def self.decode_www_form_component(str, enc=Encoding::UTF_8)
|
338
369
|
_decode_uri_component(/\+|%\h\h/, str, enc)
|
339
370
|
end
|
340
371
|
|
341
|
-
#
|
342
|
-
#
|
343
|
-
# This encodes SP to %20 instead of +.
|
372
|
+
# Like URI.encode_www_form_component, except that <tt>' '</tt> (space)
|
373
|
+
# is encoded as <tt>'%20'</tt> (instead of <tt>'+'</tt>).
|
344
374
|
def self.encode_uri_component(str, enc=nil)
|
345
375
|
_encode_uri_component(/[^*\-.0-9A-Z_a-z]/, TBLENCURICOMP_, str, enc)
|
346
376
|
end
|
347
377
|
|
348
|
-
#
|
349
|
-
#
|
350
|
-
# This does not decode + to SP.
|
378
|
+
# Like URI.decode_www_form_component, except that <tt>'+'</tt> is preserved.
|
351
379
|
def self.decode_uri_component(str, enc=Encoding::UTF_8)
|
352
380
|
_decode_uri_component(/%\h\h/, str, enc)
|
353
381
|
end
|
@@ -372,33 +400,104 @@ module URI
|
|
372
400
|
end
|
373
401
|
private_class_method :_decode_uri_component
|
374
402
|
|
375
|
-
#
|
403
|
+
# Returns a URL-encoded string derived from the given
|
404
|
+
# {Enumerable}[https://docs.ruby-lang.org/en/master/Enumerable.html#module-Enumerable-label-Enumerable+in+Ruby+Classes]
|
405
|
+
# +enum+.
|
406
|
+
#
|
407
|
+
# The result is suitable for use as form data
|
408
|
+
# for an \HTTP request whose <tt>Content-Type</tt> is
|
409
|
+
# <tt>'application/x-www-form-urlencoded'</tt>.
|
410
|
+
#
|
411
|
+
# The returned string consists of the elements of +enum+,
|
412
|
+
# each converted to one or more URL-encoded strings,
|
413
|
+
# and all joined with character <tt>'&'</tt>.
|
414
|
+
#
|
415
|
+
# Simple examples:
|
416
|
+
#
|
417
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1], ['baz', 2]])
|
418
|
+
# # => "foo=0&bar=1&baz=2"
|
419
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
420
|
+
# # => "foo=0&bar=1&baz=2"
|
421
|
+
#
|
422
|
+
# The returned string is formed using method URI.encode_www_form_component,
|
423
|
+
# which converts certain characters:
|
424
|
+
#
|
425
|
+
# URI.encode_www_form('f#o': '/', 'b-r': '$', 'b z': '@')
|
426
|
+
# # => "f%23o=%2F&b-r=%24&b+z=%40"
|
427
|
+
#
|
428
|
+
# When +enum+ is Array-like, each element +ele+ is converted to a field:
|
429
|
+
#
|
430
|
+
# - If +ele+ is an array of two or more elements,
|
431
|
+
# the field is formed from its first two elements
|
432
|
+
# (and any additional elements are ignored):
|
433
|
+
#
|
434
|
+
# name = URI.encode_www_form_component(ele[0], enc)
|
435
|
+
# value = URI.encode_www_form_component(ele[1], enc)
|
436
|
+
# "#{name}=#{value}"
|
376
437
|
#
|
377
|
-
#
|
378
|
-
# from given an Enumerable object.
|
438
|
+
# Examples:
|
379
439
|
#
|
380
|
-
#
|
440
|
+
# URI.encode_www_form([%w[foo bar], %w[baz bat bah]])
|
441
|
+
# # => "foo=bar&baz=bat"
|
442
|
+
# URI.encode_www_form([['foo', 0], ['bar', :baz, 'bat']])
|
443
|
+
# # => "foo=0&bar=baz"
|
381
444
|
#
|
382
|
-
#
|
383
|
-
#
|
384
|
-
# encoding or mixed encoding data. (Strings which are encoded in an HTML5
|
385
|
-
# ASCII incompatible encoding are converted to UTF-8.)
|
445
|
+
# - If +ele+ is an array of one element,
|
446
|
+
# the field is formed from <tt>ele[0]</tt>:
|
386
447
|
#
|
387
|
-
#
|
388
|
-
# multipart/form-data.
|
448
|
+
# URI.encode_www_form_component(ele[0])
|
389
449
|
#
|
390
|
-
#
|
450
|
+
# Example:
|
391
451
|
#
|
392
|
-
#
|
393
|
-
#
|
394
|
-
#
|
395
|
-
#
|
396
|
-
#
|
397
|
-
#
|
398
|
-
#
|
399
|
-
#
|
452
|
+
# URI.encode_www_form([['foo'], [:bar], [0]])
|
453
|
+
# # => "foo&bar&0"
|
454
|
+
#
|
455
|
+
# - Otherwise the field is formed from +ele+:
|
456
|
+
#
|
457
|
+
# URI.encode_www_form_component(ele)
|
458
|
+
#
|
459
|
+
# Example:
|
460
|
+
#
|
461
|
+
# URI.encode_www_form(['foo', :bar, 0])
|
462
|
+
# # => "foo&bar&0"
|
463
|
+
#
|
464
|
+
# The elements of an Array-like +enum+ may be mixture:
|
465
|
+
#
|
466
|
+
# URI.encode_www_form([['foo', 0], ['bar', 1, 2], ['baz'], :bat])
|
467
|
+
# # => "foo=0&bar=1&baz&bat"
|
468
|
+
#
|
469
|
+
# When +enum+ is Hash-like,
|
470
|
+
# each +key+/+value+ pair is converted to one or more fields:
|
471
|
+
#
|
472
|
+
# - If +value+ is
|
473
|
+
# {Array-convertible}[https://docs.ruby-lang.org/en/master/implicit_conversion_rdoc.html#label-Array-Convertible+Objects],
|
474
|
+
# each element +ele+ in +value+ is paired with +key+ to form a field:
|
475
|
+
#
|
476
|
+
# name = URI.encode_www_form_component(key, enc)
|
477
|
+
# value = URI.encode_www_form_component(ele, enc)
|
478
|
+
# "#{name}=#{value}"
|
479
|
+
#
|
480
|
+
# Example:
|
481
|
+
#
|
482
|
+
# URI.encode_www_form({foo: [:bar, 1], baz: [:bat, :bam, 2]})
|
483
|
+
# # => "foo=bar&foo=1&baz=bat&baz=bam&baz=2"
|
484
|
+
#
|
485
|
+
# - Otherwise, +key+ and +value+ are paired to form a field:
|
486
|
+
#
|
487
|
+
# name = URI.encode_www_form_component(key, enc)
|
488
|
+
# value = URI.encode_www_form_component(value, enc)
|
489
|
+
# "#{name}=#{value}"
|
490
|
+
#
|
491
|
+
# Example:
|
492
|
+
#
|
493
|
+
# URI.encode_www_form({foo: 0, bar: 1, baz: 2})
|
494
|
+
# # => "foo=0&bar=1&baz=2"
|
495
|
+
#
|
496
|
+
# The elements of a Hash-like +enum+ may be mixture:
|
497
|
+
#
|
498
|
+
# URI.encode_www_form({foo: [0, 1], bar: 2})
|
499
|
+
# # => "foo=0&foo=1&bar=2"
|
400
500
|
#
|
401
|
-
# See URI.encode_www_form_component, URI.decode_www_form.
|
402
501
|
def self.encode_www_form(enum, enc=nil)
|
403
502
|
enum.map do |k,v|
|
404
503
|
if v.nil?
|
@@ -419,22 +518,39 @@ module URI
|
|
419
518
|
end.join('&')
|
420
519
|
end
|
421
520
|
|
422
|
-
#
|
521
|
+
# Returns name/value pairs derived from the given string +str+,
|
522
|
+
# which must be an ASCII string.
|
523
|
+
#
|
524
|
+
# The method may be used to decode the body of Net::HTTPResponse object +res+
|
525
|
+
# for which <tt>res['Content-Type']</tt> is <tt>'application/x-www-form-urlencoded'</tt>.
|
526
|
+
#
|
527
|
+
# The returned data is an array of 2-element subarrays;
|
528
|
+
# each subarray is a name/value pair (both are strings).
|
529
|
+
# Each returned string has encoding +enc+,
|
530
|
+
# and has had invalid characters removed via
|
531
|
+
# {String#scrub}[https://docs.ruby-lang.org/en/master/String.html#method-i-scrub].
|
423
532
|
#
|
424
|
-
#
|
425
|
-
# and returns an array of key-value arrays.
|
533
|
+
# A simple example:
|
426
534
|
#
|
427
|
-
#
|
428
|
-
#
|
535
|
+
# URI.decode_www_form('foo=0&bar=1&baz')
|
536
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
429
537
|
#
|
430
|
-
#
|
431
|
-
#
|
432
|
-
#
|
433
|
-
#
|
434
|
-
#
|
435
|
-
#
|
538
|
+
# The returned strings have certain conversions,
|
539
|
+
# similar to those performed in URI.decode_www_form_component:
|
540
|
+
#
|
541
|
+
# URI.decode_www_form('f%23o=%2F&b-r=%24&b+z=%40')
|
542
|
+
# # => [["f#o", "/"], ["b-r", "$"], ["b z", "@"]]
|
543
|
+
#
|
544
|
+
# The given string may contain consecutive separators:
|
545
|
+
#
|
546
|
+
# URI.decode_www_form('foo=0&&bar=1&&baz=2')
|
547
|
+
# # => [["foo", "0"], ["", ""], ["bar", "1"], ["", ""], ["baz", "2"]]
|
548
|
+
#
|
549
|
+
# A different separator may be specified:
|
550
|
+
#
|
551
|
+
# URI.decode_www_form('foo=0--bar=1--baz', separator: '--')
|
552
|
+
# # => [["foo", "0"], ["bar", "1"], ["baz", ""]]
|
436
553
|
#
|
437
|
-
# See URI.decode_www_form_component, URI.encode_www_form.
|
438
554
|
def self.decode_www_form(str, enc=Encoding::UTF_8, separator: '&', use__charset_: false, isindex: false)
|
439
555
|
raise ArgumentError, "the input of #{self.name}.#{__method__} must be ASCII only string" unless str.ascii_only?
|
440
556
|
ary = []
|
@@ -713,7 +829,15 @@ end # module URI
|
|
713
829
|
module Kernel
|
714
830
|
|
715
831
|
#
|
716
|
-
# Returns
|
832
|
+
# Returns a \URI object derived from the given +uri+,
|
833
|
+
# which may be a \URI string or an existing \URI object:
|
834
|
+
#
|
835
|
+
# # Returns a new URI.
|
836
|
+
# uri = URI('http://github.com/ruby/ruby')
|
837
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
838
|
+
# # Returns the given URI.
|
839
|
+
# URI(uri)
|
840
|
+
# # => #<URI::HTTP http://github.com/ruby/ruby>
|
717
841
|
#
|
718
842
|
def URI(uri)
|
719
843
|
if uri.is_a?(URI::Generic)
|
data/lib/uri/generic.rb
CHANGED
data/lib/uri/rfc2396_parser.rb
CHANGED
@@ -497,8 +497,8 @@ module URI
|
|
497
497
|
ret = {}
|
498
498
|
|
499
499
|
# for URI::split
|
500
|
-
ret[:ABS_URI] = Regexp.new('\A\s
|
501
|
-
ret[:REL_URI] = Regexp.new('\A\s
|
500
|
+
ret[:ABS_URI] = Regexp.new('\A\s*+' + pattern[:X_ABS_URI] + '\s*\z', Regexp::EXTENDED)
|
501
|
+
ret[:REL_URI] = Regexp.new('\A\s*+' + pattern[:X_REL_URI] + '\s*\z', Regexp::EXTENDED)
|
502
502
|
|
503
503
|
# for URI::extract
|
504
504
|
ret[:URI_REF] = Regexp.new(pattern[:URI_REF])
|
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,15 +156,15 @@ 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:
|
103
|
-
PORT: /\A[\x09\x0a\x0c\x0d ]
|
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],
|
167
|
+
PORT: /\A[\x09\x0a\x0c\x0d ]*+\d*[\x09\x0a\x0c\x0d ]*\z/,
|
104
168
|
}
|
105
169
|
end
|
106
170
|
|
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,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.13.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Akira Yamada
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-11-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: URI is a module providing classes to handle Uniform Resource Identifiers
|
14
14
|
email:
|
@@ -18,6 +18,7 @@ extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- ".github/dependabot.yml"
|
21
|
+
- ".github/workflows/gh-pages.yml"
|
21
22
|
- ".github/workflows/test.yml"
|
22
23
|
- ".gitignore"
|
23
24
|
- Gemfile
|
@@ -41,12 +42,16 @@ files:
|
|
41
42
|
- lib/uri/version.rb
|
42
43
|
- lib/uri/ws.rb
|
43
44
|
- lib/uri/wss.rb
|
45
|
+
- rakelib/sync_tool.rake
|
44
46
|
- uri.gemspec
|
45
47
|
homepage: https://github.com/ruby/uri
|
46
48
|
licenses:
|
47
49
|
- Ruby
|
48
50
|
- BSD-2-Clause
|
49
51
|
metadata:
|
52
|
+
bug_tracker_uri: https://github.com/ruby/uri/issues
|
53
|
+
changelog_uri: https://github.com/ruby/uri/releases
|
54
|
+
documentation_uri: https://ruby.github.io/uri/
|
50
55
|
homepage_uri: https://github.com/ruby/uri
|
51
56
|
source_code_uri: https://github.com/ruby/uri
|
52
57
|
post_install_message:
|
@@ -57,7 +62,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
57
62
|
requirements:
|
58
63
|
- - ">="
|
59
64
|
- !ruby/object:Gem::Version
|
60
|
-
version: '2.
|
65
|
+
version: '2.5'
|
61
66
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
67
|
requirements:
|
63
68
|
- - ">="
|