addressable 2.1.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
|