addressable 2.3.7 → 2.7.0

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.

@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # encoding:utf-8
2
4
  #--
3
- # Copyright (C) 2006-2013 Bob Aman
5
+ # Copyright (C) Bob Aman
4
6
  #
5
7
  # Licensed under the Apache License, Version 2.0 (the "License");
6
8
  # you may not use this file except in compliance with the License.
@@ -21,8 +23,8 @@ if !defined?(Addressable::VERSION)
21
23
  module Addressable
22
24
  module VERSION
23
25
  MAJOR = 2
24
- MINOR = 3
25
- TINY = 7
26
+ MINOR = 7
27
+ TINY = 0
26
28
 
27
29
  STRING = [MAJOR, MINOR, TINY].join('.')
28
30
  end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # coding: utf-8
2
- # Copyright (C) 2006-2013 Bob Aman
4
+ # Copyright (C) Bob Aman
3
5
  #
4
6
  # Licensed under the Apache License, Version 2.0 (the "License");
5
7
  # you may not use this file except in compliance with the License.
@@ -26,6 +28,11 @@ shared_examples_for "converting from unicode to ASCII" do
26
28
  expect(Addressable::IDNA.to_ascii("www.google.com")).to eq("www.google.com")
27
29
  end
28
30
 
31
+ long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
32
+ it "should convert '#{long}' correctly" do
33
+ expect(Addressable::IDNA.to_ascii(long)).to eq(long)
34
+ end
35
+
29
36
  it "should convert 'www.詹姆斯.com' correctly" do
30
37
  expect(Addressable::IDNA.to_ascii(
31
38
  "www.詹姆斯.com"
@@ -129,6 +136,12 @@ shared_examples_for "converting from unicode to ASCII" do
129
136
  )).to eq("xn--4ud")
130
137
  end
131
138
 
139
+ it "should convert '🌹🌹🌹.ws' correctly" do
140
+ expect(Addressable::IDNA.to_ascii(
141
+ "\360\237\214\271\360\237\214\271\360\237\214\271.ws"
142
+ )).to eq("xn--2h8haa.ws")
143
+ end
144
+
132
145
  it "should handle two adjacent '.'s correctly" do
133
146
  expect(Addressable::IDNA.to_ascii(
134
147
  "example..host"
@@ -137,8 +150,23 @@ shared_examples_for "converting from unicode to ASCII" do
137
150
  end
138
151
 
139
152
  shared_examples_for "converting from ASCII to unicode" do
153
+ long = 'AcinusFallumTrompetumNullunCreditumVisumEstAtCuadLongumEtCefallum.com'
154
+ it "should convert '#{long}' correctly" do
155
+ expect(Addressable::IDNA.to_unicode(long)).to eq(long)
156
+ end
157
+
158
+ it "should return the identity conversion when punycode decode fails" do
159
+ expect(Addressable::IDNA.to_unicode("xn--zckp1cyg1.sblo.jp")).to eq(
160
+ "xn--zckp1cyg1.sblo.jp")
161
+ end
162
+
163
+ it "should return the identity conversion when the ACE prefix has no suffix" do
164
+ expect(Addressable::IDNA.to_unicode("xn--...-")).to eq("xn--...-")
165
+ end
166
+
140
167
  it "should convert 'www.google.com' correctly" do
141
- expect(Addressable::IDNA.to_unicode("www.google.com")).to eq("www.google.com")
168
+ expect(Addressable::IDNA.to_unicode("www.google.com")).to eq(
169
+ "www.google.com")
142
170
  end
143
171
 
144
172
  it "should convert 'www.詹姆斯.com' correctly" do
@@ -147,12 +175,24 @@ shared_examples_for "converting from ASCII to unicode" do
147
175
  )).to eq("www.詹姆斯.com")
148
176
  end
149
177
 
178
+ it "should convert '詹姆斯.com' correctly" do
179
+ expect(Addressable::IDNA.to_unicode(
180
+ "xn--8ws00zhy3a.com"
181
+ )).to eq("詹姆斯.com")
182
+ end
183
+
150
184
  it "should convert 'www.iñtërnâtiônàlizætiøn.com' correctly" do
151
185
  expect(Addressable::IDNA.to_unicode(
152
186
  "www.xn--itrntinliztin-vdb0a5exd8ewcye.com"
153
187
  )).to eq("www.iñtërnâtiônàlizætiøn.com")
154
188
  end
155
189
 
