addressable 2.6.0 → 2.8.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/CHANGELOG.md +19 -0
- data/Gemfile +13 -17
- data/README.md +12 -10
- data/Rakefile +3 -3
- data/addressable.gemspec +37 -0
- data/lib/addressable/idna/pure.rb +52 -50
- data/lib/addressable/template.rb +25 -39
- data/lib/addressable/uri.rb +80 -34
- data/lib/addressable/version.rb +1 -1
- data/spec/addressable/idna_spec.rb +3 -1
- data/spec/addressable/template_spec.rb +9 -0
- data/spec/addressable/uri_spec.rb +327 -207
- data/spec/spec_helper.rb +9 -0
- data/tasks/gem.rake +6 -7
- data/tasks/profile.rake +72 -0
- data/tasks/rspec.rake +1 -1
- metadata +10 -10
- data/spec/addressable/rack_mount_compat_spec.rb +0 -106
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 03a21b1eab156a16e90bd7963af85980edfbddc8f3dbe052766303dba76cc000
|
4
|
+
data.tar.gz: 03eca5d86f4c70f9320000f36e3cff4fd8023342a4e0ac855d0ef1ec89ee6183
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d504f9475ad823f5bb077b9c039a2c91c83e52c20896247a7289b61725c61b1ddefe8ae06155fb018fc67087cf04276081b42105a18394b45e2374ad0b2fadb0
|
7
|
+
data.tar.gz: b81766fbcb9335d5ca94403b62d3b2a6fae31b66cd3c05f48e1885eaf07883bfa1321b6930271fe1415135aec687af51312a26ce27bd4b83b2ac6424dec597c9
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
# Addressable 2.8.0
|
2
|
+
- fixes ReDoS vulnerability in Addressable::Template#match
|
3
|
+
- no longer replaces `+` with spaces in queries for non-http(s) schemes
|
4
|
+
- fixed encoding ipv6 literals
|
5
|
+
- the `:compacted` flag for `normalized_query` now dedupes parameters
|
6
|
+
- fix broken `escape_component` alias
|
7
|
+
- dropping support for Ruby 2.0 and 2.1
|
8
|
+
- adding Ruby 3.0 compatibility for development tasks
|
9
|
+
- drop support for `rack-mount` and remove Addressable::Template#generate
|
10
|
+
- performance improvements
|
11
|
+
- switch CI/CD to GitHub Actions
|
12
|
+
|
13
|
+
# Addressable 2.7.0
|
14
|
+
- added `:compacted` flag to `normalized_query`
|
15
|
+
- `heuristic_parse` handles `mailto:` more intuitively
|
16
|
+
- dropped explicit support for JRuby 9.0.5.0
|
17
|
+
- compatibility w/ public_suffix 4.x
|
18
|
+
- performance improvements
|
19
|
+
|
1
20
|
# Addressable 2.6.0
|
2
21
|
- added `tld=` method to allow assignment to the public suffix
|
3
22
|
- most `heuristic_parse` patterns are now case-insensitive
|
data/Gemfile
CHANGED
@@ -1,10 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
|
-
gemspec
|
5
|
+
gemspec(path: __FILE__ == "(eval)" ? ".." : ".")
|
4
6
|
|
5
7
|
group :test do
|
6
|
-
gem 'rspec', '~> 3.
|
7
|
-
gem 'rspec-its', '~> 1.
|
8
|
+
gem 'rspec', '~> 3.8'
|
9
|
+
gem 'rspec-its', '~> 1.3'
|
10
|
+
end
|
11
|
+
|
12
|
+
group :coverage do
|
13
|
+
gem "coveralls", "> 0.7", require: false, platforms: :mri
|
14
|
+
gem "simplecov", require: false
|
8
15
|
end
|
9
16
|
|
10
17
|
group :development do
|
@@ -14,19 +21,8 @@ group :development do
|
|
14
21
|
end
|
15
22
|
|
16
23
|
group :test, :development do
|
17
|
-
gem '
|
18
|
-
gem
|
19
|
-
gem 'coveralls', :require => false, :platforms => [
|
20
|
-
:ruby_20, :ruby_21, :ruby_22, :ruby_23
|
21
|
-
]
|
22
|
-
# Used to test compatibility.
|
23
|
-
gem 'rack-mount', git: 'https://github.com/sporkmonger/rack-mount.git', require: 'rack/mount'
|
24
|
-
|
25
|
-
if RUBY_VERSION.start_with?('2.0', '2.1')
|
26
|
-
gem 'rack', '< 2', :require => false
|
27
|
-
else
|
28
|
-
gem 'rack', :require => false
|
29
|
-
end
|
24
|
+
gem 'memory_profiler'
|
25
|
+
gem "rake", ">= 12.3.3"
|
30
26
|
end
|
31
27
|
|
32
|
-
gem
|
28
|
+
gem "idn-ruby", platform: :mri
|
data/README.md
CHANGED
@@ -7,21 +7,23 @@
|
|
7
7
|
<dt>License</dt><dd>Apache 2.0</dd>
|
8
8
|
</dl>
|
9
9
|
|
10
|
-
[][gem]
|
11
|
+
[][actions]
|
12
12
|
[][coveralls]
|
13
|
-
[][inch]
|
14
14
|
|
15
15
|
[gem]: https://rubygems.org/gems/addressable
|
16
|
-
[
|
16
|
+
[actions]: https://github.com/sporkmonger/addressable/actions
|
17
17
|
[coveralls]: https://coveralls.io/r/sporkmonger/addressable
|
18
|
-
[inch]:
|
18
|
+
[inch]: https://inch-ci.org/github/sporkmonger/addressable
|
19
19
|
|
20
20
|
# Description
|
21
21
|
|
22
|
-
Addressable is
|
23
|
-
Ruby's standard library. It
|
24
|
-
|
22
|
+
Addressable is an alternative implementation to the URI implementation
|
23
|
+
that is part of Ruby's standard library. It is flexible, offers heuristic
|
24
|
+
parsing, and additionally provides extensive support for IRIs and URI templates.
|
25
|
+
|
26
|
+
Addressable closely conforms to RFC 3986, RFC 3987, and RFC 6570 (level 4).
|
25
27
|
|
26
28
|
# Reference
|
27
29
|
|
@@ -96,7 +98,7 @@ You may optionally turn on native IDN support by installing libidn and the
|
|
96
98
|
idn gem:
|
97
99
|
|
98
100
|
```console
|
99
|
-
$ sudo apt-get install
|
101
|
+
$ sudo apt-get install libidn11-dev # Debian/Ubuntu
|
100
102
|
$ brew install libidn # OS X
|
101
103
|
$ gem install idn-ruby
|
102
104
|
```
|
@@ -108,7 +110,7 @@ dependency using a pessimistic version constraint covering the major and minor
|
|
108
110
|
values:
|
109
111
|
|
110
112
|
```ruby
|
111
|
-
spec.add_dependency 'addressable', '~> 2.
|
113
|
+
spec.add_dependency 'addressable', '~> 2.7'
|
112
114
|
```
|
113
115
|
|
114
116
|
If you need a specific bug fix, you can also specify minimum tiny versions
|
data/Rakefile
CHANGED
@@ -14,9 +14,9 @@ RELEASE_NAME = "REL #{PKG_VERSION}"
|
|
14
14
|
|
15
15
|
PKG_SUMMARY = "URI Implementation"
|
16
16
|
PKG_DESCRIPTION = <<-TEXT
|
17
|
-
Addressable is
|
18
|
-
Ruby's standard library. It
|
19
|
-
|
17
|
+
Addressable is an alternative implementation to the URI implementation that is
|
18
|
+
part of Ruby's standard library. It is flexible, offers heuristic parsing, and
|
19
|
+
additionally provides extensive support for IRIs and URI templates.
|
20
20
|
TEXT
|
21
21
|
|
22
22
|
PKG_FILES = FileList[
|
data/addressable.gemspec
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# stub: addressable 2.8.0 ruby lib
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "addressable".freeze
|
6
|
+
s.version = "2.8.0"
|
7
|
+
|
8
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
9
|
+
s.require_paths = ["lib".freeze]
|
10
|
+
s.authors = ["Bob Aman".freeze]
|
11
|
+
s.date = "2021-07-03"
|
12
|
+
s.description = "Addressable is an alternative implementation to the URI implementation that is\npart of Ruby's standard library. It is flexible, offers heuristic parsing, and\nadditionally provides extensive support for IRIs and URI templates.\n".freeze
|
13
|
+
s.email = "bob@sporkmonger.com".freeze
|
14
|
+
s.extra_rdoc_files = ["README.md".freeze]
|
15
|
+
s.files = ["CHANGELOG.md".freeze, "Gemfile".freeze, "LICENSE.txt".freeze, "README.md".freeze, "Rakefile".freeze, "addressable.gemspec".freeze, "data/unicode.data".freeze, "lib/addressable.rb".freeze, "lib/addressable/idna.rb".freeze, "lib/addressable/idna/native.rb".freeze, "lib/addressable/idna/pure.rb".freeze, "lib/addressable/template.rb".freeze, "lib/addressable/uri.rb".freeze, "lib/addressable/version.rb".freeze, "spec/addressable/idna_spec.rb".freeze, "spec/addressable/net_http_compat_spec.rb".freeze, "spec/addressable/security_spec.rb".freeze, "spec/addressable/template_spec.rb".freeze, "spec/addressable/uri_spec.rb".freeze, "spec/spec_helper.rb".freeze, "tasks/clobber.rake".freeze, "tasks/gem.rake".freeze, "tasks/git.rake".freeze, "tasks/metrics.rake".freeze, "tasks/profile.rake".freeze, "tasks/rspec.rake".freeze, "tasks/yard.rake".freeze]
|
16
|
+
s.homepage = "https://github.com/sporkmonger/addressable".freeze
|
17
|
+
s.licenses = ["Apache-2.0".freeze]
|
18
|
+
s.rdoc_options = ["--main".freeze, "README.md".freeze]
|
19
|
+
s.required_ruby_version = Gem::Requirement.new(">= 2.0".freeze)
|
20
|
+
s.rubygems_version = "3.0.3".freeze
|
21
|
+
s.summary = "URI Implementation".freeze
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
s.specification_version = 4
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_runtime_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
|
28
|
+
s.add_development_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
|
31
|
+
s.add_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
|
32
|
+
end
|
33
|
+
else
|
34
|
+
s.add_dependency(%q<public_suffix>.freeze, [">= 2.0.2", "< 5.0"])
|
35
|
+
s.add_dependency(%q<bundler>.freeze, [">= 1.0", "< 3.0"])
|
36
|
+
end
|
37
|
+
end
|
@@ -135,7 +135,7 @@ module Addressable
|
|
135
135
|
unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) }
|
136
136
|
return unpacked.pack("U*")
|
137
137
|
end
|
138
|
-
|
138
|
+
private_class_method :unicode_downcase
|
139
139
|
|
140
140
|
def self.unicode_compose(unpacked)
|
141
141
|
unpacked_result = []
|
@@ -160,7 +160,7 @@ module Addressable
|
|
160
160
|
unpacked_result << starter
|
161
161
|
return unpacked_result
|
162
162
|
end
|
163
|
-
|
163
|
+
private_class_method :unicode_compose
|
164
164
|
|
165
165
|
def self.unicode_compose_pair(ch_one, ch_two)
|
166
166
|
if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
|
@@ -178,43 +178,45 @@ module Addressable
|
|
178
178
|
end
|
179
179
|
|
180
180
|
p = []
|
181
|
-
ucs4_to_utf8 = lambda do |ch|
|
182
|
-
if ch < 128
|
183
|
-
p << ch
|
184
|
-
elsif ch < 2048
|
185
|
-
p << (ch >> 6 | 192)
|
186
|
-
p << (ch & 63 | 128)
|
187
|
-
elsif ch < 0x10000
|
188
|
-
p << (ch >> 12 | 224)
|
189
|
-
p << (ch >> 6 & 63 | 128)
|
190
|
-
p << (ch & 63 | 128)
|
191
|
-
elsif ch < 0x200000
|
192
|
-
p << (ch >> 18 | 240)
|
193
|
-
p << (ch >> 12 & 63 | 128)
|
194
|
-
p << (ch >> 6 & 63 | 128)
|
195
|
-
p << (ch & 63 | 128)
|
196
|
-
elsif ch < 0x4000000
|
197
|
-
p << (ch >> 24 | 248)
|
198
|
-
p << (ch >> 18 & 63 | 128)
|
199
|
-
p << (ch >> 12 & 63 | 128)
|
200
|
-
p << (ch >> 6 & 63 | 128)
|
201
|
-
p << (ch & 63 | 128)
|
202
|
-
elsif ch < 0x80000000
|
203
|
-
p << (ch >> 30 | 252)
|
204
|
-
p << (ch >> 24 & 63 | 128)
|
205
|
-
p << (ch >> 18 & 63 | 128)
|
206
|
-
p << (ch >> 12 & 63 | 128)
|
207
|
-
p << (ch >> 6 & 63 | 128)
|
208
|
-
p << (ch & 63 | 128)
|
209
|
-
end
|
210
|
-
end
|
211
181
|
|
212
|
-
ucs4_to_utf8
|
213
|
-
ucs4_to_utf8
|
182
|
+
ucs4_to_utf8(ch_one, p)
|
183
|
+
ucs4_to_utf8(ch_two, p)
|
214
184
|
|
215
185
|
return lookup_unicode_composition(p)
|
216
186
|
end
|
217
|
-
|
187
|
+
private_class_method :unicode_compose_pair
|
188
|
+
|
189
|
+
def self.ucs4_to_utf8(char, buffer)
|
190
|
+
if char < 128
|
191
|
+
buffer << char
|
192
|
+
elsif char < 2048
|
193
|
+
buffer << (char >> 6 | 192)
|
194
|
+
buffer << (char & 63 | 128)
|
195
|
+
elsif char < 0x10000
|
196
|
+
buffer << (char >> 12 | 224)
|
197
|
+
buffer << (char >> 6 & 63 | 128)
|
198
|
+
buffer << (char & 63 | 128)
|
199
|
+
elsif char < 0x200000
|
200
|
+
buffer << (char >> 18 | 240)
|
201
|
+
buffer << (char >> 12 & 63 | 128)
|
202
|
+
buffer << (char >> 6 & 63 | 128)
|
203
|
+
buffer << (char & 63 | 128)
|
204
|
+
elsif char < 0x4000000
|
205
|
+
buffer << (char >> 24 | 248)
|
206
|
+
buffer << (char >> 18 & 63 | 128)
|
207
|
+
buffer << (char >> 12 & 63 | 128)
|
208
|
+
buffer << (char >> 6 & 63 | 128)
|
209
|
+
buffer << (char & 63 | 128)
|
210
|
+
elsif char < 0x80000000
|
211
|
+
buffer << (char >> 30 | 252)
|
212
|
+
buffer << (char >> 24 & 63 | 128)
|
213
|
+
buffer << (char >> 18 & 63 | 128)
|
214
|
+
buffer << (char >> 12 & 63 | 128)
|
215
|
+
buffer << (char >> 6 & 63 | 128)
|
216
|
+
buffer << (char & 63 | 128)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
private_class_method :ucs4_to_utf8
|
218
220
|
|
219
221
|
def self.unicode_sort_canonical(unpacked)
|
220
222
|
unpacked = unpacked.dup
|
@@ -238,7 +240,7 @@ module Addressable
|
|
238
240
|
end
|
239
241
|
return unpacked
|
240
242
|
end
|
241
|
-
|
243
|
+
private_class_method :unicode_sort_canonical
|
242
244
|
|
243
245
|
def self.unicode_decompose(unpacked)
|
244
246
|
unpacked_result = []
|
@@ -259,7 +261,7 @@ module Addressable
|
|
259
261
|
end
|
260
262
|
return unpacked_result
|
261
263
|
end
|
262
|
-
|
264
|
+
private_class_method :unicode_decompose
|
263
265
|
|
264
266
|
def self.unicode_decompose_hangul(codepoint)
|
265
267
|
sindex = codepoint - HANGUL_SBASE;
|
@@ -276,7 +278,7 @@ module Addressable
|
|
276
278
|
end
|
277
279
|
return l, v, t
|
278
280
|
end
|
279
|
-
|
281
|
+
private_class_method :unicode_decompose_hangul
|
280
282
|
|
281
283
|
def self.lookup_unicode_combining_class(codepoint)
|
282
284
|
codepoint_data = UNICODE_DATA[codepoint]
|
@@ -284,14 +286,14 @@ module Addressable
|
|
284
286
|
(codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
|
285
287
|
0)
|
286
288
|
end
|
287
|
-
|
289
|
+
private_class_method :lookup_unicode_combining_class
|
288
290
|
|
289
291
|
def self.lookup_unicode_compatibility(codepoint)
|
290
292
|
codepoint_data = UNICODE_DATA[codepoint]
|
291
293
|
(codepoint_data ?
|
292
294
|
codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
|
293
295
|
end
|
294
|
-
|
296
|
+
private_class_method :lookup_unicode_compatibility
|
295
297
|
|
296
298
|
def self.lookup_unicode_lowercase(codepoint)
|
297
299
|
codepoint_data = UNICODE_DATA[codepoint]
|
@@ -299,12 +301,12 @@ module Addressable
|
|
299
301
|
(codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) :
|
300
302
|
codepoint)
|
301
303
|
end
|
302
|
-
|
304
|
+
private_class_method :lookup_unicode_lowercase
|
303
305
|
|
304
306
|
def self.lookup_unicode_composition(unpacked)
|
305
307
|
return COMPOSITION_TABLE[unpacked]
|
306
308
|
end
|
307
|
-
|
309
|
+
private_class_method :lookup_unicode_composition
|
308
310
|
|
309
311
|
HANGUL_SBASE = 0xac00
|
310
312
|
HANGUL_LBASE = 0x1100
|
@@ -341,7 +343,7 @@ module Addressable
|
|
341
343
|
end
|
342
344
|
|
343
345
|
COMPOSITION_TABLE = {}
|
344
|
-
|
346
|
+
UNICODE_DATA.each do |codepoint, data|
|
345
347
|
canonical = data[UNICODE_DATA_CANONICAL]
|
346
348
|
exclusion = data[UNICODE_DATA_EXCLUSION]
|
347
349
|
|
@@ -500,7 +502,7 @@ module Addressable
|
|
500
502
|
|
501
503
|
output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "")
|
502
504
|
end
|
503
|
-
|
505
|
+
private_class_method :punycode_encode
|
504
506
|
|
505
507
|
def self.punycode_decode(punycode)
|
506
508
|
input = []
|
@@ -622,22 +624,22 @@ module Addressable
|
|
622
624
|
|
623
625
|
output.pack("U*")
|
624
626
|
end
|
625
|
-
|
627
|
+
private_class_method :punycode_decode
|
626
628
|
|
627
629
|
def self.punycode_basic?(codepoint)
|
628
630
|
codepoint < 0x80
|
629
631
|
end
|
630
|
-
|
632
|
+
private_class_method :punycode_basic?
|
631
633
|
|
632
634
|
def self.punycode_delimiter?(codepoint)
|
633
635
|
codepoint == PUNYCODE_DELIMITER
|
634
636
|
end
|
635
|
-
|
637
|
+
private_class_method :punycode_delimiter?
|
636
638
|
|
637
639
|
def self.punycode_encode_digit(d)
|
638
640
|
d + 22 + 75 * ((d < 26) ? 1 : 0)
|
639
641
|
end
|
640
|
-
|
642
|
+
private_class_method :punycode_encode_digit
|
641
643
|
|
642
644
|
# Returns the numeric value of a basic codepoint
|
643
645
|
# (for use in representing integers) in the range 0 to
|
@@ -653,7 +655,7 @@ module Addressable
|
|
653
655
|
PUNYCODE_BASE
|
654
656
|
end
|
655
657
|
end
|
656
|
-
|
658
|
+
private_class_method :punycode_decode_digit
|
657
659
|
|
658
660
|
# Bias adaptation method
|
659
661
|
def self.punycode_adapt(delta, numpoints, firsttime)
|
@@ -670,7 +672,7 @@ module Addressable
|
|
670
672
|
|
671
673
|
k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
|
672
674
|
end
|
673
|
-
|
675
|
+
private_class_method :punycode_adapt
|
674
676
|
end
|
675
677
|
# :startdoc:
|
676
678
|
end
|
data/lib/addressable/template.rb
CHANGED
@@ -37,7 +37,7 @@ module Addressable
|
|
37
37
|
Addressable::URI::CharacterClasses::DIGIT + '_'
|
38
38
|
|
39
39
|
var_char =
|
40
|
-
"(
|
40
|
+
"(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
|
41
41
|
RESERVED =
|
42
42
|
"(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])"
|
43
43
|
UNRESERVED =
|
@@ -412,7 +412,7 @@ module Addressable
|
|
412
412
|
# match.captures
|
413
413
|
# #=> ["a", ["b", "c"]]
|
414
414
|
def match(uri, processor=nil)
|
415
|
-
uri = Addressable::URI.parse(uri)
|
415
|
+
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
|
416
416
|
mapping = {}
|
417
417
|
|
418
418
|
# First, we need to process the pattern, and extract the values.
|
@@ -653,40 +653,6 @@ module Addressable
|
|
653
653
|
self.to_regexp.named_captures
|
654
654
|
end
|
655
655
|
|
656
|
-
##
|
657
|
-
# Generates a route result for a given set of parameters.
|
658
|
-
# Should only be used by rack-mount.
|
659
|
-
#
|
660
|
-
# @param params [Hash] The set of parameters used to expand the template.
|
661
|
-
# @param recall [Hash] Default parameters used to expand the template.
|
662
|
-
# @param options [Hash] Either a `:processor` or a `:parameterize` block.
|
663
|
-
#
|
664
|
-
# @api private
|
665
|
-
def generate(params={}, recall={}, options={})
|
666
|
-
merged = recall.merge(params)
|
667
|
-
if options[:processor]
|
668
|
-
processor = options[:processor]
|
669
|
-
elsif options[:parameterize]
|
670
|
-
# TODO: This is sending me into fits trying to shoe-horn this into
|
671
|
-
# the existing API. I think I've got this backwards and processors
|
672
|
-
# should be a set of 4 optional blocks named :validate, :transform,
|
673
|
-
# :match, and :restore. Having to use a singleton here is a huge
|
674
|
-
# code smell.
|
675
|
-
processor = Object.new
|
676
|
-
class <<processor
|
677
|
-
attr_accessor :block
|
678
|
-
def transform(name, value)
|
679
|
-
block.call(name, value)
|
680
|
-
end
|
681
|
-
end
|
682
|
-
processor.block = options[:parameterize]
|
683
|
-
else
|
684
|
-
processor = nil
|
685
|
-
end
|
686
|
-
result = self.expand(merged, processor)
|
687
|
-
result.to_s if result
|
688
|
-
end
|
689
|
-
|
690
656
|
private
|
691
657
|
def ordered_variable_defaults
|
692
658
|
@ordered_variable_defaults ||= begin
|
@@ -973,15 +939,35 @@ module Addressable
|
|
973
939
|
end
|
974
940
|
end
|
975
941
|
|
942
|
+
##
|
943
|
+
# Generates the <tt>Regexp</tt> that parses a template pattern. Memoizes the
|
944
|
+
# value if template processor not set (processors may not be deterministic)
|
945
|
+
#
|
946
|
+
# @param [String] pattern The URI template pattern.
|
947
|
+
# @param [#match] processor The template processor to use.
|
948
|
+
#
|
949
|
+
# @return [Array, Regexp]
|
950
|
+
# An array of expansion variables nad a regular expression which may be
|
951
|
+
# used to parse a template pattern
|
952
|
+
def parse_template_pattern(pattern, processor = nil)
|
953
|
+
if processor.nil? && pattern == @pattern
|
954
|
+
@cached_template_parse ||=
|
955
|
+
parse_new_template_pattern(pattern, processor)
|
956
|
+
else
|
957
|
+
parse_new_template_pattern(pattern, processor)
|
958
|
+
end
|
959
|
+
end
|
960
|
+
|
976
961
|
##
|
977
962
|
# Generates the <tt>Regexp</tt> that parses a template pattern.
|
978
963
|
#
|
979
964
|
# @param [String] pattern The URI template pattern.
|
980
965
|
# @param [#match] processor The template processor to use.
|
981
966
|
#
|
982
|
-
# @return [Regexp]
|
983
|
-
#
|
984
|
-
|
967
|
+
# @return [Array, Regexp]
|
968
|
+
# An array of expansion variables nad a regular expression which may be
|
969
|
+
# used to parse a template pattern
|
970
|
+
def parse_new_template_pattern(pattern, processor = nil)
|
985
971
|
# Escape the pattern. The two gsubs restore the escaped curly braces
|
986
972
|
# back to their original form. Basically, escape everything that isn't
|
987
973
|
# within an expansion.
|