addressable 2.1.0 → 2.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/Rakefile +34 -10
- data/lib/addressable/idna.rb +4 -4
- data/lib/addressable/template.rb +109 -84
- data/lib/addressable/uri.rb +125 -82
- data/lib/addressable/version.rb +1 -1
- data/spec/addressable/idna_spec.rb +0 -3
- data/spec/addressable/template_spec.rb +48 -16
- data/spec/addressable/uri_spec.rb +128 -3
- data/tasks/spec.rake +8 -25
- metadata +11 -8
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -1,7 +1,3 @@
|
|
1
|
-
lib_dir = File.expand_path(File.join(File.dirname(__FILE__), "lib"))
|
2
|
-
$:.unshift(lib_dir)
|
3
|
-
$:.uniq!
|
4
|
-
|
5
1
|
require 'rubygems'
|
6
2
|
require 'rake'
|
7
3
|
require 'rake/testtask'
|
@@ -10,7 +6,7 @@ require 'rake/packagetask'
|
|
10
6
|
require 'rake/gempackagetask'
|
11
7
|
require 'spec/rake/spectask'
|
12
8
|
|
13
|
-
require File.join(File.dirname(__FILE__), 'lib
|
9
|
+
require File.join(File.dirname(__FILE__), 'lib', 'addressable', 'version')
|
14
10
|
|
15
11
|
PKG_DISPLAY_NAME = 'Addressable'
|
16
12
|
PKG_NAME = PKG_DISPLAY_NAME.downcase
|
@@ -31,6 +27,38 @@ Ruby's standard library. It more closely conforms to the relevant RFCs and
|
|
31
27
|
adds support for IRIs and URI templates.
|
32
28
|
TEXT
|
33
29
|
|
30
|
+
desc "generates .gemspec file"
|
31
|
+
task :gemspec do
|
32
|
+
spec = Gem::Specification.new do |p|
|
33
|
+
p.name = 'addressable'
|
34
|
+
p.version = PKG_VERSION
|
35
|
+
|
36
|
+
p.summary = PKG_SUMMARY
|
37
|
+
p.description = PKG_DESCRIPTION
|
38
|
+
|
39
|
+
p.author = 'Bob Aman'
|
40
|
+
p.email = 'bob@sporkmonger.com'
|
41
|
+
p.homepage = 'http://github.com/mislav/addressable'
|
42
|
+
p.rubyforge_project = nil
|
43
|
+
|
44
|
+
p.files = FileList['Rakefile', '{bin,lib,tasks,spec}/**/*', 'README*', 'LICENSE*', 'CHANGELOG*'] & `git ls-files`.split
|
45
|
+
|
46
|
+
p.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
47
|
+
|
48
|
+
p.has_rdoc = true
|
49
|
+
end
|
50
|
+
|
51
|
+
spec_string = spec.to_ruby
|
52
|
+
|
53
|
+
begin
|
54
|
+
Thread.new { eval("$SAFE = 3\n#{spec_string}", binding) }.join
|
55
|
+
rescue
|
56
|
+
abort "unsafe gemspec: #{$!}"
|
57
|
+
else
|
58
|
+
File.open("#{spec.name}.gemspec", 'w') { |file| file.write spec_string }
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
34
62
|
PKG_FILES = FileList[
|
35
63
|
"lib/**/*", "spec/**/*", "vendor/**/*",
|
36
64
|
"tasks/**/*", "website/**/*",
|
@@ -38,11 +66,7 @@ PKG_FILES = FileList[
|
|
38
66
|
].exclude(/database\.yml/).exclude(/[_\.]git$/)
|
39
67
|
|
40
68
|
RCOV_ENABLED = (RUBY_PLATFORM != "java" && RUBY_VERSION =~ /^1\.8/)
|
41
|
-
|
42
|
-
task :default => "spec:verify"
|
43
|
-
else
|
44
|
-
task :default => "spec"
|
45
|
-
end
|
69
|
+
task :default => "spec"
|
46
70
|
|
47
71
|
WINDOWS = (RUBY_PLATFORM =~ /mswin|win32|mingw|bccwin|cygwin/) rescue false
|
48
72
|
SUDO = WINDOWS ? '' : ('sudo' unless ENV['SUDOLESS'])
|
data/lib/addressable/idna.rb
CHANGED
@@ -4855,15 +4855,15 @@ module Addressable
|
|
4855
4855
|
delta = firsttime ? delta / PUNYCODE_DAMP : delta >> 1
|
4856
4856
|
# delta >> 1 is a faster way of doing delta / 2
|
4857
4857
|
delta += delta / numpoints
|
4858
|
+
difference = PUNYCODE_BASE - PUNYCODE_TMIN
|
4858
4859
|
|
4859
4860
|
k = 0
|
4860
|
-
while delta > (
|
4861
|
-
delta /=
|
4861
|
+
while delta > (difference * PUNYCODE_TMAX) / 2
|
4862
|
+
delta /= difference
|
4862
4863
|
k += PUNYCODE_BASE
|
4863
4864
|
end
|
4864
4865
|
|
4865
|
-
k + (
|
4866
|
-
delta / (delta + PUNYCODE_SKEW)
|
4866
|
+
k + (difference + 1) * delta / (delta + PUNYCODE_SKEW)
|
4867
4867
|
end
|
4868
4868
|
(class <<self; private :punycode_adapt; end)
|
4869
4869
|
end
|
data/lib/addressable/template.rb
CHANGED
@@ -22,9 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
#++
|
24
24
|
|
25
|
-
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '/..')))
|
26
|
-
$:.uniq!
|
27
|
-
|
28
25
|
require "addressable/version"
|
29
26
|
require "addressable/uri"
|
30
27
|
|
@@ -39,7 +36,7 @@ module Addressable
|
|
39
36
|
Addressable::URI::CharacterClasses::UNRESERVED
|
40
37
|
OPERATOR_EXPANSION =
|
41
38
|
/\{-([a-zA-Z]+)\|([#{anything}]+)\|([#{anything}]+)\}/
|
42
|
-
VARIABLE_EXPANSION = /\{([#{anything}]+?)(
|
39
|
+
VARIABLE_EXPANSION = /\{([#{anything}]+?)(?:=([#{anything}]+))?\}/
|
43
40
|
|
44
41
|
##
|
45
42
|
# Raised if an invalid template value is supplied.
|
@@ -154,21 +151,23 @@ module Addressable
|
|
154
151
|
#
|
155
152
|
# @param [Addressable::URI, #to_str] uri
|
156
153
|
# The URI to extract from.
|
154
|
+
#
|
157
155
|
# @param [#restore, #match] processor
|
158
156
|
# A template processor object may optionally be supplied.
|
159
|
-
#
|
160
|
-
#
|
161
|
-
#
|
162
|
-
#
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
168
|
-
#
|
157
|
+
#
|
158
|
+
# The object should respond to either the <tt>restore</tt> or
|
159
|
+
# <tt>match</tt> messages or both. The <tt>restore</tt> method should take
|
160
|
+
# two parameters: [String] name and [String] value. The <tt>restore</tt>
|
161
|
+
# method should reverse any transformations that have been performed on the
|
162
|
+
# value to ensure a valid URI. The <tt>match</tt> method should take a
|
163
|
+
# single parameter: [String] name. The <tt>match</tt> method should return
|
164
|
+
# a <tt>String</tt> containing a regular expression capture group for
|
165
|
+
# matching on that particular variable. The default value is ".*?". The
|
166
|
+
# <tt>match</tt> method has no effect on multivariate operator expansions.
|
167
|
+
#
|
169
168
|
# @return [Hash, NilClass]
|
170
|
-
#
|
171
|
-
#
|
169
|
+
# The <tt>Hash</tt> mapping that was extracted from the URI, or
|
170
|
+
# <tt>nil</tt> if the URI didn't match the template.
|
172
171
|
#
|
173
172
|
# @example
|
174
173
|
# class ExampleProcessor
|
@@ -212,21 +211,23 @@ module Addressable
|
|
212
211
|
#
|
213
212
|
# @param [Addressable::URI, #to_str] uri
|
214
213
|
# The URI to extract from.
|
214
|
+
#
|
215
215
|
# @param [#restore, #match] processor
|
216
216
|
# A template processor object may optionally be supplied.
|
217
|
-
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
#
|
221
|
-
#
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
#
|
217
|
+
#
|
218
|
+
# The object should respond to either the <tt>restore</tt> or
|
219
|
+
# <tt>match</tt> messages or both. The <tt>restore</tt> method should take
|
220
|
+
# two parameters: [String] name and [String] value. The <tt>restore</tt>
|
221
|
+
# method should reverse any transformations that have been performed on the
|
222
|
+
# value to ensure a valid URI. The <tt>match</tt> method should take a
|
223
|
+
# single parameter: [String] name. The <tt>match</tt> method should return
|
224
|
+
# a <tt>String</tt> containing a regular expression capture group for
|
225
|
+
# matching on that particular variable. The default value is ".*?". The
|
226
|
+
# <tt>match</tt> method has no effect on multivariate operator expansions.
|
227
|
+
#
|
227
228
|
# @return [Hash, NilClass]
|
228
|
-
#
|
229
|
-
#
|
229
|
+
# The <tt>Hash</tt> mapping that was extracted from the URI, or
|
230
|
+
# <tt>nil</tt> if the URI didn't match the template.
|
230
231
|
#
|
231
232
|
# @example
|
232
233
|
# class ExampleProcessor
|
@@ -325,19 +326,19 @@ module Addressable
|
|
325
326
|
#
|
326
327
|
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
327
328
|
# @param [#validate, #transform] processor
|
328
|
-
# An optional processor object may be supplied.
|
329
|
-
#
|
330
|
-
#
|
331
|
-
#
|
332
|
-
#
|
333
|
-
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
#
|
337
|
-
#
|
338
|
-
#
|
339
|
-
#
|
340
|
-
#
|
329
|
+
# An optional processor object may be supplied.
|
330
|
+
#
|
331
|
+
# The object should respond to either the <tt>validate</tt> or
|
332
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
333
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
334
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
335
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
336
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
|
337
|
+
# exception will be raised if the value is invalid. The <tt>transform</tt>
|
338
|
+
# method should return the transformed variable value as a <tt>String</tt>.
|
339
|
+
# If a <tt>transform</tt> method is used, the value will not be percent
|
340
|
+
# encoded automatically. Unicode normalization will be performed both
|
341
|
+
# before and after sending the value to the transform method.
|
341
342
|
#
|
342
343
|
# @return [Addressable::Template] The partially expanded URI template.
|
343
344
|
#
|
@@ -401,19 +402,19 @@ module Addressable
|
|
401
402
|
#
|
402
403
|
# @param [Hash] mapping The mapping that corresponds to the pattern.
|
403
404
|
# @param [#validate, #transform] processor
|
404
|
-
# An optional processor object may be supplied.
|
405
|
-
#
|
406
|
-
#
|
407
|
-
#
|
408
|
-
#
|
409
|
-
#
|
410
|
-
#
|
411
|
-
#
|
412
|
-
#
|
413
|
-
#
|
414
|
-
#
|
415
|
-
#
|
416
|
-
#
|
405
|
+
# An optional processor object may be supplied.
|
406
|
+
#
|
407
|
+
# The object should respond to either the <tt>validate</tt> or
|
408
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
409
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
410
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
411
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
412
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt>
|
413
|
+
# exception will be raised if the value is invalid. The <tt>transform</tt>
|
414
|
+
# method should return the transformed variable value as a <tt>String</tt>.
|
415
|
+
# If a <tt>transform</tt> method is used, the value will not be percent
|
416
|
+
# encoded automatically. Unicode normalization will be performed both
|
417
|
+
# before and after sending the value to the transform method.
|
417
418
|
#
|
418
419
|
# @return [Addressable::URI] The expanded URI template.
|
419
420
|
#
|
@@ -484,55 +485,79 @@ module Addressable
|
|
484
485
|
#
|
485
486
|
# @return [Array] The variables present in the template's pattern.
|
486
487
|
def variables
|
487
|
-
@variables ||=
|
488
|
-
|
488
|
+
@variables ||= ordered_variable_defaults.map { |var, val| var }.uniq
|
489
|
+
end
|
490
|
+
alias_method :keys, :variables
|
491
|
+
|
492
|
+
##
|
493
|
+
# Returns a mapping of variables to their default values specified
|
494
|
+
# in the template. Variables without defaults are not returned.
|
495
|
+
#
|
496
|
+
# @return [Hash] Mapping of template variables to their defaults
|
497
|
+
def variable_defaults
|
498
|
+
@variable_defaults ||= Hash[*ordered_variable_defaults.reject { |k,v| v.nil? }.flatten]
|
499
|
+
end
|
489
500
|
|
501
|
+
private
|
502
|
+
|
503
|
+
def ordered_variable_defaults
|
504
|
+
@ordered_variable_defaults ||= begin
|
490
505
|
expansions, expansion_regexp = parse_template_pattern(pattern)
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
result
|
506
|
+
|
507
|
+
expansions.inject([]) do |result, expansion|
|
508
|
+
case expansion
|
509
|
+
when OPERATOR_EXPANSION
|
510
|
+
_, _, variables, mapping = parse_template_expansion(expansion)
|
511
|
+
result.concat variables.map { |var| [var, mapping[var]] }
|
512
|
+
when VARIABLE_EXPANSION
|
513
|
+
result << [$1, $2]
|
497
514
|
end
|
515
|
+
result
|
498
516
|
end
|
499
|
-
|
500
|
-
end)
|
517
|
+
end
|
501
518
|
end
|
502
|
-
alias_method :keys, :variables
|
503
519
|
|
504
|
-
private
|
505
520
|
##
|
506
521
|
# Transforms a mapping so that values can be substituted into the
|
507
522
|
# template.
|
508
523
|
#
|
509
524
|
# @param [Hash] mapping The mapping of variables to values.
|
510
525
|
# @param [#validate, #transform] processor
|
511
|
-
# An optional processor object may be supplied.
|
512
|
-
#
|
513
|
-
#
|
514
|
-
#
|
515
|
-
#
|
516
|
-
#
|
517
|
-
#
|
518
|
-
#
|
519
|
-
#
|
520
|
-
#
|
521
|
-
#
|
522
|
-
#
|
523
|
-
#
|
526
|
+
# An optional processor object may be supplied.
|
527
|
+
#
|
528
|
+
# The object should respond to either the <tt>validate</tt> or
|
529
|
+
# <tt>transform</tt> messages or both. Both the <tt>validate</tt> and
|
530
|
+
# <tt>transform</tt> methods should take two parameters: <tt>name</tt> and
|
531
|
+
# <tt>value</tt>. The <tt>validate</tt> method should return <tt>true</tt>
|
532
|
+
# or <tt>false</tt>; <tt>true</tt> if the value of the variable is valid,
|
533
|
+
# <tt>false</tt> otherwise. An <tt>InvalidTemplateValueError</tt> exception
|
534
|
+
# will be raised if the value is invalid. The <tt>transform</tt> method
|
535
|
+
# should return the transformed variable value as a <tt>String</tt>. If a
|
536
|
+
# <tt>transform</tt> method is used, the value will not be percent encoded
|
537
|
+
# automatically. Unicode normalization will be performed both before and
|
538
|
+
# after sending the value to the transform method.
|
524
539
|
#
|
525
540
|
# @return [Hash] The transformed mapping.
|
526
541
|
def transform_mapping(mapping, processor=nil)
|
527
542
|
return mapping.inject({}) do |accu, pair|
|
528
543
|
name, value = pair
|
544
|
+
value = value.to_s if Numeric === value || Symbol === value
|
545
|
+
|
529
546
|
unless value.respond_to?(:to_ary) || value.respond_to?(:to_str)
|
530
547
|
raise TypeError,
|
531
548
|
"Can't convert #{value.class} into String or Array."
|
532
549
|
end
|
533
550
|
|
534
|
-
|
535
|
-
|
551
|
+
if Symbol === name
|
552
|
+
name = name.to_s
|
553
|
+
elsif name.respond_to?(:to_str)
|
554
|
+
name = name.to_str
|
555
|
+
else
|
556
|
+
raise TypeError,
|
557
|
+
"Can't convert #{name.class} into String."
|
558
|
+
end
|
559
|
+
value = value.respond_to?(:to_ary) ? value.to_ary : value.to_str
|
560
|
+
|
536
561
|
# Handle unicode normalization
|
537
562
|
if value.kind_of?(Array)
|
538
563
|
value.map! { |val| Addressable::IDNA.unicode_normalize_kc(val) }
|
@@ -796,8 +821,8 @@ module Addressable
|
|
796
821
|
# @return [Regexp]
|
797
822
|
# A regular expression which may be used to parse a template pattern.
|
798
823
|
def parse_template_pattern(pattern, processor=nil)
|
799
|
-
# Escape the pattern.
|
800
|
-
# back to their original form.
|
824
|
+
# Escape the pattern. The two gsubs restore the escaped curly braces
|
825
|
+
# back to their original form. Basically, escape everything that isn't
|
801
826
|
# within an expansion.
|
802
827
|
escaped_pattern = Regexp.escape(
|
803
828
|
pattern
|
@@ -819,7 +844,7 @@ module Addressable
|
|
819
844
|
parse_template_expansion(expansion)
|
820
845
|
if processor != nil && processor.respond_to?(:match)
|
821
846
|
# We can only lookup the match values for single variable
|
822
|
-
# operator expansions.
|
847
|
+
# operator expansions. Besides, ".*" is usually the only
|
823
848
|
# reasonable value for multivariate operators anyways.
|
824
849
|
if ["prefix", "suffix", "list"].include?(operator)
|
825
850
|
capture_group = "(#{processor.match(names.first)})"
|
data/lib/addressable/uri.rb
CHANGED
@@ -22,9 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
#++
|
24
24
|
|
25
|
-
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '/..')))
|
26
|
-
$:.uniq!
|
27
|
-
|
28
25
|
require "addressable/version"
|
29
26
|
require "addressable/idna"
|
30
27
|
|
@@ -66,8 +63,9 @@ module Addressable
|
|
66
63
|
# Returns a URI object based on the parsed string.
|
67
64
|
#
|
68
65
|
# @param [String, Addressable::URI, #to_str] uri
|
69
|
-
# The URI string to parse.
|
70
|
-
#
|
66
|
+
# The URI string to parse.
|
67
|
+
# No parsing is performed if the object is already an
|
68
|
+
# <tt>Addressable::URI</tt>.
|
71
69
|
#
|
72
70
|
# @return [Addressable::URI] The parsed URI.
|
73
71
|
def self.parse(uri)
|
@@ -131,16 +129,17 @@ module Addressable
|
|
131
129
|
end
|
132
130
|
|
133
131
|
##
|
134
|
-
# Converts an input to a URI.
|
132
|
+
# Converts an input to a URI. The input does not have to be a valid
|
135
133
|
# URI — the method will use heuristics to guess what URI was intended.
|
136
134
|
# This is not standards-compliant, merely user-friendly.
|
137
135
|
#
|
138
136
|
# @param [String, Addressable::URI, #to_str] uri
|
139
|
-
# The URI string to parse.
|
140
|
-
#
|
137
|
+
# The URI string to parse.
|
138
|
+
# No parsing is performed if the object is already an
|
139
|
+
# <tt>Addressable::URI</tt>.
|
141
140
|
# @param [Hash] hints
|
142
|
-
# A <tt>Hash</tt> of hints to the heuristic parser.
|
143
|
-
#
|
141
|
+
# A <tt>Hash</tt> of hints to the heuristic parser.
|
142
|
+
# Defaults to <tt>{:scheme => "http"}</tt>.
|
144
143
|
#
|
145
144
|
# @return [Addressable::URI] The parsed URI.
|
146
145
|
def self.heuristic_parse(uri, hints={})
|
@@ -184,16 +183,16 @@ module Addressable
|
|
184
183
|
end
|
185
184
|
|
186
185
|
##
|
187
|
-
# Converts a path to a file scheme URI.
|
188
|
-
# relative, it will be returned as a relative URI.
|
186
|
+
# Converts a path to a file scheme URI. If the path supplied is
|
187
|
+
# relative, it will be returned as a relative URI. If the path supplied
|
189
188
|
# is actually a non-file URI, it will parse the URI as if it had been
|
190
|
-
# parsed with <tt>Addressable::URI.parse</tt>.
|
189
|
+
# parsed with <tt>Addressable::URI.parse</tt>. Handles all of the
|
191
190
|
# various Microsoft-specific formats for specifying paths.
|
192
191
|
#
|
193
192
|
# @param [String, Addressable::URI, #to_str] path
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
193
|
+
#
|
194
|
+
# Typically a <tt>String</tt> path to a file or directory, but will return
|
195
|
+
# a sensible return value if an absolute URI is supplied instead.
|
197
196
|
#
|
198
197
|
# @return [Addressable::URI]
|
199
198
|
# The parsed file scheme URI or the original URI if some other URI
|
@@ -281,17 +280,17 @@ module Addressable
|
|
281
280
|
# @param [String, #to_str] component The URI component to encode.
|
282
281
|
#
|
283
282
|
# @param [String, Regexp] character_class
|
284
|
-
#
|
285
|
-
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
289
|
-
#
|
290
|
-
#
|
291
|
-
#
|
292
|
-
#
|
293
|
-
#
|
294
|
-
#
|
283
|
+
#
|
284
|
+
# The characters which are not percent encoded. If a <tt>String</tt> is
|
285
|
+
# passed, the <tt>String</tt> must be formatted as a regular expression
|
286
|
+
# character class. (Do not include the surrounding square brackets.) For
|
287
|
+
# example, <tt>"b-zB-Z0-9"</tt> would cause everything but the letters 'b'
|
288
|
+
# through 'z' and the numbers '0' through '9' to be percent encoded. If a
|
289
|
+
# <tt>Regexp</tt> is passed, the value <tt>/[^b-zB-Z0-9]/</tt> would have
|
290
|
+
# the same effect. A set of useful <tt>String</tt> values may be found in
|
291
|
+
# the <tt>Addressable::URI::CharacterClasses</tt> module. The default
|
292
|
+
# value is the reserved plus unreserved character classes specified in <a
|
293
|
+
# href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
|
295
294
|
#
|
296
295
|
# @return [String] The encoded component.
|
297
296
|
#
|
@@ -343,13 +342,14 @@ module Addressable
|
|
343
342
|
# The URI or component to unencode.
|
344
343
|
#
|
345
344
|
# @param [Class] returning
|
346
|
-
# The type of object to return.
|
347
|
-
#
|
348
|
-
#
|
345
|
+
# The type of object to return.
|
346
|
+
# This value may only be set to <tt>String</tt> or
|
347
|
+
# <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
|
348
|
+
# <tt>String</tt>.
|
349
349
|
#
|
350
350
|
# @return [String, Addressable::URI]
|
351
|
-
# The unencoded component or URI.
|
352
|
-
#
|
351
|
+
# The unencoded component or URI.
|
352
|
+
# The return type is determined by the <tt>returning</tt> parameter.
|
353
353
|
def self.unencode(uri, returning=String)
|
354
354
|
return nil if uri.nil?
|
355
355
|
if !uri.respond_to?(:to_str)
|
@@ -384,13 +384,14 @@ module Addressable
|
|
384
384
|
# The URI to encode.
|
385
385
|
#
|
386
386
|
# @param [Class] returning
|
387
|
-
# The type of object to return.
|
388
|
-
#
|
389
|
-
#
|
387
|
+
# The type of object to return.
|
388
|
+
# This value may only be set to <tt>String</tt> or
|
389
|
+
# <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
|
390
|
+
# <tt>String</tt>.
|
390
391
|
#
|
391
392
|
# @return [String, Addressable::URI]
|
392
|
-
# The encoded URI.
|
393
|
-
#
|
393
|
+
# The encoded URI.
|
394
|
+
# The return type is determined by the <tt>returning</tt> parameter.
|
394
395
|
def self.encode(uri, returning=String)
|
395
396
|
return nil if uri.nil?
|
396
397
|
if !uri.respond_to?(:to_str)
|
@@ -426,20 +427,21 @@ module Addressable
|
|
426
427
|
end
|
427
428
|
|
428
429
|
##
|
429
|
-
# Normalizes the encoding of a URI.
|
430
|
+
# Normalizes the encoding of a URI. Characters within a hostname are
|
430
431
|
# not percent encoded to allow for internationalized domain names.
|
431
432
|
#
|
432
433
|
# @param [String, Addressable::URI, #to_str] uri
|
433
434
|
# The URI to encode.
|
434
435
|
#
|
435
436
|
# @param [Class] returning
|
436
|
-
# The type of object to return.
|
437
|
-
#
|
438
|
-
#
|
437
|
+
# The type of object to return.
|
438
|
+
# This value may only be set to <tt>String</tt> or
|
439
|
+
# <tt>Addressable::URI</tt>. All other values are invalid. Defaults to
|
440
|
+
# <tt>String</tt>.
|
439
441
|
#
|
440
442
|
# @return [String, Addressable::URI]
|
441
|
-
# The encoded URI.
|
442
|
-
#
|
443
|
+
# The encoded URI.
|
444
|
+
# The return type is determined by the <tt>returning</tt> parameter.
|
443
445
|
def self.normalized_encode(uri, returning=String)
|
444
446
|
if !uri.respond_to?(:to_str)
|
445
447
|
raise TypeError, "Can't convert #{uri.class} into String."
|
@@ -501,12 +503,12 @@ module Addressable
|
|
501
503
|
# @option [String, #to_str] user The user component.
|
502
504
|
# @option [String, #to_str] password The password component.
|
503
505
|
# @option [String, #to_str] userinfo
|
504
|
-
# The userinfo component.
|
506
|
+
# The userinfo component. If this is supplied, the user and password
|
505
507
|
# components must be omitted.
|
506
508
|
# @option [String, #to_str] host The host component.
|
507
509
|
# @option [String, #to_str] port The port component.
|
508
510
|
# @option [String, #to_str] authority
|
509
|
-
# The authority component.
|
511
|
+
# The authority component. If this is supplied, the user, password,
|
510
512
|
# userinfo, host, and port components must be omitted.
|
511
513
|
# @option [String, #to_str] path The path component.
|
512
514
|
# @option [String, #to_str] query The query component.
|
@@ -581,6 +583,9 @@ module Addressable
|
|
581
583
|
# Check for frozenness
|
582
584
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
583
585
|
|
586
|
+
if new_scheme && !new_scheme.respond_to?(:to_str)
|
587
|
+
raise TypeError, "Can't convert #{new_scheme.class} into String."
|
588
|
+
end
|
584
589
|
@scheme = new_scheme ? new_scheme.to_str : nil
|
585
590
|
@scheme = nil if @scheme.to_s.strip == ""
|
586
591
|
|
@@ -631,6 +636,9 @@ module Addressable
|
|
631
636
|
# Check for frozenness
|
632
637
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
633
638
|
|
639
|
+
if new_user && !new_user.respond_to?(:to_str)
|
640
|
+
raise TypeError, "Can't convert #{new_user.class} into String."
|
641
|
+
end
|
634
642
|
@user = new_user ? new_user.to_str : nil
|
635
643
|
|
636
644
|
# You can't have a nil user with a non-nil password
|
@@ -689,6 +697,9 @@ module Addressable
|
|
689
697
|
# Check for frozenness
|
690
698
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
691
699
|
|
700
|
+
if new_password && !new_password.respond_to?(:to_str)
|
701
|
+
raise TypeError, "Can't convert #{new_password.class} into String."
|
702
|
+
end
|
692
703
|
@password = new_password ? new_password.to_str : nil
|
693
704
|
|
694
705
|
# You can't have a nil user with a non-nil password
|
@@ -754,6 +765,9 @@ module Addressable
|
|
754
765
|
# Check for frozenness
|
755
766
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
756
767
|
|
768
|
+
if new_userinfo && !new_userinfo.respond_to?(:to_str)
|
769
|
+
raise TypeError, "Can't convert #{new_userinfo.class} into String."
|
770
|
+
end
|
757
771
|
new_user, new_password = if new_userinfo
|
758
772
|
[
|
759
773
|
new_userinfo.to_str.strip[/^(.*):/, 1],
|
@@ -816,6 +830,9 @@ module Addressable
|
|
816
830
|
# Check for frozenness
|
817
831
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
818
832
|
|
833
|
+
if new_host && !new_host.respond_to?(:to_str)
|
834
|
+
raise TypeError, "Can't convert #{new_host.class} into String."
|
835
|
+
end
|
819
836
|
@host = new_host ? new_host.to_str : nil
|
820
837
|
|
821
838
|
# Reset dependant values
|
@@ -881,6 +898,9 @@ module Addressable
|
|
881
898
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
882
899
|
|
883
900
|
if new_authority
|
901
|
+
if !new_authority.respond_to?(:to_str)
|
902
|
+
raise TypeError, "Can't convert #{new_authority.class} into String."
|
903
|
+
end
|
884
904
|
new_authority = new_authority.to_str
|
885
905
|
new_userinfo = new_authority[/^([^\[\]]*)@/, 1]
|
886
906
|
if new_userinfo
|
@@ -894,10 +914,10 @@ module Addressable
|
|
894
914
|
end
|
895
915
|
|
896
916
|
# Password assigned first to ensure validity in case of nil
|
897
|
-
self.password = new_password
|
898
|
-
self.user = new_user
|
899
|
-
self.host = new_host
|
900
|
-
self.port = new_port
|
917
|
+
self.password = defined?(new_password) ? new_password : nil
|
918
|
+
self.user = defined?(new_user) ? new_user : nil
|
919
|
+
self.host = defined?(new_host) ? new_host : nil
|
920
|
+
self.port = defined?(new_port) ? new_port : nil
|
901
921
|
|
902
922
|
# Reset dependant values
|
903
923
|
@inferred_port = nil
|
@@ -909,7 +929,7 @@ module Addressable
|
|
909
929
|
validate()
|
910
930
|
end
|
911
931
|
|
912
|
-
# Returns an array of known ip-based schemes.
|
932
|
+
# Returns an array of known ip-based schemes. These schemes typically
|
913
933
|
# use a similar URI form:
|
914
934
|
# //<user>:<password>@<host>:<port>/<url-path>
|
915
935
|
def self.ip_based_schemes
|
@@ -917,7 +937,7 @@ module Addressable
|
|
917
937
|
end
|
918
938
|
|
919
939
|
# Returns a hash of common IP-based schemes and their default port
|
920
|
-
# numbers.
|
940
|
+
# numbers. Adding new schemes to this hash, as necessary, will allow
|
921
941
|
# for better URI normalization.
|
922
942
|
def self.port_mapping
|
923
943
|
@port_mapping ||= {
|
@@ -939,7 +959,7 @@ module Addressable
|
|
939
959
|
|
940
960
|
##
|
941
961
|
# The port component for this URI.
|
942
|
-
# This is the port number actually given in the URI.
|
962
|
+
# This is the port number actually given in the URI. This does not
|
943
963
|
# infer port numbers from default values.
|
944
964
|
#
|
945
965
|
# @return [Integer] The port component.
|
@@ -1054,6 +1074,9 @@ module Addressable
|
|
1054
1074
|
# Check for frozenness
|
1055
1075
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
1056
1076
|
|
1077
|
+
if new_path && !new_path.respond_to?(:to_str)
|
1078
|
+
raise TypeError, "Can't convert #{new_path.class} into String."
|
1079
|
+
end
|
1057
1080
|
@path = (new_path || "").to_str
|
1058
1081
|
if @path != "" && @path[0..0] != "/" && host != nil
|
1059
1082
|
@path = "/#{@path}"
|
@@ -1098,11 +1121,19 @@ module Addressable
|
|
1098
1121
|
def normalized_query
|
1099
1122
|
@normalized_query ||= (begin
|
1100
1123
|
if self.query
|
1101
|
-
|
1102
|
-
Addressable::
|
1103
|
-
Addressable::
|
1104
|
-
|
1105
|
-
|
1124
|
+
begin
|
1125
|
+
Addressable::URI.encode_component(
|
1126
|
+
Addressable::IDNA.unicode_normalize_kc(
|
1127
|
+
Addressable::URI.unencode_component(self.query.strip)),
|
1128
|
+
Addressable::URI::CharacterClasses::QUERY
|
1129
|
+
)
|
1130
|
+
rescue ArgumentError
|
1131
|
+
# Likely a malformed UTF-8 character, skip unicode normalization
|
1132
|
+
Addressable::URI.encode_component(
|
1133
|
+
Addressable::URI.unencode_component(self.query.strip),
|
1134
|
+
Addressable::URI::CharacterClasses::QUERY
|
1135
|
+
)
|
1136
|
+
end
|
1106
1137
|
else
|
1107
1138
|
nil
|
1108
1139
|
end
|
@@ -1117,6 +1148,9 @@ module Addressable
|
|
1117
1148
|
# Check for frozenness
|
1118
1149
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
1119
1150
|
|
1151
|
+
if new_query && !new_query.respond_to?(:to_str)
|
1152
|
+
raise TypeError, "Can't convert #{new_query.class} into String."
|
1153
|
+
end
|
1120
1154
|
@query = new_query ? new_query.to_str : nil
|
1121
1155
|
|
1122
1156
|
# Reset dependant values
|
@@ -1129,8 +1163,8 @@ module Addressable
|
|
1129
1163
|
#
|
1130
1164
|
# @option [Symbol] notation
|
1131
1165
|
# May be one of <tt>:flat</tt>, <tt>:dot</tt>, or <tt>:subscript</tt>.
|
1132
|
-
#
|
1133
|
-
#
|
1166
|
+
# The <tt>:dot</tt> notation is not supported for assignment. Default
|
1167
|
+
# value is <tt>:subscript</tt>.
|
1134
1168
|
#
|
1135
1169
|
# @return [Hash] The query string parsed as a Hash object.
|
1136
1170
|
#
|
@@ -1285,11 +1319,19 @@ module Addressable
|
|
1285
1319
|
def normalized_fragment
|
1286
1320
|
@normalized_fragment ||= (begin
|
1287
1321
|
if self.fragment
|
1288
|
-
|
1289
|
-
Addressable::
|
1290
|
-
Addressable::
|
1291
|
-
|
1292
|
-
|
1322
|
+
begin
|
1323
|
+
Addressable::URI.encode_component(
|
1324
|
+
Addressable::IDNA.unicode_normalize_kc(
|
1325
|
+
Addressable::URI.unencode_component(self.fragment.strip)),
|
1326
|
+
Addressable::URI::CharacterClasses::FRAGMENT
|
1327
|
+
)
|
1328
|
+
rescue ArgumentError
|
1329
|
+
# Likely a malformed UTF-8 character, skip unicode normalization
|
1330
|
+
Addressable::URI.encode_component(
|
1331
|
+
Addressable::URI.unencode_component(self.fragment.strip),
|
1332
|
+
Addressable::URI::CharacterClasses::FRAGMENT
|
1333
|
+
)
|
1334
|
+
end
|
1293
1335
|
else
|
1294
1336
|
nil
|
1295
1337
|
end
|
@@ -1304,6 +1346,9 @@ module Addressable
|
|
1304
1346
|
# Check for frozenness
|
1305
1347
|
raise TypeError, "Can't modify frozen URI." if self.frozen?
|
1306
1348
|
|
1349
|
+
if new_fragment && !new_fragment.respond_to?(:to_str)
|
1350
|
+
raise TypeError, "Can't convert #{new_fragment.class} into String."
|
1351
|
+
end
|
1307
1352
|
@fragment = new_fragment ? new_fragment.to_str : nil
|
1308
1353
|
|
1309
1354
|
# Reset dependant values
|
@@ -1318,8 +1363,8 @@ module Addressable
|
|
1318
1363
|
# Determines if the scheme indicates an IP-based protocol.
|
1319
1364
|
#
|
1320
1365
|
# @return [TrueClass, FalseClass]
|
1321
|
-
#
|
1322
|
-
#
|
1366
|
+
# <tt>true</tt> if the scheme indicates an IP-based protocol.
|
1367
|
+
# <tt>false</tt> otherwise.
|
1323
1368
|
def ip_based?
|
1324
1369
|
if self.scheme
|
1325
1370
|
return self.class.ip_based_schemes.include?(
|
@@ -1332,8 +1377,7 @@ module Addressable
|
|
1332
1377
|
# Determines if the URI is relative.
|
1333
1378
|
#
|
1334
1379
|
# @return [TrueClass, FalseClass]
|
1335
|
-
#
|
1336
|
-
# <tt>false</tt> otherwise.
|
1380
|
+
# <tt>true</tt> if the URI is relative. <tt>false</tt> otherwise.
|
1337
1381
|
def relative?
|
1338
1382
|
return self.scheme.nil?
|
1339
1383
|
end
|
@@ -1342,8 +1386,7 @@ module Addressable
|
|
1342
1386
|
# Determines if the URI is absolute.
|
1343
1387
|
#
|
1344
1388
|
# @return [TrueClass, FalseClass]
|
1345
|
-
#
|
1346
|
-
# <tt>false</tt> otherwise.
|
1389
|
+
# <tt>true</tt> if the URI is absolute. <tt>false</tt> otherwise.
|
1347
1390
|
def absolute?
|
1348
1391
|
return !relative?
|
1349
1392
|
end
|
@@ -1463,9 +1506,9 @@ module Addressable
|
|
1463
1506
|
|
1464
1507
|
##
|
1465
1508
|
# Merges a URI with a <tt>Hash</tt> of components.
|
1466
|
-
# This method has different behavior from <tt>join</tt>.
|
1509
|
+
# This method has different behavior from <tt>join</tt>. Any components
|
1467
1510
|
# present in the <tt>hash</tt> parameter will override the original
|
1468
|
-
# components.
|
1511
|
+
# components. The path component is not treated specially.
|
1469
1512
|
#
|
1470
1513
|
# @param [Hash, Addressable::URI, #to_hash] The components to merge with.
|
1471
1514
|
#
|
@@ -1541,8 +1584,8 @@ module Addressable
|
|
1541
1584
|
|
1542
1585
|
##
|
1543
1586
|
# Returns the shortest normalized relative form of this URI that uses the
|
1544
|
-
# supplied URI as a base for resolution.
|
1545
|
-
# necessary.
|
1587
|
+
# supplied URI as a base for resolution. Returns an absolute URI if
|
1588
|
+
# necessary. This is effectively the opposite of <tt>route_to</tt>.
|
1546
1589
|
#
|
1547
1590
|
# @param [String, Addressable::URI, #to_str] uri The URI to route from.
|
1548
1591
|
#
|
@@ -1599,8 +1642,8 @@ module Addressable
|
|
1599
1642
|
|
1600
1643
|
##
|
1601
1644
|
# Returns the shortest normalized relative form of the supplied URI that
|
1602
|
-
# uses this URI as a base for resolution.
|
1603
|
-
# necessary.
|
1645
|
+
# uses this URI as a base for resolution. Returns an absolute URI if
|
1646
|
+
# necessary. This is effectively the opposite of <tt>route_from</tt>.
|
1604
1647
|
#
|
1605
1648
|
# @param [String, Addressable::URI, #to_str] uri The URI to route to.
|
1606
1649
|
#
|
@@ -1651,7 +1694,7 @@ module Addressable
|
|
1651
1694
|
end
|
1652
1695
|
|
1653
1696
|
##
|
1654
|
-
# Creates a URI suitable for display to users.
|
1697
|
+
# Creates a URI suitable for display to users. If semantic attacks are
|
1655
1698
|
# likely, the application should try to detect these and warn the user.
|
1656
1699
|
# See <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>,
|
1657
1700
|
# section 7.6 for more information.
|
@@ -1664,7 +1707,7 @@ module Addressable
|
|
1664
1707
|
end
|
1665
1708
|
|
1666
1709
|
##
|
1667
|
-
# Returns <tt>true</tt> if the URI objects are equal.
|
1710
|
+
# Returns <tt>true</tt> if the URI objects are equal. This method
|
1668
1711
|
# normalizes both URIs before doing the comparison, and allows comparison
|
1669
1712
|
# against <tt>Strings</tt>.
|
1670
1713
|
#
|
@@ -1686,7 +1729,7 @@ module Addressable
|
|
1686
1729
|
end
|
1687
1730
|
|
1688
1731
|
##
|
1689
|
-
# Returns <tt>true</tt> if the URI objects are equal.
|
1732
|
+
# Returns <tt>true</tt> if the URI objects are equal. This method
|
1690
1733
|
# normalizes both URIs before doing the comparison.
|
1691
1734
|
#
|
1692
1735
|
# @param [Object] uri The URI to compare.
|
@@ -1699,7 +1742,7 @@ module Addressable
|
|
1699
1742
|
end
|
1700
1743
|
|
1701
1744
|
##
|
1702
|
-
# Returns <tt>true</tt> if the URI objects are equal.
|
1745
|
+
# Returns <tt>true</tt> if the URI objects are equal. This method
|
1703
1746
|
# does NOT normalize either URI before doing the comparison.
|
1704
1747
|
#
|
1705
1748
|
# @param [Object] uri The URI to compare.
|
@@ -1746,7 +1789,7 @@ module Addressable
|
|
1746
1789
|
# Unfortunately, because of the memoized implementation of many of the
|
1747
1790
|
# URI methods, the default freeze method will cause unexpected errors.
|
1748
1791
|
# As an alternative, we freeze the string representation of the URI
|
1749
|
-
# instead.
|
1792
|
+
# instead. This should generally produce the desired effect.
|
1750
1793
|
self.to_s.freeze
|
1751
1794
|
return self
|
1752
1795
|
end
|
@@ -1823,7 +1866,7 @@ module Addressable
|
|
1823
1866
|
end
|
1824
1867
|
|
1825
1868
|
##
|
1826
|
-
# URI's are glorified <tt>Strings</tt>.
|
1869
|
+
# URI's are glorified <tt>Strings</tt>. Allow implicit conversion.
|
1827
1870
|
alias_method :to_str, :to_s
|
1828
1871
|
|
1829
1872
|
##
|
data/lib/addressable/version.rb
CHANGED
@@ -22,9 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
#++
|
24
24
|
|
25
|
-
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
|
26
|
-
$:.uniq!
|
27
|
-
|
28
25
|
require "addressable/idna"
|
29
26
|
|
30
27
|
describe Addressable::IDNA, "when converting from unicode to ASCII" do
|
@@ -22,10 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
#++
|
24
24
|
|
25
|
-
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
|
26
|
-
$:.uniq!
|
27
|
-
|
28
|
-
require "addressable/uri"
|
29
25
|
require "addressable/template"
|
30
26
|
|
31
27
|
if !"".respond_to?("force_encoding")
|
@@ -1341,6 +1337,54 @@ describe Addressable::URI, "when given a simple mapping" do
|
|
1341
1337
|
end
|
1342
1338
|
end
|
1343
1339
|
|
1340
|
+
describe Addressable::URI, "extracting defaults from a pattern" do
|
1341
|
+
before do
|
1342
|
+
@template = Addressable::Template.new("{foo}{bar=baz}{-opt|found|cond}")
|
1343
|
+
end
|
1344
|
+
|
1345
|
+
it "should extract default value" do
|
1346
|
+
@template.variable_defaults.should == {"bar" => "baz"}
|
1347
|
+
end
|
1348
|
+
end
|
1349
|
+
|
1350
|
+
describe Addressable::URI, "when given a mapping with symbol keys" do
|
1351
|
+
before do
|
1352
|
+
@mapping = { :name => "fred" }
|
1353
|
+
end
|
1354
|
+
|
1355
|
+
it "should result in 'fred' when used to expand '{foo}'" do
|
1356
|
+
Addressable::Template.new(
|
1357
|
+
"{name}"
|
1358
|
+
).expand(@mapping).to_s.should == "fred"
|
1359
|
+
end
|
1360
|
+
end
|
1361
|
+
|
1362
|
+
describe Addressable::URI, "when given a mapping with bogus keys" do
|
1363
|
+
before do
|
1364
|
+
@mapping = { Object.new => "fred" }
|
1365
|
+
end
|
1366
|
+
|
1367
|
+
it "should raise an error" do
|
1368
|
+
(lambda do
|
1369
|
+
Addressable::Template.new(
|
1370
|
+
"{name}"
|
1371
|
+
).expand(@mapping)
|
1372
|
+
end).should raise_error(TypeError)
|
1373
|
+
end
|
1374
|
+
end
|
1375
|
+
|
1376
|
+
describe Addressable::URI, "when given a mapping with numeric values" do
|
1377
|
+
before do
|
1378
|
+
@mapping = { :id => 123 }
|
1379
|
+
end
|
1380
|
+
|
1381
|
+
it "should result in 'fred' when used to expand '{foo}'" do
|
1382
|
+
Addressable::Template.new(
|
1383
|
+
"{id}"
|
1384
|
+
).expand(@mapping).to_s.should == "123"
|
1385
|
+
end
|
1386
|
+
end
|
1387
|
+
|
1344
1388
|
describe Addressable::URI, "when given a mapping containing values " +
|
1345
1389
|
"that are already percent-encoded" do
|
1346
1390
|
before do
|
@@ -1357,18 +1401,6 @@ describe Addressable::URI, "when given a mapping containing values " +
|
|
1357
1401
|
end
|
1358
1402
|
end
|
1359
1403
|
|
1360
|
-
describe Addressable::URI, "when given a mapping containing bogus values" do
|
1361
|
-
it "should raise a TypeError" do
|
1362
|
-
(lambda do
|
1363
|
-
Addressable::Template.new(
|
1364
|
-
"http://example.com/{bogus}/"
|
1365
|
-
).expand({
|
1366
|
-
"bogus" => 42
|
1367
|
-
})
|
1368
|
-
end).should raise_error(TypeError)
|
1369
|
-
end
|
1370
|
-
end
|
1371
|
-
|
1372
1404
|
describe Addressable::URI, "when given a pattern with bogus operators" do
|
1373
1405
|
it "should raise an InvalidTemplateOperatorError" do
|
1374
1406
|
(lambda do
|
@@ -22,9 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
#++
|
24
24
|
|
25
|
-
$:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../lib'))
|
26
|
-
$:.uniq!
|
27
|
-
|
28
25
|
require "addressable/uri"
|
29
26
|
|
30
27
|
if !"".respond_to?("force_encoding")
|
@@ -72,6 +69,86 @@ describe Addressable::URI, "when created with a non-numeric port number" do
|
|
72
69
|
end
|
73
70
|
end
|
74
71
|
|
72
|
+
describe Addressable::URI, "when created with a non-string scheme" do
|
73
|
+
it "should raise an error" do
|
74
|
+
(lambda do
|
75
|
+
Addressable::URI.new(:scheme => :bogus)
|
76
|
+
end).should raise_error(TypeError)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
describe Addressable::URI, "when created with a non-string user" do
|
81
|
+
it "should raise an error" do
|
82
|
+
(lambda do
|
83
|
+
Addressable::URI.new(:user => :bogus)
|
84
|
+
end).should raise_error(TypeError)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe Addressable::URI, "when created with a non-string password" do
|
89
|
+
it "should raise an error" do
|
90
|
+
(lambda do
|
91
|
+
Addressable::URI.new(:password => :bogus)
|
92
|
+
end).should raise_error(TypeError)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe Addressable::URI, "when created with a non-string userinfo" do
|
97
|
+
it "should raise an error" do
|
98
|
+
(lambda do
|
99
|
+
Addressable::URI.new(:userinfo => :bogus)
|
100
|
+
end).should raise_error(TypeError)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe Addressable::URI, "when created with a non-string host" do
|
105
|
+
it "should raise an error" do
|
106
|
+
(lambda do
|
107
|
+
Addressable::URI.new(:host => :bogus)
|
108
|
+
end).should raise_error(TypeError)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
describe Addressable::URI, "when created with a non-string authority" do
|
113
|
+
it "should raise an error" do
|
114
|
+
(lambda do
|
115
|
+
Addressable::URI.new(:authority => :bogus)
|
116
|
+
end).should raise_error(TypeError)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe Addressable::URI, "when created with a non-string authority" do
|
121
|
+
it "should raise an error" do
|
122
|
+
(lambda do
|
123
|
+
Addressable::URI.new(:authority => :bogus)
|
124
|
+
end).should raise_error(TypeError)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe Addressable::URI, "when created with a non-string path" do
|
129
|
+
it "should raise an error" do
|
130
|
+
(lambda do
|
131
|
+
Addressable::URI.new(:path => :bogus)
|
132
|
+
end).should raise_error(TypeError)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe Addressable::URI, "when created with a non-string query" do
|
137
|
+
it "should raise an error" do
|
138
|
+
(lambda do
|
139
|
+
Addressable::URI.new(:query => :bogus)
|
140
|
+
end).should raise_error(TypeError)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe Addressable::URI, "when created with a non-string fragment" do
|
145
|
+
it "should raise an error" do
|
146
|
+
(lambda do
|
147
|
+
Addressable::URI.new(:fragment => :bogus)
|
148
|
+
end).should raise_error(TypeError)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
75
152
|
describe Addressable::URI, "when created with a scheme but no hierarchical " +
|
76
153
|
"segment" do
|
77
154
|
it "should raise an error" do
|
@@ -944,6 +1021,54 @@ describe Addressable::URI, "when parsed from " +
|
|
944
1021
|
end
|
945
1022
|
end
|
946
1023
|
|
1024
|
+
describe Addressable::URI, "when parsed from " +
|
1025
|
+
"'http://example.com/?%F6'" do
|
1026
|
+
before do
|
1027
|
+
@uri = Addressable::URI.parse("http://example.com/?%F6")
|
1028
|
+
end
|
1029
|
+
|
1030
|
+
it "should not raise an exception when normalized" do
|
1031
|
+
(lambda do
|
1032
|
+
@uri.normalize
|
1033
|
+
end).should_not raise_error(ArgumentError)
|
1034
|
+
end
|
1035
|
+
|
1036
|
+
it "should be considered to be in normal form" do
|
1037
|
+
@uri.normalize.should be_eql(@uri)
|
1038
|
+
end
|
1039
|
+
|
1040
|
+
it "should not change if encoded with the normalizing algorithm" do
|
1041
|
+
Addressable::URI.normalized_encode(@uri).to_s.should ==
|
1042
|
+
"http://example.com/?%F6"
|
1043
|
+
Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
|
1044
|
+
"http://example.com/?%F6"
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
describe Addressable::URI, "when parsed from " +
|
1049
|
+
"'http://example.com/#%F6'" do
|
1050
|
+
before do
|
1051
|
+
@uri = Addressable::URI.parse("http://example.com/#%F6")
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
it "should not raise an exception when normalized" do
|
1055
|
+
(lambda do
|
1056
|
+
@uri.normalize
|
1057
|
+
end).should_not raise_error(ArgumentError)
|
1058
|
+
end
|
1059
|
+
|
1060
|
+
it "should be considered to be in normal form" do
|
1061
|
+
@uri.normalize.should be_eql(@uri)
|
1062
|
+
end
|
1063
|
+
|
1064
|
+
it "should not change if encoded with the normalizing algorithm" do
|
1065
|
+
Addressable::URI.normalized_encode(@uri).to_s.should ==
|
1066
|
+
"http://example.com/#%F6"
|
1067
|
+
Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
|
1068
|
+
"http://example.com/#%F6"
|
1069
|
+
end
|
1070
|
+
end
|
1071
|
+
|
947
1072
|
describe Addressable::URI, "when parsed from " +
|
948
1073
|
"'http://example.com/%C3%87'" do
|
949
1074
|
before do
|
data/tasks/spec.rake
CHANGED
@@ -1,14 +1,10 @@
|
|
1
|
-
require 'spec/rake/verify_rcov'
|
2
|
-
|
3
1
|
namespace :spec do
|
4
2
|
Spec::Rake::SpecTask.new(:rcov) do |t|
|
3
|
+
t.libs = %w[lib spec]
|
5
4
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
6
5
|
t.spec_opts = ['--color', '--format', 'specdoc']
|
7
|
-
|
8
|
-
|
9
|
-
else
|
10
|
-
t.rcov = false
|
11
|
-
end
|
6
|
+
|
7
|
+
t.rcov = RCOV_ENABLED
|
12
8
|
t.rcov_opts = [
|
13
9
|
'--exclude', 'spec',
|
14
10
|
'--exclude', '1\\.8\\/gems',
|
@@ -18,27 +14,19 @@ namespace :spec do
|
|
18
14
|
end
|
19
15
|
|
20
16
|
Spec::Rake::SpecTask.new(:normal) do |t|
|
17
|
+
t.libs = %w[lib spec]
|
21
18
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
22
19
|
t.spec_opts = ['--color', '--format', 'specdoc']
|
23
20
|
t.rcov = false
|
24
21
|
end
|
25
22
|
|
26
|
-
if RCOV_ENABLED
|
27
|
-
RCov::VerifyTask.new(:verify) do |t|
|
28
|
-
t.threshold = 100.0
|
29
|
-
t.index_html = 'coverage/index.html'
|
30
|
-
end
|
31
|
-
|
32
|
-
task :verify => :rcov
|
33
|
-
end
|
34
|
-
|
35
23
|
desc "Generate HTML Specdocs for all specs"
|
36
24
|
Spec::Rake::SpecTask.new(:specdoc) do |t|
|
37
|
-
specdoc_path = File.expand_path(
|
38
|
-
File.join(File.dirname(__FILE__), '../specdoc/'))
|
25
|
+
specdoc_path = File.expand_path(File.join(File.dirname(__FILE__), '..', 'specdoc'))
|
39
26
|
Dir.mkdir(specdoc_path) if !File.exist?(specdoc_path)
|
40
27
|
|
41
28
|
output_file = File.join(specdoc_path, 'index.html')
|
29
|
+
t.libs = %w[lib spec]
|
42
30
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
43
31
|
t.spec_opts = ["--format", "\"html:#{output_file}\"", "--diff"]
|
44
32
|
t.fail_on_error = false
|
@@ -53,12 +41,7 @@ namespace :spec do
|
|
53
41
|
end
|
54
42
|
end
|
55
43
|
|
56
|
-
|
57
|
-
|
58
|
-
task "spec" => "spec:verify"
|
59
|
-
else
|
60
|
-
desc "Alias to spec:normal"
|
61
|
-
task "spec" => "spec:normal"
|
62
|
-
end
|
44
|
+
desc "Alias to spec:normal"
|
45
|
+
task "spec" => "spec:normal"
|
63
46
|
|
64
47
|
task "clobber" => ["spec:clobber_rcov"]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: addressable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bob Aman
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-10-31 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -42,7 +42,11 @@ dependencies:
|
|
42
42
|
- !ruby/object:Gem::Version
|
43
43
|
version: 0.3.2
|
44
44
|
version:
|
45
|
-
description:
|
45
|
+
description: |
|
46
|
+
Addressable is a replacement for the URI implementation that is part of
|
47
|
+
Ruby's standard library. It more closely conforms to the relevant RFCs and
|
48
|
+
adds support for IRIs and URI templates.
|
49
|
+
|
46
50
|
email: bob@sporkmonger.com
|
47
51
|
executables: []
|
48
52
|
|
@@ -51,16 +55,13 @@ extensions: []
|
|
51
55
|
extra_rdoc_files:
|
52
56
|
- README
|
53
57
|
files:
|
54
|
-
- lib/addressable
|
55
58
|
- lib/addressable/idna.rb
|
56
59
|
- lib/addressable/template.rb
|
57
60
|
- lib/addressable/uri.rb
|
58
61
|
- lib/addressable/version.rb
|
59
|
-
- spec/addressable
|
60
62
|
- spec/addressable/idna_spec.rb
|
61
63
|
- spec/addressable/template_spec.rb
|
62
64
|
- spec/addressable/uri_spec.rb
|
63
|
-
- spec/data
|
64
65
|
- spec/data/rfc3986.txt
|
65
66
|
- tasks/clobber.rake
|
66
67
|
- tasks/gem.rake
|
@@ -76,6 +77,8 @@ files:
|
|
76
77
|
- README
|
77
78
|
has_rdoc: true
|
78
79
|
homepage: http://addressable.rubyforge.org/
|
80
|
+
licenses: []
|
81
|
+
|
79
82
|
post_install_message:
|
80
83
|
rdoc_options:
|
81
84
|
- --main
|
@@ -97,9 +100,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
97
100
|
requirements: []
|
98
101
|
|
99
102
|
rubyforge_project: addressable
|
100
|
-
rubygems_version: 1.3.
|
103
|
+
rubygems_version: 1.3.5
|
101
104
|
signing_key:
|
102
|
-
specification_version:
|
105
|
+
specification_version: 3
|
103
106
|
summary: URI Implementation
|
104
107
|
test_files: []
|
105
108
|
|