addressable 2.6.0 → 2.8.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +35 -0
- data/Gemfile +14 -16
- data/README.md +12 -10
- data/Rakefile +3 -3
- data/lib/addressable/idna/native.rb +0 -1
- data/lib/addressable/idna/pure.rb +52 -51
- data/lib/addressable/idna.rb +0 -1
- data/lib/addressable/template.rb +28 -43
- data/lib/addressable/uri.rb +129 -79
- data/lib/addressable/version.rb +2 -3
- data/spec/addressable/idna_spec.rb +3 -2
- data/spec/addressable/net_http_compat_spec.rb +0 -1
- data/spec/addressable/security_spec.rb +0 -1
- data/spec/addressable/template_spec.rb +18 -1
- data/spec/addressable/uri_spec.rb +408 -208
- data/spec/spec_helper.rb +9 -0
- data/tasks/gem.rake +9 -7
- data/tasks/profile.rake +72 -0
- data/tasks/rspec.rake +1 -1
- metadata +15 -15
- 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: 3ddda72232f6aef9f6f4311c2855f1b3fea9acc80f51c4e5e90bd23820b0d74e
|
4
|
+
data.tar.gz: 88f208cb2d73dec64663e6e3c1710dc08b188402937038fefce6a2d47debc97d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4e1b0c83fc2f2e54cba6804f3840c8bb29f0d73259979d5bf678ebd5d32257b91585d9b71a780321427835d10f98b9c07969267878f0b032c53d031c30202a4c
|
7
|
+
data.tar.gz: 35abc3652c8ff92032411e4daad7133b7c4649aff4a1a25fe622cf1c9b661d56f096a1084392e053788baea79f551a9d4a448d16c9e61e23bf4d9692a6728bf3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,38 @@
|
|
1
|
+
# Addressable 2.8.1
|
2
|
+
- refactor `Addressable::URI.normalize_path` to address linter offenses ([#430](https://github.com/sporkmonger/addressable/pull/430))
|
3
|
+
- remove redundant colon in `Addressable::URI::CharacterClasses::AUTHORITY` regex ([#438](https://github.com/sporkmonger/addressable/pull/438))
|
4
|
+
- update gemspec to reflect supported Ruby versions ([#466], [#464], [#463])
|
5
|
+
- compatibility w/ public_suffix 5.x ([#466], [#465], [#460])
|
6
|
+
- fixes "invalid byte sequence in UTF-8" exception when unencoding URLs containing non UTF-8 characters ([#459](https://github.com/sporkmonger/addressable/pull/459))
|
7
|
+
- `Ractor` compatibility ([#449](https://github.com/sporkmonger/addressable/pull/449))
|
8
|
+
- use the whole string instead of a single line for template match ([#431](https://github.com/sporkmonger/addressable/pull/431))
|
9
|
+
- force UTF-8 encoding only if needed ([#341](https://github.com/sporkmonger/addressable/pull/341))
|
10
|
+
|
11
|
+
[#460]: https://github.com/sporkmonger/addressable/pull/460
|
12
|
+
[#463]: https://github.com/sporkmonger/addressable/pull/463
|
13
|
+
[#464]: https://github.com/sporkmonger/addressable/pull/464
|
14
|
+
[#465]: https://github.com/sporkmonger/addressable/pull/465
|
15
|
+
[#466]: https://github.com/sporkmonger/addressable/pull/466
|
16
|
+
|
17
|
+
# Addressable 2.8.0
|
18
|
+
- fixes ReDoS vulnerability in Addressable::Template#match
|
19
|
+
- no longer replaces `+` with spaces in queries for non-http(s) schemes
|
20
|
+
- fixed encoding ipv6 literals
|
21
|
+
- the `:compacted` flag for `normalized_query` now dedupes parameters
|
22
|
+
- fix broken `escape_component` alias
|
23
|
+
- dropping support for Ruby 2.0 and 2.1
|
24
|
+
- adding Ruby 3.0 compatibility for development tasks
|
25
|
+
- drop support for `rack-mount` and remove Addressable::Template#generate
|
26
|
+
- performance improvements
|
27
|
+
- switch CI/CD to GitHub Actions
|
28
|
+
|
29
|
+
# Addressable 2.7.0
|
30
|
+
- added `:compacted` flag to `normalized_query`
|
31
|
+
- `heuristic_parse` handles `mailto:` more intuitively
|
32
|
+
- dropped explicit support for JRuby 9.0.5.0
|
33
|
+
- compatibility w/ public_suffix 4.x
|
34
|
+
- performance improvements
|
35
|
+
|
1
36
|
# Addressable 2.6.0
|
2
37
|
- added `tld=` method to allow assignment to the public suffix
|
3
38
|
- 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
5
|
gemspec
|
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,10 @@ 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
|
-
|
28
|
+
unless ENV["IDNA_MODE"] == "pure"
|
29
|
+
gem "idn-ruby", platform: :mri
|
30
|
+
end
|
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 Version](
|
11
|
-
[![Build Status](https://
|
10
|
+
[![Gem Version](https://img.shields.io/gem/dt/addressable.svg)][gem]
|
11
|
+
[![Build Status](https://github.com/sporkmonger/addressable/workflows/CI/badge.svg)][actions]
|
12
12
|
[![Test Coverage Status](https://img.shields.io/coveralls/sporkmonger/addressable.svg)][coveralls]
|
13
|
-
[![Documentation Coverage Status](
|
13
|
+
[![Documentation Coverage Status](https://inch-ci.org/github/sporkmonger/addressable.svg?branch=master)][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[
|
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# encoding:utf-8
|
4
3
|
#--
|
5
4
|
# Copyright (C) Bob Aman
|
6
5
|
#
|
@@ -135,7 +134,7 @@ module Addressable
|
|
135
134
|
unpacked.map! { |codepoint| lookup_unicode_lowercase(codepoint) }
|
136
135
|
return unpacked.pack("U*")
|
137
136
|
end
|
138
|
-
|
137
|
+
private_class_method :unicode_downcase
|
139
138
|
|
140
139
|
def self.unicode_compose(unpacked)
|
141
140
|
unpacked_result = []
|
@@ -160,7 +159,7 @@ module Addressable
|
|
160
159
|
unpacked_result << starter
|
161
160
|
return unpacked_result
|
162
161
|
end
|
163
|
-
|
162
|
+
private_class_method :unicode_compose
|
164
163
|
|
165
164
|
def self.unicode_compose_pair(ch_one, ch_two)
|
166
165
|
if ch_one >= HANGUL_LBASE && ch_one < HANGUL_LBASE + HANGUL_LCOUNT &&
|
@@ -178,43 +177,45 @@ module Addressable
|
|
178
177
|
end
|
179
178
|
|
180
179
|
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
180
|
|
212
|
-
ucs4_to_utf8
|
213
|
-
ucs4_to_utf8
|
181
|
+
ucs4_to_utf8(ch_one, p)
|
182
|
+
ucs4_to_utf8(ch_two, p)
|
214
183
|
|
215
184
|
return lookup_unicode_composition(p)
|
216
185
|
end
|
217
|
-
|
186
|
+
private_class_method :unicode_compose_pair
|
187
|
+
|
188
|
+
def self.ucs4_to_utf8(char, buffer)
|
189
|
+
if char < 128
|
190
|
+
buffer << char
|
191
|
+
elsif char < 2048
|
192
|
+
buffer << (char >> 6 | 192)
|
193
|
+
buffer << (char & 63 | 128)
|
194
|
+
elsif char < 0x10000
|
195
|
+
buffer << (char >> 12 | 224)
|
196
|
+
buffer << (char >> 6 & 63 | 128)
|
197
|
+
buffer << (char & 63 | 128)
|
198
|
+
elsif char < 0x200000
|
199
|
+
buffer << (char >> 18 | 240)
|
200
|
+
buffer << (char >> 12 & 63 | 128)
|
201
|
+
buffer << (char >> 6 & 63 | 128)
|
202
|
+
buffer << (char & 63 | 128)
|
203
|
+
elsif char < 0x4000000
|
204
|
+
buffer << (char >> 24 | 248)
|
205
|
+
buffer << (char >> 18 & 63 | 128)
|
206
|
+
buffer << (char >> 12 & 63 | 128)
|
207
|
+
buffer << (char >> 6 & 63 | 128)
|
208
|
+
buffer << (char & 63 | 128)
|
209
|
+
elsif char < 0x80000000
|
210
|
+
buffer << (char >> 30 | 252)
|
211
|
+
buffer << (char >> 24 & 63 | 128)
|
212
|
+
buffer << (char >> 18 & 63 | 128)
|
213
|
+
buffer << (char >> 12 & 63 | 128)
|
214
|
+
buffer << (char >> 6 & 63 | 128)
|
215
|
+
buffer << (char & 63 | 128)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
private_class_method :ucs4_to_utf8
|
218
219
|
|
219
220
|
def self.unicode_sort_canonical(unpacked)
|
220
221
|
unpacked = unpacked.dup
|
@@ -238,7 +239,7 @@ module Addressable
|
|
238
239
|
end
|
239
240
|
return unpacked
|
240
241
|
end
|
241
|
-
|
242
|
+
private_class_method :unicode_sort_canonical
|
242
243
|
|
243
244
|
def self.unicode_decompose(unpacked)
|
244
245
|
unpacked_result = []
|
@@ -259,7 +260,7 @@ module Addressable
|
|
259
260
|
end
|
260
261
|
return unpacked_result
|
261
262
|
end
|
262
|
-
|
263
|
+
private_class_method :unicode_decompose
|
263
264
|
|
264
265
|
def self.unicode_decompose_hangul(codepoint)
|
265
266
|
sindex = codepoint - HANGUL_SBASE;
|
@@ -276,7 +277,7 @@ module Addressable
|
|
276
277
|
end
|
277
278
|
return l, v, t
|
278
279
|
end
|
279
|
-
|
280
|
+
private_class_method :unicode_decompose_hangul
|
280
281
|
|
281
282
|
def self.lookup_unicode_combining_class(codepoint)
|
282
283
|
codepoint_data = UNICODE_DATA[codepoint]
|
@@ -284,14 +285,14 @@ module Addressable
|
|
284
285
|
(codepoint_data[UNICODE_DATA_COMBINING_CLASS] || 0) :
|
285
286
|
0)
|
286
287
|
end
|
287
|
-
|
288
|
+
private_class_method :lookup_unicode_combining_class
|
288
289
|
|
289
290
|
def self.lookup_unicode_compatibility(codepoint)
|
290
291
|
codepoint_data = UNICODE_DATA[codepoint]
|
291
292
|
(codepoint_data ?
|
292
293
|
codepoint_data[UNICODE_DATA_COMPATIBILITY] : nil)
|
293
294
|
end
|
294
|
-
|
295
|
+
private_class_method :lookup_unicode_compatibility
|
295
296
|
|
296
297
|
def self.lookup_unicode_lowercase(codepoint)
|
297
298
|
codepoint_data = UNICODE_DATA[codepoint]
|
@@ -299,12 +300,12 @@ module Addressable
|
|
299
300
|
(codepoint_data[UNICODE_DATA_LOWERCASE] || codepoint) :
|
300
301
|
codepoint)
|
301
302
|
end
|
302
|
-
|
303
|
+
private_class_method :lookup_unicode_lowercase
|
303
304
|
|
304
305
|
def self.lookup_unicode_composition(unpacked)
|
305
306
|
return COMPOSITION_TABLE[unpacked]
|
306
307
|
end
|
307
|
-
|
308
|
+
private_class_method :lookup_unicode_composition
|
308
309
|
|
309
310
|
HANGUL_SBASE = 0xac00
|
310
311
|
HANGUL_LBASE = 0x1100
|
@@ -341,7 +342,7 @@ module Addressable
|
|
341
342
|
end
|
342
343
|
|
343
344
|
COMPOSITION_TABLE = {}
|
344
|
-
|
345
|
+
UNICODE_DATA.each do |codepoint, data|
|
345
346
|
canonical = data[UNICODE_DATA_CANONICAL]
|
346
347
|
exclusion = data[UNICODE_DATA_EXCLUSION]
|
347
348
|
|
@@ -500,7 +501,7 @@ module Addressable
|
|
500
501
|
|
501
502
|
output[0..outlen].map { |x| x.chr }.join("").sub(/\0+\z/, "")
|
502
503
|
end
|
503
|
-
|
504
|
+
private_class_method :punycode_encode
|
504
505
|
|
505
506
|
def self.punycode_decode(punycode)
|
506
507
|
input = []
|
@@ -622,22 +623,22 @@ module Addressable
|
|
622
623
|
|
623
624
|
output.pack("U*")
|
624
625
|
end
|
625
|
-
|
626
|
+
private_class_method :punycode_decode
|
626
627
|
|
627
628
|
def self.punycode_basic?(codepoint)
|
628
629
|
codepoint < 0x80
|
629
630
|
end
|
630
|
-
|
631
|
+
private_class_method :punycode_basic?
|
631
632
|
|
632
633
|
def self.punycode_delimiter?(codepoint)
|
633
634
|
codepoint == PUNYCODE_DELIMITER
|
634
635
|
end
|
635
|
-
|
636
|
+
private_class_method :punycode_delimiter?
|
636
637
|
|
637
638
|
def self.punycode_encode_digit(d)
|
638
639
|
d + 22 + 75 * ((d < 26) ? 1 : 0)
|
639
640
|
end
|
640
|
-
|
641
|
+
private_class_method :punycode_encode_digit
|
641
642
|
|
642
643
|
# Returns the numeric value of a basic codepoint
|
643
644
|
# (for use in representing integers) in the range 0 to
|
@@ -653,7 +654,7 @@ module Addressable
|
|
653
654
|
PUNYCODE_BASE
|
654
655
|
end
|
655
656
|
end
|
656
|
-
|
657
|
+
private_class_method :punycode_decode_digit
|
657
658
|
|
658
659
|
# Bias adaptation method
|
659
660
|
def self.punycode_adapt(delta, numpoints, firsttime)
|
@@ -670,7 +671,7 @@ module Addressable
|
|
670
671
|
|
671
672
|
k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
|
672
673
|
end
|
673
|
-
|
674
|
+
private_class_method :punycode_adapt
|
674
675
|
end
|
675
676
|
# :startdoc:
|
676
677
|
end
|
data/lib/addressable/idna.rb
CHANGED
data/lib/addressable/template.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# encoding:utf-8
|
4
3
|
#--
|
5
4
|
# Copyright (C) Bob Aman
|
6
5
|
#
|
@@ -37,7 +36,7 @@ module Addressable
|
|
37
36
|
Addressable::URI::CharacterClasses::DIGIT + '_'
|
38
37
|
|
39
38
|
var_char =
|
40
|
-
"(
|
39
|
+
"(?>(?:[#{variable_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
|
41
40
|
RESERVED =
|
42
41
|
"(?:[#{anything}]|%[a-fA-F0-9][a-fA-F0-9])"
|
43
42
|
UNRESERVED =
|
@@ -412,7 +411,7 @@ module Addressable
|
|
412
411
|
# match.captures
|
413
412
|
# #=> ["a", ["b", "c"]]
|
414
413
|
def match(uri, processor=nil)
|
415
|
-
uri = Addressable::URI.parse(uri)
|
414
|
+
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
|
416
415
|
mapping = {}
|
417
416
|
|
418
417
|
# First, we need to process the pattern, and extract the values.
|
@@ -653,50 +652,16 @@ module Addressable
|
|
653
652
|
self.to_regexp.named_captures
|
654
653
|
end
|
655
654
|
|
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
655
|
private
|
691
656
|
def ordered_variable_defaults
|
692
657
|
@ordered_variable_defaults ||= begin
|
693
658
|
expansions, _ = parse_template_pattern(pattern)
|
694
|
-
expansions.
|
659
|
+
expansions.flat_map do |capture|
|
695
660
|
_, _, varlist = *capture.match(EXPRESSION)
|
696
661
|
varlist.split(',').map do |varspec|
|
697
662
|
varspec[VARSPEC, 1]
|
698
663
|
end
|
699
|
-
end
|
664
|
+
end
|
700
665
|
end
|
701
666
|
end
|
702
667
|
|
@@ -973,15 +938,35 @@ module Addressable
|
|
973
938
|
end
|
974
939
|
end
|
975
940
|
|
941
|
+
##
|
942
|
+
# Generates the <tt>Regexp</tt> that parses a template pattern. Memoizes the
|
943
|
+
# value if template processor not set (processors may not be deterministic)
|
944
|
+
#
|
945
|
+
# @param [String] pattern The URI template pattern.
|
946
|
+
# @param [#match] processor The template processor to use.
|
947
|
+
#
|
948
|
+
# @return [Array, Regexp]
|
949
|
+
# An array of expansion variables nad a regular expression which may be
|
950
|
+
# used to parse a template pattern
|
951
|
+
def parse_template_pattern(pattern, processor = nil)
|
952
|
+
if processor.nil? && pattern == @pattern
|
953
|
+
@cached_template_parse ||=
|
954
|
+
parse_new_template_pattern(pattern, processor)
|
955
|
+
else
|
956
|
+
parse_new_template_pattern(pattern, processor)
|
957
|
+
end
|
958
|
+
end
|
959
|
+
|
976
960
|
##
|
977
961
|
# Generates the <tt>Regexp</tt> that parses a template pattern.
|
978
962
|
#
|
979
963
|
# @param [String] pattern The URI template pattern.
|
980
964
|
# @param [#match] processor The template processor to use.
|
981
965
|
#
|
982
|
-
# @return [Regexp]
|
983
|
-
#
|
984
|
-
|
966
|
+
# @return [Array, Regexp]
|
967
|
+
# An array of expansion variables nad a regular expression which may be
|
968
|
+
# used to parse a template pattern
|
969
|
+
def parse_new_template_pattern(pattern, processor = nil)
|
985
970
|
# Escape the pattern. The two gsubs restore the escaped curly braces
|
986
971
|
# back to their original form. Basically, escape everything that isn't
|
987
972
|
# within an expansion.
|
@@ -1037,7 +1022,7 @@ module Addressable
|
|
1037
1022
|
end
|
1038
1023
|
|
1039
1024
|
# Ensure that the regular expression matches the whole URI.
|
1040
|
-
regexp_string = "
|
1025
|
+
regexp_string = "\\A#{regexp_string}\\z"
|
1041
1026
|
return expansions, Regexp.new(regexp_string)
|
1042
1027
|
end
|
1043
1028
|
|