addressable 2.3.2 → 2.3.3
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of addressable might be problematic. Click here for more details.
- data/CHANGELOG.md +9 -0
- data/Gemfile +2 -1
- data/lib/addressable/template.rb +13 -7
- data/lib/addressable/uri.rb +67 -30
- data/lib/addressable/version.rb +1 -1
- data/spec/addressable/template_spec.rb +21 -0
- data/spec/addressable/uri_spec.rb +100 -3
- data/tasks/gem.rake +1 -0
- metadata +67 -54
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
# Addressable 2.3.3
|
2
|
+
- fixed issue with converting common primitives during template expansion
|
3
|
+
- fixed port encoding issue
|
4
|
+
- removed a few warnings
|
5
|
+
- normalize should now ignore %2B in query strings
|
6
|
+
- the IDNA logic should now be handled by libidn in Ruby 1.9
|
7
|
+
- no template match should now result in nil instead of an empty MatchData
|
8
|
+
- added license information to gemspec
|
9
|
+
|
1
10
|
# Addressable 2.3.2
|
2
11
|
- added Addressable::URI#default_port method
|
3
12
|
- fixed issue with Marshalling Unicode data on Windows
|
data/Gemfile
CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
|
|
3
3
|
group :development do
|
4
4
|
gem 'launchy'
|
5
5
|
gem 'yard'
|
6
|
-
gem 'redcarpet'
|
6
|
+
gem 'redcarpet', :platform => :mri_19
|
7
7
|
gem 'rubyforge'
|
8
8
|
end
|
9
9
|
|
@@ -13,5 +13,6 @@ group :test, :development do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
gem 'idn', :platform => :mri_18
|
16
|
+
gem 'idn-ruby', :platform => :mri_19
|
16
17
|
|
17
18
|
gemspec
|
data/lib/addressable/template.rb
CHANGED
@@ -317,6 +317,8 @@ module Addressable
|
|
317
317
|
# First, we need to process the pattern, and extract the values.
|
318
318
|
expansions, expansion_regexp =
|
319
319
|
parse_template_pattern(pattern, processor)
|
320
|
+
|
321
|
+
return nil unless uri.to_str.match(expansion_regexp)
|
320
322
|
unparsed_values = uri.to_str.scan(expansion_regexp).flatten
|
321
323
|
|
322
324
|
if uri.to_str == pattern
|
@@ -513,11 +515,11 @@ module Addressable
|
|
513
515
|
private
|
514
516
|
def ordered_variable_defaults
|
515
517
|
@ordered_variable_defaults ||= (
|
516
|
-
expansions,
|
518
|
+
expansions, _ = parse_template_pattern(pattern)
|
517
519
|
expansions.map do |capture|
|
518
|
-
_,
|
520
|
+
_, _, varlist = *capture.match(EXPRESSION)
|
519
521
|
varlist.split(',').map do |varspec|
|
520
|
-
|
522
|
+
varspec[VARSPEC, 1]
|
521
523
|
end
|
522
524
|
end.flatten
|
523
525
|
)
|
@@ -551,7 +553,7 @@ module Addressable
|
|
551
553
|
_, operator, varlist = *capture.match(EXPRESSION)
|
552
554
|
is_first = true
|
553
555
|
varlist.split(',').inject('') do |acc, varspec|
|
554
|
-
_, name,
|
556
|
+
_, name, _ = *varspec.match(VARSPEC)
|
555
557
|
value = mapping[name]
|
556
558
|
if value
|
557
559
|
operator = '&' if !is_first && operator == '?'
|
@@ -595,7 +597,11 @@ module Addressable
|
|
595
597
|
value = mapping[name]
|
596
598
|
unless value == nil || value == {}
|
597
599
|
allow_reserved = %w(+ #).include?(operator)
|
598
|
-
|
600
|
+
# Common primitives where the .to_s output is well-defined
|
601
|
+
if Numeric === value || Symbol === value ||
|
602
|
+
value == true || value == false
|
603
|
+
value = value.to_s
|
604
|
+
end
|
599
605
|
length = modifier.gsub(':', '').to_i if modifier =~ /^:\d+/
|
600
606
|
|
601
607
|
unless (Hash === value) ||
|
@@ -698,7 +704,7 @@ module Addressable
|
|
698
704
|
if v.is_a?(Array) && v.first =~ /=/
|
699
705
|
v.join(joiner)
|
700
706
|
elsif v.is_a?(Array)
|
701
|
-
v.map{|
|
707
|
+
v.map{|inner_value| "#{k}=#{inner_value}"}.join(joiner)
|
702
708
|
else
|
703
709
|
"#{k}=#{v}"
|
704
710
|
end
|
@@ -708,7 +714,7 @@ module Addressable
|
|
708
714
|
if v.is_a?(Array) && v.first =~ /=/
|
709
715
|
';' + v.join(";")
|
710
716
|
elsif v.is_a?(Array)
|
711
|
-
';' + v.map{|
|
717
|
+
';' + v.map{|inner_value| "#{k}=#{inner_value}"}.join(";")
|
712
718
|
else
|
713
719
|
v && v != '' ? ";#{k}=#{v}" : ";#{k}"
|
714
720
|
end
|
data/lib/addressable/uri.rb
CHANGED
@@ -315,6 +315,12 @@ module Addressable
|
|
315
315
|
# value is the reserved plus unreserved character classes specified in
|
316
316
|
# <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
|
317
317
|
#
|
318
|
+
# @param [Regexp] upcase_encoded
|
319
|
+
# A string of characters that may already be percent encoded, and whose
|
320
|
+
# encodings should be upcased. This allows normalization of percent
|
321
|
+
# encodings for characters not included in the
|
322
|
+
# <code>character_class</code>.
|
323
|
+
#
|
318
324
|
# @return [String] The encoded component.
|
319
325
|
#
|
320
326
|
# @example
|
@@ -327,11 +333,15 @@ module Addressable
|
|
327
333
|
# )
|
328
334
|
# => "simple%2Fexample"
|
329
335
|
def self.encode_component(component, character_class=
|
330
|
-
CharacterClasses::RESERVED + CharacterClasses::UNRESERVED
|
336
|
+
CharacterClasses::RESERVED + CharacterClasses::UNRESERVED,
|
337
|
+
upcase_encoded='')
|
331
338
|
return nil if component.nil?
|
332
339
|
|
333
340
|
begin
|
334
|
-
if component.kind_of?(Symbol) ||
|
341
|
+
if component.kind_of?(Symbol) ||
|
342
|
+
component.kind_of?(Numeric) ||
|
343
|
+
component.kind_of?(TrueClass) ||
|
344
|
+
component.kind_of?(FalseClass)
|
335
345
|
component = component.to_s
|
336
346
|
else
|
337
347
|
component = component.to_str
|
@@ -353,9 +363,15 @@ module Addressable
|
|
353
363
|
component = component.dup
|
354
364
|
component.force_encoding(Encoding::ASCII_8BIT)
|
355
365
|
end
|
356
|
-
|
366
|
+
component.gsub!(character_class) do |sequence|
|
357
367
|
(sequence.unpack('C*').map { |c| "%" + ("%02x" % c).upcase }).join
|
358
368
|
end
|
369
|
+
if upcase_encoded.length > 0
|
370
|
+
component.gsub!(/%(#{upcase_encoded.chars.map do |char|
|
371
|
+
char.unpack('C*').map { |c| '%02x' % c }.join
|
372
|
+
end.join('|')})/i) { |s| s.upcase }
|
373
|
+
end
|
374
|
+
return component
|
359
375
|
end
|
360
376
|
|
361
377
|
class << self
|
@@ -377,11 +393,15 @@ module Addressable
|
|
377
393
|
# <code>Addressable::URI</code>. All other values are invalid. Defaults
|
378
394
|
# to <code>String</code>.
|
379
395
|
#
|
396
|
+
# @param [String] leave_encoded
|
397
|
+
# A string of characters to leave encoded. If a percent encoded character
|
398
|
+
# in this list is encountered then it will remain percent encoded.
|
399
|
+
#
|
380
400
|
# @return [String, Addressable::URI]
|
381
401
|
# The unencoded component or URI.
|
382
402
|
# The return type is determined by the <code>return_type</code>
|
383
403
|
# parameter.
|
384
|
-
def self.unencode(uri, return_type=String)
|
404
|
+
def self.unencode(uri, return_type=String, leave_encoded='')
|
385
405
|
return nil if uri.nil?
|
386
406
|
|
387
407
|
begin
|
@@ -395,7 +415,8 @@ module Addressable
|
|
395
415
|
"got #{return_type.inspect}"
|
396
416
|
end
|
397
417
|
result = uri.gsub(/%[0-9a-f]{2}/i) do |sequence|
|
398
|
-
sequence[1..3].to_i(16).chr
|
418
|
+
c = sequence[1..3].to_i(16).chr
|
419
|
+
leave_encoded.include?(c) ? sequence : c
|
399
420
|
end
|
400
421
|
result.force_encoding("utf-8") if result.respond_to?(:force_encoding)
|
401
422
|
if return_type == String
|
@@ -430,6 +451,13 @@ module Addressable
|
|
430
451
|
# value is the reserved plus unreserved character classes specified in
|
431
452
|
# <a href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>.
|
432
453
|
#
|
454
|
+
# @param [String] leave_encoded
|
455
|
+
# When <code>character_class</code> is a <code>String</code> then
|
456
|
+
# <code>leave_encoded</code> is a string of characters that should remain
|
457
|
+
# percent encoded while normalizing the component; if they appear percent
|
458
|
+
# encoded in the original component, then they will be upcased ("%2f"
|
459
|
+
# normalized to "%2F") but otherwise left alone.
|
460
|
+
#
|
433
461
|
# @return [String] The normalized component.
|
434
462
|
#
|
435
463
|
# @example
|
@@ -444,8 +472,15 @@ module Addressable
|
|
444
472
|
# Addressable::URI::CharacterClasses::UNRESERVED
|
445
473
|
# )
|
446
474
|
# => "simple%2Fexample"
|
475
|
+
# Addressable::URI.normalize_component(
|
476
|
+
# "one%20two%2fthree%26four",
|
477
|
+
# "0-9a-zA-Z &/",
|
478
|
+
# "/"
|
479
|
+
# )
|
480
|
+
# => "one two%2Fthree&four"
|
447
481
|
def self.normalize_component(component, character_class=
|
448
|
-
CharacterClasses::RESERVED + CharacterClasses::UNRESERVED
|
482
|
+
CharacterClasses::RESERVED + CharacterClasses::UNRESERVED,
|
483
|
+
leave_encoded='')
|
449
484
|
return nil if component.nil?
|
450
485
|
|
451
486
|
begin
|
@@ -459,7 +494,16 @@ module Addressable
|
|
459
494
|
"Expected String or Regexp, got #{character_class.inspect}"
|
460
495
|
end
|
461
496
|
if character_class.kind_of?(String)
|
462
|
-
|
497
|
+
leave_re = if leave_encoded.length > 0
|
498
|
+
character_class << '%'
|
499
|
+
|
500
|
+
"|%(?!#{leave_encoded.chars.map do |char|
|
501
|
+
seq = char.unpack('C*').map { |c| '%02x' % c }.join
|
502
|
+
[seq.upcase, seq.downcase]
|
503
|
+
end.flatten.join('|')})"
|
504
|
+
end
|
505
|
+
|
506
|
+
character_class = /[^#{character_class}]#{leave_re}/
|
463
507
|
end
|
464
508
|
if component.respond_to?(:force_encoding)
|
465
509
|
# We can't perform regexps on invalid UTF sequences, but
|
@@ -467,11 +511,12 @@ module Addressable
|
|
467
511
|
component = component.dup
|
468
512
|
component.force_encoding(Encoding::ASCII_8BIT)
|
469
513
|
end
|
470
|
-
unencoded = self.unencode_component(component)
|
514
|
+
unencoded = self.unencode_component(component, String, leave_encoded)
|
471
515
|
begin
|
472
516
|
encoded = self.encode_component(
|
473
517
|
Addressable::IDNA.unicode_normalize_kc(unencoded),
|
474
|
-
character_class
|
518
|
+
character_class,
|
519
|
+
leave_encoded
|
475
520
|
)
|
476
521
|
rescue ArgumentError
|
477
522
|
encoded = self.encode_component(unencoded)
|
@@ -568,7 +613,7 @@ module Addressable
|
|
568
613
|
:user => self.unencode_component(uri_object.user),
|
569
614
|
:password => self.unencode_component(uri_object.password),
|
570
615
|
:host => self.unencode_component(uri_object.host),
|
571
|
-
:port => uri_object.port,
|
616
|
+
:port => (uri_object.port.nil? ? nil : uri_object.port.to_s),
|
572
617
|
:path => self.unencode_component(uri_object.path),
|
573
618
|
:query => self.unencode_component(uri_object.query),
|
574
619
|
:fragment => self.unencode_component(uri_object.fragment)
|
@@ -999,21 +1044,17 @@ module Addressable
|
|
999
1044
|
# @return [String] The host component, normalized.
|
1000
1045
|
def normalized_host
|
1001
1046
|
self.host && @normalized_host ||= (begin
|
1002
|
-
if self.host
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
result = result[0...-1]
|
1010
|
-
end
|
1011
|
-
result
|
1012
|
-
else
|
1013
|
-
EMPTY_STR
|
1047
|
+
if !self.host.strip.empty?
|
1048
|
+
result = ::Addressable::IDNA.to_ascii(
|
1049
|
+
URI.unencode_component(self.host.strip.downcase)
|
1050
|
+
)
|
1051
|
+
if result[-1..-1] == "."
|
1052
|
+
# Trailing dots are unnecessary
|
1053
|
+
result = result[0...-1]
|
1014
1054
|
end
|
1055
|
+
result
|
1015
1056
|
else
|
1016
|
-
|
1057
|
+
EMPTY_STR
|
1017
1058
|
end
|
1018
1059
|
end)
|
1019
1060
|
end
|
@@ -1392,7 +1433,8 @@ module Addressable
|
|
1392
1433
|
(self.query.split("&", -1).map do |pair|
|
1393
1434
|
Addressable::URI.normalize_component(
|
1394
1435
|
pair,
|
1395
|
-
Addressable::URI::CharacterClasses::QUERY.sub("\\&", "")
|
1436
|
+
Addressable::URI::CharacterClasses::QUERY.sub("\\&", ""),
|
1437
|
+
'+'
|
1396
1438
|
)
|
1397
1439
|
end).join("&")
|
1398
1440
|
end)
|
@@ -1443,11 +1485,6 @@ module Addressable
|
|
1443
1485
|
# but in this case I really want to maintain the exact pair structure,
|
1444
1486
|
# so it's best to make all changes in-place.
|
1445
1487
|
pair[0] = URI.unencode_component(pair[0])
|
1446
|
-
# This looks weird, but it's correct. Handles query values like:
|
1447
|
-
# ?data=1&flag&color=blue
|
1448
|
-
# In this case, `flag` would evaluate to `true`, which is what you
|
1449
|
-
# want. Its absence implies that `flag` resolves to `false`.
|
1450
|
-
# value = true if value.nil?
|
1451
1488
|
if pair[1].respond_to?(:to_str)
|
1452
1489
|
# I loathe the fact that I have to do this. Stupid HTML 4.01.
|
1453
1490
|
# Treating '+' as a space was just an unbelievably bad idea.
|
@@ -1510,7 +1547,7 @@ module Addressable
|
|
1510
1547
|
encoded_key = URI.encode_component(
|
1511
1548
|
key, CharacterClasses::UNRESERVED
|
1512
1549
|
)
|
1513
|
-
if value == nil
|
1550
|
+
if value == nil
|
1514
1551
|
buffer << "#{encoded_key}&"
|
1515
1552
|
elsif value.kind_of?(Array)
|
1516
1553
|
value.each do |sub_value|
|
data/lib/addressable/version.rb
CHANGED
@@ -14,6 +14,18 @@ shared_examples_for 'expands' do |tests|
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
describe "Type conversion" do
|
18
|
+
subject{
|
19
|
+
{:var => true, :hello => 1234, :nothing => nil, :sym => :symbolic}
|
20
|
+
}
|
21
|
+
it_behaves_like 'expands', {
|
22
|
+
'{var}' => 'true',
|
23
|
+
'{hello}' => '1234',
|
24
|
+
'{nothing}' => '',
|
25
|
+
'{sym}' => 'symbolic'
|
26
|
+
}
|
27
|
+
end
|
28
|
+
|
17
29
|
describe "Level 1:" do
|
18
30
|
subject{
|
19
31
|
{:var => "value", :hello => "Hello World!"}
|
@@ -815,6 +827,15 @@ describe Addressable::Template do
|
|
815
827
|
data.mapping["foo"].should == "foo"
|
816
828
|
data.mapping["bar"].should == "banana"
|
817
829
|
end
|
830
|
+
it "can fail" do
|
831
|
+
subject.match("bar/foo").should be_nil
|
832
|
+
subject.match("foobaz").should be_nil
|
833
|
+
end
|
834
|
+
it "can match empty" do
|
835
|
+
data = subject.match("foo/baz")
|
836
|
+
data.mapping["foo"].should == ""
|
837
|
+
data.mapping["bar"].should == ""
|
838
|
+
end
|
818
839
|
it "lists vars" do
|
819
840
|
subject.variables.should == ["foo", "bar"]
|
820
841
|
end
|
@@ -1840,6 +1840,13 @@ describe Addressable::URI, "when parsed from " +
|
|
1840
1840
|
it "should have an origin of 'http://example.com'" do
|
1841
1841
|
@uri.origin.should == 'http://example.com'
|
1842
1842
|
end
|
1843
|
+
|
1844
|
+
it "should not change if encoded with the normalizing algorithm" do
|
1845
|
+
Addressable::URI.normalized_encode(@uri).to_s.should ==
|
1846
|
+
"http://example.com:80/"
|
1847
|
+
Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
|
1848
|
+
"http://example.com:80/"
|
1849
|
+
end
|
1843
1850
|
end
|
1844
1851
|
|
1845
1852
|
describe Addressable::URI, "when parsed from " +
|
@@ -1949,6 +1956,13 @@ describe Addressable::URI, "when parsed from " +
|
|
1949
1956
|
it "should have an origin of 'http://example.com:8080'" do
|
1950
1957
|
@uri.origin.should == 'http://example.com:8080'
|
1951
1958
|
end
|
1959
|
+
|
1960
|
+
it "should not change if encoded with the normalizing algorithm" do
|
1961
|
+
Addressable::URI.normalized_encode(@uri).to_s.should ==
|
1962
|
+
"http://example.com:8080/"
|
1963
|
+
Addressable::URI.normalized_encode(@uri, Addressable::URI).to_s.should ===
|
1964
|
+
"http://example.com:8080/"
|
1965
|
+
end
|
1952
1966
|
end
|
1953
1967
|
|
1954
1968
|
describe Addressable::URI, "when parsed from " +
|
@@ -2934,7 +2948,7 @@ describe Addressable::URI, "when parsed from " +
|
|
2934
2948
|
end
|
2935
2949
|
|
2936
2950
|
it "should have the correct query string after flag hash assignment" do
|
2937
|
-
@uri.query_values = {'flag?1' =>
|
2951
|
+
@uri.query_values = {'flag?1' => nil, 'fl=ag2' => nil, 'flag3' => nil}
|
2938
2952
|
@uri.query.split("&").should include("flag%3F1")
|
2939
2953
|
@uri.query.split("&").should include("fl%3Dag2")
|
2940
2954
|
@uri.query.split("&").should include("flag3")
|
@@ -3146,6 +3160,10 @@ describe Addressable::URI, "when parsed from " +
|
|
3146
3160
|
it "should have query_values of {'q' => 'a b'}" do
|
3147
3161
|
@uri.query_values.should == {'q' => 'a b'}
|
3148
3162
|
end
|
3163
|
+
|
3164
|
+
it "should have a normalized query of 'q=a+b'" do
|
3165
|
+
@uri.normalized_query.should == "q=a+b"
|
3166
|
+
end
|
3149
3167
|
end
|
3150
3168
|
|
3151
3169
|
describe Addressable::URI, "when parsed from " +
|
@@ -3161,6 +3179,43 @@ describe Addressable::URI, "when parsed from " +
|
|
3161
3179
|
it "should have query_values of {'q' => 'a+b'}" do
|
3162
3180
|
@uri.query_values.should == {'q' => 'a+b'}
|
3163
3181
|
end
|
3182
|
+
|
3183
|
+
it "should have a normalized query of 'q=a%2Bb'" do
|
3184
|
+
@uri.normalized_query.should == "q=a%2Bb"
|
3185
|
+
end
|
3186
|
+
end
|
3187
|
+
|
3188
|
+
describe Addressable::URI, "when parsed from " +
|
3189
|
+
"'http://example.com/?v=%7E&w=%&x=%25&y=%2B&z=C%CC%A7'" do
|
3190
|
+
before do
|
3191
|
+
@uri = Addressable::URI.parse("http://example.com/?v=%7E&w=%&x=%25&y=%2B&z=C%CC%A7")
|
3192
|
+
end
|
3193
|
+
|
3194
|
+
it "should have a normalized query of 'v=~&w=%25&x=%25&y=%2B&z=%C3%87'" do
|
3195
|
+
@uri.normalized_query.should == "v=~&w=%25&x=%25&y=%2B&z=%C3%87"
|
3196
|
+
end
|
3197
|
+
end
|
3198
|
+
|
3199
|
+
describe Addressable::URI, "when parsed from " +
|
3200
|
+
"'http://example.com/?v=%7E&w=%&x=%25&y=+&z=C%CC%A7'" do
|
3201
|
+
before do
|
3202
|
+
@uri = Addressable::URI.parse("http://example.com/?v=%7E&w=%&x=%25&y=+&z=C%CC%A7")
|
3203
|
+
end
|
3204
|
+
|
3205
|
+
it "should have a normalized query of 'v=~&w=%25&x=%25&y=+&z=%C3%87'" do
|
3206
|
+
@uri.normalized_query.should == "v=~&w=%25&x=%25&y=+&z=%C3%87"
|
3207
|
+
end
|
3208
|
+
end
|
3209
|
+
|
3210
|
+
describe Addressable::URI, "when parsed from " +
|
3211
|
+
"'http://example.com/sound%2bvision'" do
|
3212
|
+
before do
|
3213
|
+
@uri = Addressable::URI.parse("http://example.com/sound%2bvision")
|
3214
|
+
end
|
3215
|
+
|
3216
|
+
it "should have a normalized path of '/sound+vision'" do
|
3217
|
+
@uri.normalized_path.should == '/sound+vision'
|
3218
|
+
end
|
3164
3219
|
end
|
3165
3220
|
|
3166
3221
|
describe Addressable::URI, "when parsed from " +
|
@@ -3771,13 +3826,20 @@ describe Addressable::URI, "when parsed from " +
|
|
3771
3826
|
"'?one=two&one=three'" do
|
3772
3827
|
before do
|
3773
3828
|
@uri = Addressable::URI.parse(
|
3774
|
-
"?one=two&one=three"
|
3829
|
+
"?one=two&one=three&one=four"
|
3775
3830
|
)
|
3776
3831
|
end
|
3777
3832
|
|
3778
3833
|
it "should have correct array query values" do
|
3779
3834
|
@uri.query_values(Array).should ==
|
3780
|
-
[['one', 'two'], ['one', 'three']]
|
3835
|
+
[['one', 'two'], ['one', 'three'], ['one', 'four']]
|
3836
|
+
end
|
3837
|
+
|
3838
|
+
it "should have correct hash query values" do
|
3839
|
+
pending("This is probably more desirable behavior.") do
|
3840
|
+
@uri.query_values(Hash).should ==
|
3841
|
+
{'one' => ['two', 'three', 'four']}
|
3842
|
+
end
|
3781
3843
|
end
|
3782
3844
|
end
|
3783
3845
|
|
@@ -4619,6 +4681,19 @@ describe Addressable::URI, "when normalizing a multibyte string" do
|
|
4619
4681
|
end
|
4620
4682
|
end
|
4621
4683
|
|
4684
|
+
describe Addressable::URI, "when normalizing a string but leaving some characters encoded" do
|
4685
|
+
it "should result in correct percent encoded sequence" do
|
4686
|
+
Addressable::URI.normalize_component("%58X%59Y%5AZ", "0-9a-zXY", "Y").should ==
|
4687
|
+
"XX%59Y%5A%5A"
|
4688
|
+
end
|
4689
|
+
end
|
4690
|
+
|
4691
|
+
describe Addressable::URI, "when encoding a string with existing encodings to upcase" do
|
4692
|
+
it "should result in correct percent encoded sequence" do
|
4693
|
+
Addressable::URI.encode_component("JK%4c", "0-9A-IKM-Za-z%", "L").should == "%4AK%4C"
|
4694
|
+
end
|
4695
|
+
end
|
4696
|
+
|
4622
4697
|
describe Addressable::URI, "when encoding a multibyte string" do
|
4623
4698
|
it "should result in correct percent encoded sequence" do
|
4624
4699
|
Addressable::URI.encode_component("günther").should == "g%C3%BCnther"
|
@@ -4664,6 +4739,20 @@ describe Addressable::URI, "when unencoding a multibyte string" do
|
|
4664
4739
|
end
|
4665
4740
|
end
|
4666
4741
|
|
4742
|
+
describe Addressable::URI, "when partially unencoding a string" do
|
4743
|
+
it "should unencode all characters by default" do
|
4744
|
+
Addressable::URI.unencode('%%25~%7e+%2b', String).should == '%%~~++'
|
4745
|
+
end
|
4746
|
+
|
4747
|
+
it "should unencode characters not in leave_encoded" do
|
4748
|
+
Addressable::URI.unencode('%%25~%7e+%2b', String, '~').should == '%%~%7e++'
|
4749
|
+
end
|
4750
|
+
|
4751
|
+
it "should leave characters in leave_encoded alone" do
|
4752
|
+
Addressable::URI.unencode('%%25~%7e+%2b', String, '%~+').should == '%%25~%7e+%2b'
|
4753
|
+
end
|
4754
|
+
end
|
4755
|
+
|
4667
4756
|
describe Addressable::URI, "when unencoding a bogus object" do
|
4668
4757
|
it "should raise a TypeError" do
|
4669
4758
|
(lambda do
|
@@ -5011,6 +5100,14 @@ describe Addressable::URI, "when assigning query values" do
|
|
5011
5100
|
@uri.query_values = @uri.query_values(Array)
|
5012
5101
|
@uri.to_s.should == original_uri
|
5013
5102
|
end
|
5103
|
+
|
5104
|
+
describe 'when a hash with mixed types is assigned to query_values' do
|
5105
|
+
it 'should not raise an error' do
|
5106
|
+
pending 'Issue #94' do
|
5107
|
+
expect { subject.query_values = { "page" => "1", :page => 2 } }.to_not raise_error ArgumentError
|
5108
|
+
end
|
5109
|
+
end
|
5110
|
+
end
|
5014
5111
|
end
|
5015
5112
|
|
5016
5113
|
describe Addressable::URI, "when assigning path values" do
|
data/tasks/gem.rake
CHANGED
metadata
CHANGED
@@ -1,66 +1,81 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: addressable
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.3.3
|
4
5
|
prerelease:
|
5
|
-
version: 2.3.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Bob Aman
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-02-19 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: rake
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
21
|
-
- -
|
22
|
-
- !ruby/object:Gem::Version
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
23
21
|
version: 0.7.3
|
24
22
|
type: :development
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: rspec
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.7.3
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
30
33
|
none: false
|
31
|
-
requirements:
|
32
|
-
- -
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
34
37
|
version: 2.9.0
|
35
38
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: launchy
|
39
39
|
prerelease: false
|
40
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.9.0
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: launchy
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
41
49
|
none: false
|
42
|
-
requirements:
|
43
|
-
- -
|
44
|
-
- !ruby/object:Gem::Version
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
45
53
|
version: 0.3.2
|
46
54
|
type: :development
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 0.3.2
|
62
|
+
description: ! 'Addressable is a replacement for the URI implementation that is part
|
63
|
+
of
|
64
|
+
|
65
|
+
Ruby''s standard library. It more closely conforms to the relevant RFCs and
|
66
|
+
|
51
67
|
adds support for IRIs and URI templates.
|
52
68
|
|
69
|
+
'
|
53
70
|
email: bob@sporkmonger.com
|
54
71
|
executables: []
|
55
|
-
|
56
72
|
extensions: []
|
57
|
-
|
58
|
-
extra_rdoc_files:
|
73
|
+
extra_rdoc_files:
|
59
74
|
- README.md
|
60
|
-
files:
|
75
|
+
files:
|
76
|
+
- lib/addressable/idna.rb
|
61
77
|
- lib/addressable/idna/native.rb
|
62
78
|
- lib/addressable/idna/pure.rb
|
63
|
-
- lib/addressable/idna.rb
|
64
79
|
- lib/addressable/template.rb
|
65
80
|
- lib/addressable/uri.rb
|
66
81
|
- lib/addressable/version.rb
|
@@ -80,35 +95,33 @@ files:
|
|
80
95
|
- CHANGELOG.md
|
81
96
|
- Gemfile
|
82
97
|
- LICENSE.txt
|
83
|
-
- Rakefile
|
84
98
|
- README.md
|
99
|
+
- Rakefile
|
85
100
|
homepage: http://addressable.rubyforge.org/
|
86
|
-
licenses:
|
87
|
-
|
101
|
+
licenses:
|
102
|
+
- Apache License 2.0
|
88
103
|
post_install_message:
|
89
|
-
rdoc_options:
|
104
|
+
rdoc_options:
|
90
105
|
- --main
|
91
106
|
- README.md
|
92
|
-
require_paths:
|
107
|
+
require_paths:
|
93
108
|
- lib
|
94
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
95
110
|
none: false
|
96
|
-
requirements:
|
97
|
-
- -
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
version:
|
100
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ! '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
116
|
none: false
|
102
|
-
requirements:
|
103
|
-
- -
|
104
|
-
- !ruby/object:Gem::Version
|
105
|
-
version:
|
117
|
+
requirements:
|
118
|
+
- - ! '>='
|
119
|
+
- !ruby/object:Gem::Version
|
120
|
+
version: '0'
|
106
121
|
requirements: []
|
107
|
-
|
108
122
|
rubyforge_project: addressable
|
109
|
-
rubygems_version: 1.8.
|
123
|
+
rubygems_version: 1.8.24
|
110
124
|
signing_key:
|
111
125
|
specification_version: 3
|
112
126
|
summary: URI Implementation
|
113
127
|
test_files: []
|
114
|
-
|