190
+ it "should convert 'iñtërnâtiônàlizætiøn.com' correctly" do
191
+ expect(Addressable::IDNA.to_unicode(
192
+ "xn--itrntinliztin-vdb0a5exd8ewcye.com"
193
+ )).to eq("iñtërnâtiônàlizætiøn.com")
194
+ end
195
+
156
196
  it "should convert " +
157
197
  "'www.ほんとうにながいわけのわからないどめいんめいのらべるまだながくしないとたりない.w3.mag.keio.ac.jp' " +
158
198
  "correctly" do
@@ -199,6 +239,12 @@ shared_examples_for "converting from ASCII to unicode" do
199
239
  )).to eq("\341\206\265")
200
240
  end
201
241
 
242
+ it "should convert '🌹🌹🌹.ws' correctly" do
243
+ expect(Addressable::IDNA.to_unicode(
244
+ "xn--2h8haa.ws"
245
+ )).to eq("\360\237\214\271\360\237\214\271\360\237\214\271.ws")
246
+ end
247
+
202
248
  it "should handle two adjacent '.'s correctly" do
203
249
  expect(Addressable::IDNA.to_unicode(
204
250
  "example..host"
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # coding: utf-8
2
- # Copyright (C) 2006-2013 Bob Aman
4
+ # Copyright (C) Bob Aman
3
5
  #
4
6
  # Licensed under the Apache License, Version 2.0 (the "License");
5
7
  # you may not use this file except in compliance with the License.
@@ -0,0 +1,106 @@
1
+ # frozen_string_literal: true
2
+
3
+ # coding: utf-8
4
+ # Copyright (C) Bob Aman
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ require "spec_helper"
20
+
21
+ require "addressable/uri"
22
+ require "addressable/template"
23
+ require "rack/mount"
24
+
25
+ describe Rack::Mount do
26
+ let(:app_one) do
27
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 1'] }
28
+ end
29
+ let(:app_two) do
30
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 2'] }
31
+ end
32
+ let(:app_three) do
33
+ proc { |env| [200, {'Content-Type' => 'text/plain'}, 'Route 3'] }
34
+ end
35
+ let(:routes) do
36
+ s = Rack::Mount::RouteSet.new do |set|
37
+ set.add_route(app_one, {
38
+ :request_method => 'GET',
39
+ :path_info => Addressable::Template.new('/one/{id}/')
40
+ }, {:id => 'unidentified'}, :one)
41
+ set.add_route(app_two, {
42
+ :request_method => 'GET',
43
+ :path_info => Addressable::Template.new('/two/')
44
+ }, {:id => 'unidentified'}, :two)
45
+ set.add_route(app_three, {
46
+ :request_method => 'GET',
47
+ :path_info => Addressable::Template.new('/three/{id}/').to_regexp
48
+ }, {:id => 'unidentified'}, :three)
49
+ end
50
+ s.rehash
51
+ s
52
+ end
53
+
54
+ it "should generate from routes with Addressable::Template" do
55
+ path, _ = routes.generate(:path_info, :one, {:id => '123'})
56
+ expect(path).to eq '/one/123/'
57
+ end
58
+
59
+ it "should generate from routes with Addressable::Template using defaults" do
60
+ path, _ = routes.generate(:path_info, :one, {})
61
+ expect(path).to eq '/one/unidentified/'
62
+ end
63
+
64
+ it "should recognize routes with Addressable::Template" do
65
+ request = Rack::Request.new(
66
+ 'REQUEST_METHOD' => 'GET',
67
+ 'PATH_INFO' => '/one/123/'
68
+ )
69
+ route, _, params = routes.recognize(request)
70
+ expect(route).not_to be_nil
71
+ expect(route.app).to eq app_one
72
+ expect(params).to eq({id: '123'})
73
+ end
74
+
75
+ it "should generate from routes with Addressable::Template" do
76
+ path, _ = routes.generate(:path_info, :two, {:id => '654'})
77
+ expect(path).to eq '/two/'
78
+ end
79
+
80
+ it "should generate from routes with Addressable::Template using defaults" do
81
+ path, _ = routes.generate(:path_info, :two, {})
82
+ expect(path).to eq '/two/'
83
+ end
84
+
85
+ it "should recognize routes with Addressable::Template" do
86
+ request = Rack::Request.new(
87
+ 'REQUEST_METHOD' => 'GET',
88
+ 'PATH_INFO' => '/two/'
89
+ )
90
+ route, _, params = routes.recognize(request)
91
+ expect(route).not_to be_nil
92
+ expect(route.app).to eq app_two
93
+ expect(params).to eq({id: 'unidentified'})
94
+ end
95
+
96
+ it "should recognize routes with derived Regexp" do
97
+ request = Rack::Request.new(
98
+ 'REQUEST_METHOD' => 'GET',
99
+ 'PATH_INFO' => '/three/789/'
100
+ )
101
+ route, _, params = routes.recognize(request)
102
+ expect(route).not_to be_nil
103
+ expect(route.app).to eq app_three
104
+ expect(params).to eq({id: '789'})
105
+ end
106
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ # coding: utf-8
4
+ # Copyright (C) Bob Aman
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ require "spec_helper"
20
+
21
+ require "addressable/uri"
22
+
23
+ describe Addressable::URI, "when created with a URI known to cause crashes " +
24
+ "in certain browsers" do
25
+ it "should parse correctly" do
26
+ uri = Addressable::URI.parse('%%30%30')
27
+ expect(uri.path).to eq('%%30%30')
28
+ expect(uri.normalize.path).to eq('%2500')
29
+ end
30
+
31
+ it "should parse correctly as a full URI" do
32
+ uri = Addressable::URI.parse('http://www.example.com/%%30%30')
33
+ expect(uri.path).to eq('/%%30%30')
34
+ expect(uri.normalize.path).to eq('/%2500')
35
+ end
36
+ end
37
+
38
+ describe Addressable::URI, "when created with a URI known to cause crashes " +
39
+ "in certain browsers" do
40
+ it "should parse correctly" do
41
+ uri = Addressable::URI.parse('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
42
+ expect(uri.path).to eq('لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
43
+ expect(uri.normalize.path).to eq(
44
+ '%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
45
+ '%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
46
+ '%A3%20%E0%A5%A3%20%E5%86%97'
47
+ )
48
+ end
49
+
50
+ it "should parse correctly as a full URI" do
51
+ uri = Addressable::URI.parse('http://www.example.com/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
52
+ expect(uri.path).to eq('/لُصّبُلُلصّبُررً ॣ ॣh ॣ ॣ 冗')
53
+ expect(uri.normalize.path).to eq(
54
+ '/%D9%84%D9%8F%D8%B5%D9%91%D8%A8%D9%8F%D9%84%D9%8F%D9%84%D8%B5%D9%91' +
55
+ '%D8%A8%D9%8F%D8%B1%D8%B1%D9%8B%20%E0%A5%A3%20%E0%A5%A3h%20%E0%A5' +
56
+ '%A3%20%E0%A5%A3%20%E5%86%97'
57
+ )
58
+ end
59
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # coding: utf-8
2
- # Copyright (C) 2006-2013 Bob Aman
4
+ # Copyright (C) Bob Aman
3
5
  #
4
6
  # Licensed under the Apache License, Version 2.0 (the "License");
5
7
  # you may not use this file except in compliance with the License.
@@ -16,6 +18,7 @@
16
18
 
17
19
  require "spec_helper"
18
20
 
21
+ require "bigdecimal"
19
22
  require "addressable/template"
20
23
 
21
24
  shared_examples_for 'expands' do |tests|
@@ -75,15 +78,13 @@ describe "==" do
75
78
  end
76
79
 
77
80
  describe "Type conversion" do
78
- require "bigdecimal"
79
-
80
81
  subject {
81
82
  {
82
83
  :var => true,
83
84
  :hello => 1234,
84
85
  :nothing => nil,
85
86
  :sym => :symbolic,
86
- :decimal => BigDecimal.new('1')
87
+ :decimal => BigDecimal('1')
87
88
  }
88
89
  }
89
90
 
@@ -92,7 +93,7 @@ describe "Type conversion" do
92
93
  '{hello}' => '1234',
93
94
  '{nothing}' => '',
94
95
  '{sym}' => 'symbolic',
95
- '{decimal}' => '0.1E1'
96
+ '{decimal}' => RUBY_VERSION < '2.4.0' ? '0.1E1' : '0.1e1'
96
97
  }
97
98
  end
98
99
 
@@ -699,6 +700,13 @@ describe "Expansion" do
699
700
  ]
700
701
  }
701
702
  end
703
+ context "non-string key in match data" do
704
+ subject {Addressable::Template.new("http://example.com/{one}")}
705
+
706
+ it "raises TypeError" do
707
+ expect { subject.expand(Object.new => "1") }.to raise_error TypeError
708
+ end
709
+ end
702
710
  end
703
711
 
704
712
  class ExampleTwoProcessor
@@ -729,6 +737,21 @@ class DumbProcessor
729
737
  end
730
738
 
731
739
  describe Addressable::Template do
740
+ describe 'initialize' do
741
+ context 'with a non-string' do
742
+ it 'raises a TypeError' do
743
+ expect { Addressable::Template.new(nil) }.to raise_error(TypeError)
744
+ end
745
+ end
746
+ end
747
+
748
+ describe 'freeze' do
749
+ subject { Addressable::Template.new("http://example.com/{first}/{+second}/") }
750
+ it 'freezes the template' do
751
+ expect(subject.freeze).to be_frozen
752
+ end
753
+ end
754
+
732
755
  describe "Matching" do
733
756
  let(:uri){
734
757
  Addressable::URI.parse(
@@ -749,7 +772,7 @@ describe Addressable::Template do
749
772
  }
750
773
  context "first uri with ExampleTwoProcessor" do
751
774
  subject {
752
- match = Addressable::Template.new(
775
+ Addressable::Template.new(
753
776
  "http://example.com/search/{query}/"
754
777
  ).match(uri, ExampleTwoProcessor)
755
778
  }
@@ -759,7 +782,7 @@ describe Addressable::Template do
759
782
 
760
783
  context "second uri with ExampleTwoProcessor" do
761
784
  subject {
762
- match = Addressable::Template.new(
785
+ Addressable::Template.new(
763
786
  "http://example.com/{first}/{+second}/"
764
787
  ).match(uri2, ExampleTwoProcessor)
765
788
  }
@@ -769,7 +792,7 @@ describe Addressable::Template do
769
792
 
770
793
  context "second uri with DumbProcessor" do
771
794
  subject {
772
- match = Addressable::Template.new(
795
+ Addressable::Template.new(
773
796
  "http://example.com/{first}/{+second}/"
774
797
  ).match(uri2, DumbProcessor)
775
798
  }
@@ -779,7 +802,7 @@ describe Addressable::Template do
779
802
 
780
803
  context "second uri" do
781
804
  subject {
782
- match = Addressable::Template.new(
805
+ Addressable::Template.new(
783
806
  "http://example.com/{first}{/second*}/"
784
807
  ).match(uri2)
785
808
  }
@@ -788,7 +811,7 @@ describe Addressable::Template do
788
811
  end
789
812
  context "third uri" do
790
813
  subject {
791
- match = Addressable::Template.new(
814
+ Addressable::Template.new(
792
815
  "http://example.com/{;hash*,first}"
793
816
  ).match(uri3)
794
817
  }
@@ -801,7 +824,7 @@ describe Addressable::Template do
801
824
  # Semantically, a separate key is more likely, but both are possible.
802
825
  context "fourth uri" do
803
826
  subject {
804
- match = Addressable::Template.new(
827
+ Addressable::Template.new(
805
828
  "http://example.com/{?hash*,first}"
806
829
  ).match(uri4)
807
830
  }
@@ -811,7 +834,7 @@ describe Addressable::Template do
811
834
  end
812
835
  context "fifth uri" do
813
836
  subject {
814
- match = Addressable::Template.new(
837
+ Addressable::Template.new(
815
838
  "http://example.com/{path}{?hash*,first}"
816
839
  ).match(uri5)
817
840
  }
@@ -819,6 +842,22 @@ describe Addressable::Template do
819
842
  its(:captures){ should == ["foo", nil, nil] }
820
843
  end
821
844
  end
845
+
846
+ describe 'match' do
847
+ subject { Addressable::Template.new('http://example.com/first/second/') }
848
+ context 'when the URI is the same as the template' do
849
+ it 'returns the match data itself with an empty mapping' do
850
+ uri = Addressable::URI.parse('http://example.com/first/second/')
851
+ match_data = subject.match(uri)
852
+ expect(match_data).to be_an Addressable::Template::MatchData
853
+ expect(match_data.uri).to eq(uri)
854
+ expect(match_data.template).to eq(subject)
855
+ expect(match_data.mapping).to be_empty
856
+ expect(match_data.inspect).to be_an String
857
+ end
858
+ end
859
+ end
860
+
822
861
  describe "extract" do
823
862
  let(:template) {
824
863
  Addressable::Template.new(
@@ -902,13 +941,53 @@ describe Addressable::Template do
902
941
  )
903
942
  end
904
943
  end
944
+ context "partial_expand form style query with missing param at beginning" do
945
+ subject {
946
+ Addressable::Template.new("http://example.com/{?one,two}/")
947
+ }
948
+ it "builds a new pattern" do
949
+ expect(subject.partial_expand(:two => "2").pattern).to eq(
950
+ "http://example.com/?two=2{&one}/"
951
+ )
952
+ end
953
+ end
954
+ context "issue #307 - partial_expand form query with nil params" do
955
+ subject do
956
+ Addressable::Template.new("http://example.com/{?one,two,three}/")
957
+ end
958
+ it "builds a new pattern with two=nil" do
959
+ expect(subject.partial_expand(two: nil).pattern).to eq(
960
+ "http://example.com/{?one}{&three}/"
961
+ )
962
+ end
963
+ it "builds a new pattern with one=nil and two=nil" do
964
+ expect(subject.partial_expand(one: nil, two: nil).pattern).to eq(
965
+ "http://example.com/{?three}/"
966
+ )
967
+ end
968
+ it "builds a new pattern with one=1 and two=nil" do
969
+ expect(subject.partial_expand(one: 1, two: nil).pattern).to eq(
970
+ "http://example.com/?one=1{&three}/"
971
+ )
972
+ end
973
+ it "builds a new pattern with one=nil and two=2" do
974
+ expect(subject.partial_expand(one: nil, two: 2).pattern).to eq(
975
+ "http://example.com/?two=2{&three}/"
976
+ )
977
+ end
978
+ it "builds a new pattern with one=nil" do
979
+ expect(subject.partial_expand(one: nil).pattern).to eq(
980
+ "http://example.com/{?two}{&three}/"
981
+ )
982
+ end
983
+ end
905
984
  context "partial_expand with query string" do
906
985
  subject {
907
986
  Addressable::Template.new("http://example.com/{?two,one}/")
908
987
  }
909
988
  it "builds a new pattern" do
910
989
  expect(subject.partial_expand(:one => "1").pattern).to eq(
911
- "http://example.com/{?two}&one=1/"
990
+ "http://example.com/?one=1{&two}/"
912
991
  )
913
992
  end
914
993
  end
@@ -922,6 +1001,24 @@ describe Addressable::Template do
922
1001
  )
923
1002
  end
924
1003
  end
1004
+ context "partial expand with unicode values" do
1005
+ subject do
1006
+ Addressable::Template.new("http://example.com/{resource}/{query}/")
1007
+ end
1008
+ it "normalizes unicode by default" do
1009
+ template = subject.partial_expand("query" => "Cafe\u0301")
1010
+ expect(template.pattern).to eq(
1011
+ "http://example.com/{resource}/Caf%C3%A9/"
1012
+ )
1013
+ end
1014
+
1015
+ it "does not normalize unicode when byte semantics requested" do
1016
+ template = subject.partial_expand({"query" => "Cafe\u0301"}, nil, false)
1017
+ expect(template.pattern).to eq(
1018
+ "http://example.com/{resource}/Cafe%CC%81/"
1019
+ )
1020
+ end
1021
+ end
925
1022
  end
926
1023
  describe "Partial expand with strings" do
927
1024
  context "partial_expand with two simple values" do
@@ -950,7 +1047,7 @@ describe Addressable::Template do
950
1047
  }
951
1048
  it "builds a new pattern" do
952
1049
  expect(subject.partial_expand("one" => "1").pattern).to eq(
953
- "http://example.com/{?two}&one=1/"
1050
+ "http://example.com/?one=1{&two}/"
954
1051
  )
955
1052
  end
956
1053
  end
@@ -966,6 +1063,20 @@ describe Addressable::Template do
966
1063
  end
967
1064
  end
968
1065
  describe "Expand" do
1066
+ context "expand with unicode values" do
1067
+ subject do
1068
+ Addressable::Template.new("http://example.com/search/{query}/")
1069
+ end
1070
+ it "normalizes unicode by default" do
1071
+ uri = subject.expand("query" => "Cafe\u0301").to_str
1072
+ expect(uri).to eq("http://example.com/search/Caf%C3%A9/")
1073
+ end
1074
+
1075
+ it "does not normalize unicode when byte semantics requested" do
1076
+ uri = subject.expand({ "query" => "Cafe\u0301" }, nil, false).to_str
1077
+ expect(uri).to eq("http://example.com/search/Cafe%CC%81/")
1078
+ end
1079
+ end
969
1080
  context "expand with a processor" do
970
1081
  subject {
971
1082
  Addressable::Template.new("http://example.com/search/{query}/")
@@ -999,7 +1110,7 @@ describe Addressable::Template do
999
1110
  }
1000
1111
  it "builds a new pattern" do
1001
1112
  expect(subject.partial_expand("one" => "1").pattern).to eq(
1002
- "http://example.com/{?two}&one=1/"
1113
+ "http://example.com/?one=1{&two}/"
1003
1114
  )
1004
1115
  end
1005
1116
  end