addressable 2.6.0 → 2.8.0

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.
@@ -48,12 +48,21 @@ module Addressable
48
48
  PCHAR = UNRESERVED + SUB_DELIMS + "\\:\\@"
49
49
  SCHEME = ALPHA + DIGIT + "\\-\\+\\."
50
50
  HOST = UNRESERVED + SUB_DELIMS + "\\[\\:\\]"
51
- AUTHORITY = PCHAR
51
+ AUTHORITY = PCHAR + "\\[\\:\\]"
52
52
  PATH = PCHAR + "\\/"
53
53
  QUERY = PCHAR + "\\/\\?"
54
54
  FRAGMENT = PCHAR + "\\/\\?"
55
55
  end
56
56
 
57
+ module NormalizeCharacterClasses
58
+ HOST = /[^#{CharacterClasses::HOST}]/
59
+ UNRESERVED = /[^#{CharacterClasses::UNRESERVED}]/
60
+ PCHAR = /[^#{CharacterClasses::PCHAR}]/
61
+ SCHEME = /[^#{CharacterClasses::SCHEME}]/
62
+ FRAGMENT = /[^#{CharacterClasses::FRAGMENT}]/
63
+ QUERY = %r{[^a-zA-Z0-9\-\.\_\~\!\$\'\(\)\*\+\,\=\:\@\/\?%]|%(?!2B|2b)}
64
+ end
65
+
57
66
  SLASH = '/'
58
67
  EMPTY_STR = ''
59
68
 
@@ -73,7 +82,7 @@ module Addressable
73
82
  "wais" => 210,
74
83
  "ldap" => 389,
75
84
  "prospero" => 1525
76
- }
85
+ }.freeze
77
86
 
78
87
  ##
79
88
  # Returns a URI object based on the parsed string.
@@ -207,7 +216,7 @@ module Addressable
207
216
  fragments = match.captures
208
217
  authority = fragments[3]
209
218
  if authority && authority.length > 0
210
- new_authority = authority.gsub(/\\/, '/').gsub(/ /, '%20')
219
+ new_authority = authority.tr("\\", "/").gsub(" ", "%20")
211
220
  # NOTE: We want offset 4, not 3!
212
221
  offset = match.offset(4)
213
222
  uri = uri.dup
@@ -218,8 +227,9 @@ module Addressable
218
227
  parsed = self.parse(hints[:scheme] + "://" + uri)
219
228
  end
220
229
  if parsed.path.include?(".")
221
- new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1]
222
- if new_host
230
+ if parsed.path[/\b@\b/]
231
+ parsed.scheme = "mailto" unless parsed.scheme
232
+ elsif new_host = parsed.path[/^([^\/]+\.[^\/]*)/, 1]
223
233
  parsed.defer_validation do
224
234
  new_path = parsed.path.sub(
225
235
  Regexp.new("^" + Regexp.escape(new_host)), EMPTY_STR)
@@ -281,15 +291,15 @@ module Addressable
281
291
  uri.path.sub!(/^\/?([a-zA-Z])[\|:][\\\/]/) do
282
292
  "/#{$1.downcase}:/"
283
293
  end
284
- uri.path.gsub!(/\\/, SLASH)
294
+ uri.path.tr!("\\", SLASH)
285
295
  if File.exist?(uri.path) &&
286
296
  File.stat(uri.path).directory?
287
- uri.path.sub!(/\/$/, EMPTY_STR)
297
+ uri.path.chomp!(SLASH)
288
298
  uri.path = uri.path + '/'
289
299
  end
290
300
 
291
301
  # If the path is absolute, set the scheme and host.
292
- if uri.path =~ /^\//
302
+ if uri.path.start_with?(SLASH)
293
303
  uri.scheme = "file"
294
304
  uri.host = EMPTY_STR
295
305
  end
@@ -326,6 +336,21 @@ module Addressable
326
336
  return result
327
337
  end
328
338
 
339
+ ##
340
+ # Tables used to optimize encoding operations in `self.encode_component`
341
+ # and `self.normalize_component`
342
+ SEQUENCE_ENCODING_TABLE = Hash.new do |hash, sequence|
343
+ hash[sequence] = sequence.unpack("C*").map do |c|
344
+ format("%02x", c)
345
+ end.join
346
+ end
347
+
348
+ SEQUENCE_UPCASED_PERCENT_ENCODING_TABLE = Hash.new do |hash, sequence|
349
+ hash[sequence] = sequence.unpack("C*").map do |c|
350
+ format("%%%02X", c)
351
+ end.join
352
+ end
353
+
329
354
  ##
330
355
  # Percent encodes a URI component.
331
356
  #
@@ -392,18 +417,20 @@ module Addressable
392
417
  component.force_encoding(Encoding::ASCII_8BIT)
393
418
  # Avoiding gsub! because there are edge cases with frozen strings
394
419
  component = component.gsub(character_class) do |sequence|
395
- (sequence.unpack('C*').map { |c| "%" + ("%02x" % c).upcase }).join
420
+ SEQUENCE_UPCASED_PERCENT_ENCODING_TABLE[sequence]
396
421
  end
397
422
  if upcase_encoded.length > 0
398
- component = component.gsub(/%(#{upcase_encoded.chars.map do |char|
399
- char.unpack('C*').map { |c| '%02x' % c }.join
400
- end.join('|')})/i) { |s| s.upcase }
423
+ upcase_encoded_chars = upcase_encoded.chars.map do |char|
424
+ SEQUENCE_ENCODING_TABLE[char]
425
+ end
426
+ component = component.gsub(/%(#{upcase_encoded_chars.join('|')})/,
427
+ &:upcase)
401
428
  end
402
429
  return component
403
430
  end
404
431
 
405
432
  class << self
406
- alias_method :encode_component, :encode_component
433
+ alias_method :escape_component, :encode_component
407
434
  end
408
435
 
409
436
  ##
@@ -445,7 +472,11 @@ module Addressable
445
472
  uri = uri.dup
446
473
  # Seriously, only use UTF-8. I'm really not kidding!
447
474
  uri.force_encoding("utf-8")
448
- leave_encoded = leave_encoded.dup.force_encoding("utf-8")
475
+
476
+ unless leave_encoded.empty?
477
+ leave_encoded = leave_encoded.dup.force_encoding("utf-8")
478
+ end
479
+
449
480
  result = uri.gsub(/%[0-9a-f]{2}/iu) do |sequence|
450
481
  c = sequence[1..3].to_i(16).chr
451
482
  c.force_encoding("utf-8")
@@ -531,12 +562,16 @@ module Addressable
531
562
  character_class = "#{character_class}%" unless character_class.include?('%')
532
563
 
533
564
  "|%(?!#{leave_encoded.chars.map do |char|
534
- seq = char.unpack('C*').map { |c| '%02x' % c }.join
565
+ seq = SEQUENCE_ENCODING_TABLE[char]
535
566
  [seq.upcase, seq.downcase]
536
567
  end.flatten.join('|')})"
537
568
  end
538
569
 
539
- character_class = /[^#{character_class}]#{leave_re}/
570
+ character_class = if leave_re
571
+ /[^#{character_class}]#{leave_re}/
572
+ else
573
+ /[^#{character_class}]/
574
+ end
540
575
  end
541
576
  # We can't perform regexps on invalid UTF sequences, but
542
577
  # here we need to, so switch to ASCII.
@@ -860,7 +895,7 @@ module Addressable
860
895
  else
861
896
  Addressable::URI.normalize_component(
862
897
  self.scheme.strip.downcase,
863
- Addressable::URI::CharacterClasses::SCHEME
898
+ Addressable::URI::NormalizeCharacterClasses::SCHEME
864
899
  )
865
900
  end
866
901
  end
@@ -880,7 +915,7 @@ module Addressable
880
915
  new_scheme = new_scheme.to_str
881
916
  end
882
917
  if new_scheme && new_scheme !~ /\A[a-z][a-z0-9\.\+\-]*\z/i
883
- raise InvalidURIError, "Invalid scheme format: #{new_scheme}"
918
+ raise InvalidURIError, "Invalid scheme format: '#{new_scheme}'"
884
919
  end
885
920
  @scheme = new_scheme
886
921
  @scheme = nil if @scheme.to_s.strip.empty?
@@ -915,7 +950,7 @@ module Addressable
915
950
  else
916
951
  Addressable::URI.normalize_component(
917
952
  self.user.strip,
918
- Addressable::URI::CharacterClasses::UNRESERVED
953
+ Addressable::URI::NormalizeCharacterClasses::UNRESERVED
919
954
  )
920
955
  end
921
956
  end
@@ -972,7 +1007,7 @@ module Addressable
972
1007
  else
973
1008
  Addressable::URI.normalize_component(
974
1009
  self.password.strip,
975
- Addressable::URI::CharacterClasses::UNRESERVED
1010
+ Addressable::URI::NormalizeCharacterClasses::UNRESERVED
976
1011
  )
977
1012
  end
978
1013
  end
@@ -1096,6 +1131,7 @@ module Addressable
1096
1131
  # @return [String] The host component, normalized.
1097
1132
  def normalized_host
1098
1133
  return nil unless self.host
1134
+
1099
1135
  @normalized_host ||= begin
1100
1136
  if !self.host.strip.empty?
1101
1137
  result = ::Addressable::IDNA.to_ascii(
@@ -1107,14 +1143,17 @@ module Addressable
1107
1143
  end
1108
1144
  result = Addressable::URI.normalize_component(
1109
1145
  result,
1110
- CharacterClasses::HOST)
1146
+ NormalizeCharacterClasses::HOST
1147
+ )
1111
1148
  result
1112
1149
  else
1113
1150
  EMPTY_STR.dup
1114
1151
  end
1115
1152
  end
1116
1153
  # All normalized values should be UTF-8
1117
- @normalized_host.force_encoding(Encoding::UTF_8) if @normalized_host
1154
+ if @normalized_host && !@normalized_host.empty?
1155
+ @normalized_host.force_encoding(Encoding::UTF_8)
1156
+ end
1118
1157
  @normalized_host
1119
1158
  end
1120
1159
 
@@ -1172,7 +1211,7 @@ module Addressable
1172
1211
  # Returns the top-level domain for this host.
1173
1212
  #
1174
1213
  # @example
1175
- # Addressable::URI.parse("www.example.co.uk").tld # => "co.uk"
1214
+ # Addressable::URI.parse("http://www.example.co.uk").tld # => "co.uk"
1176
1215
  def tld
1177
1216
  PublicSuffix.parse(self.host, ignore_private: true).tld
1178
1217
  end
@@ -1182,7 +1221,7 @@ module Addressable
1182
1221
  #
1183
1222
  # @param [String, #to_str] new_tld The new top-level domain.
1184
1223
  def tld=(new_tld)
1185
- replaced_tld = domain.sub(/#{tld}\z/, new_tld)
1224
+ replaced_tld = host.sub(/#{tld}\z/, new_tld)
1186
1225
  self.host = PublicSuffix::Domain.new(replaced_tld).to_s
1187
1226
  end
1188
1227
 
@@ -1190,7 +1229,7 @@ module Addressable
1190
1229
  # Returns the public suffix domain for this host.
1191
1230
  #
1192
1231
  # @example
1193
- # Addressable::URI.parse("www.example.co.uk").domain # => "example.co.uk"
1232
+ # Addressable::URI.parse("http://www.example.co.uk").domain # => "example.co.uk"
1194
1233
  def domain
1195
1234
  PublicSuffix.domain(self.host, ignore_private: true)
1196
1235
  end
@@ -1519,7 +1558,7 @@ module Addressable
1519
1558
  result = path.strip.split(SLASH, -1).map do |segment|
1520
1559
  Addressable::URI.normalize_component(
1521
1560
  segment,
1522
- Addressable::URI::CharacterClasses::PCHAR
1561
+ Addressable::URI::NormalizeCharacterClasses::PCHAR
1523
1562
  )
1524
1563
  end.join(SLASH)
1525
1564
 
@@ -1594,10 +1633,15 @@ module Addressable
1594
1633
  modified_query_class = Addressable::URI::CharacterClasses::QUERY.dup
1595
1634
  # Make sure possible key-value pair delimiters are escaped.
1596
1635
  modified_query_class.sub!("\\&", "").sub!("\\;", "")
1597
- pairs = (self.query || "").split("&", -1)
1636
+ pairs = (query || "").split("&", -1)
1637
+ pairs.delete_if(&:empty?).uniq! if flags.include?(:compacted)
1598
1638
  pairs.sort! if flags.include?(:sorted)
1599
1639
  component = pairs.map do |pair|
1600
- Addressable::URI.normalize_component(pair, modified_query_class, "+")
1640
+ Addressable::URI.normalize_component(
1641
+ pair,
1642
+ Addressable::URI::NormalizeCharacterClasses::QUERY,
1643
+ "+"
1644
+ )
1601
1645
  end.join("&")
1602
1646
  component == "" ? nil : component
1603
1647
  end
@@ -1656,11 +1700,13 @@ module Addressable
1656
1700
  # so it's best to make all changes in-place.
1657
1701
  pair[0] = URI.unencode_component(pair[0])
1658
1702
  if pair[1].respond_to?(:to_str)
1703
+ value = pair[1].to_str
1659
1704
  # I loathe the fact that I have to do this. Stupid HTML 4.01.
1660
1705
  # Treating '+' as a space was just an unbelievably bad idea.
1661
1706
  # There was nothing wrong with '%20'!
1662
1707
  # If it ain't broke, don't fix it!
1663
- pair[1] = URI.unencode_component(pair[1].to_str.gsub(/\+/, " "))
1708
+ value = value.tr("+", " ") if ["http", "https", nil].include?(scheme)
1709
+ pair[1] = URI.unencode_component(value)
1664
1710
  end
1665
1711
  if return_type == Hash
1666
1712
  accu[pair[0]] = pair[1]
@@ -1791,7 +1837,7 @@ module Addressable
1791
1837
  @normalized_fragment ||= begin
1792
1838
  component = Addressable::URI.normalize_component(
1793
1839
  self.fragment,
1794
- Addressable::URI::CharacterClasses::FRAGMENT
1840
+ Addressable::URI::NormalizeCharacterClasses::FRAGMENT
1795
1841
  )
1796
1842
  component == "" ? nil : component
1797
1843
  end
@@ -1917,7 +1963,7 @@ module Addressable
1917
1963
  # Section 5.2.3 of RFC 3986
1918
1964
  #
1919
1965
  # Removes the right-most path segment from the base path.
1920
- if base_path =~ /\//
1966
+ if base_path.include?(SLASH)
1921
1967
  base_path.sub!(/\/[^\/]+$/, SLASH)
1922
1968
  else
1923
1969
  base_path = EMPTY_STR
@@ -2367,10 +2413,10 @@ module Addressable
2367
2413
  #
2368
2414
  # @param [Proc] block
2369
2415
  # A set of operations to perform on a given URI.
2370
- def defer_validation(&block)
2371
- raise LocalJumpError, "No block given." unless block
2416
+ def defer_validation
2417
+ raise LocalJumpError, "No block given." unless block_given?
2372
2418
  @validation_deferred = true
2373
- block.call()
2419
+ yield
2374
2420
  @validation_deferred = false
2375
2421
  validate
2376
2422
  return nil
@@ -23,7 +23,7 @@ if !defined?(Addressable::VERSION)
23
23
  module Addressable
24
24
  module VERSION
25
25
  MAJOR = 2
26
- MINOR = 6
26
+ MINOR = 8
27
27
  TINY = 0
28
28
 
29
29
  STRING = [MAJOR, MINOR, TINY].join('.')
@@ -294,7 +294,9 @@ begin
294
294
  it_should_behave_like "converting from unicode to ASCII"
295
295
  it_should_behave_like "converting from ASCII to unicode"
296
296
  end
297
- rescue LoadError
297
+ rescue LoadError => error
298
+ raise error if ENV["CI"] && TestHelper.native_supported?
299
+
298
300
  # Cannot test the native implementation without libidn support.
299
301
  warn('Could not load native IDN implementation.')
300
302
  end
@@ -19,6 +19,7 @@
19
19
  require "spec_helper"
20
20
 
21
21
  require "bigdecimal"
22
+ require "timeout"
22
23
  require "addressable/template"
23
24
 
24
25
  shared_examples_for 'expands' do |tests|
@@ -1340,6 +1341,14 @@ describe Addressable::Template do
1340
1341
  expect(subject).not_to match("foo_bar*")
1341
1342
  expect(subject).not_to match("foo_bar:20")
1342
1343
  end
1344
+
1345
+ it 'should parse in a reasonable time' do
1346
+ expect do
1347
+ Timeout.timeout(0.1) do
1348
+ expect(subject).not_to match("0"*25 + "!")
1349
+ end
1350
+ end.not_to raise_error
1351
+ end
1343
1352
  end
1344
1353
  context "VARIABLE_LIST" do
1345
1354
  subject { Addressable::Template::VARIABLE_LIST }
@@ -65,116 +65,116 @@ end
65
65
 
66
66
  describe Addressable::URI, "when created with a non-numeric port number" do
67
67
  it "should raise an error" do
68
- expect(lambda do
68
+ expect do
69
69
  Addressable::URI.new(:port => "bogus")
70
- end).to raise_error(Addressable::URI::InvalidURIError)
70
+ end.to raise_error(Addressable::URI::InvalidURIError)
71
71
  end
72
72
  end
73
73
 
74
74
  describe Addressable::URI, "when created with a invalid encoded port number" do
75
75
  it "should raise an error" do
76
- expect(lambda do
76
+ expect do
77
77
  Addressable::URI.new(:port => "%eb")
78
- end).to raise_error(Addressable::URI::InvalidURIError)
78
+ end.to raise_error(Addressable::URI::InvalidURIError)
79
79
  end
80
80
  end
81
81
 
82
82
  describe Addressable::URI, "when created with a non-string scheme" do
83
83
  it "should raise an error" do
84
- expect(lambda do
84
+ expect do
85
85
  Addressable::URI.new(:scheme => :bogus)
86
- end).to raise_error(TypeError)
86
+ end.to raise_error(TypeError)
87
87
  end
88
88
  end
89
89
 
90
90
  describe Addressable::URI, "when created with a non-string user" do
91
91
  it "should raise an error" do
92
- expect(lambda do
92
+ expect do
93
93
  Addressable::URI.new(:user => :bogus)
94
- end).to raise_error(TypeError)
94
+ end.to raise_error(TypeError)
95
95
  end
96
96
  end
97
97
 
98
98
  describe Addressable::URI, "when created with a non-string password" do
99
99
  it "should raise an error" do
100
- expect(lambda do
100
+ expect do
101
101
  Addressable::URI.new(:password => :bogus)
102
- end).to raise_error(TypeError)
102
+ end.to raise_error(TypeError)
103
103
  end
104
104
  end
105
105
 
106
106
  describe Addressable::URI, "when created with a non-string userinfo" do
107
107
  it "should raise an error" do
108
- expect(lambda do
108
+ expect do
109
109
  Addressable::URI.new(:userinfo => :bogus)
110
- end).to raise_error(TypeError)
110
+ end.to raise_error(TypeError)
111
111
  end
112
112
  end
113
113
 
114
114
  describe Addressable::URI, "when created with a non-string host" do
115
115
  it "should raise an error" do
116
- expect(lambda do
116
+ expect do
117
117
  Addressable::URI.new(:host => :bogus)
118
- end).to raise_error(TypeError)
118
+ end.to raise_error(TypeError)
119
119
  end
120
120
  end
121
121
 
122
122
  describe Addressable::URI, "when created with a non-string authority" do
123
123
  it "should raise an error" do
124
- expect(lambda do
124
+ expect do
125
125
  Addressable::URI.new(:authority => :bogus)
126
- end).to raise_error(TypeError)
126
+ end.to raise_error(TypeError)
127
127
  end
128
128
  end
129
129
 
130
130
  describe Addressable::URI, "when created with a non-string path" do
131
131
  it "should raise an error" do
132
- expect(lambda do
132
+ expect do
133
133
  Addressable::URI.new(:path => :bogus)
134
- end).to raise_error(TypeError)
134
+ end.to raise_error(TypeError)
135
135
  end
136
136
  end
137
137
 
138
138
  describe Addressable::URI, "when created with a non-string query" do
139
139
  it "should raise an error" do
140
- expect(lambda do
140
+ expect do
141
141
  Addressable::URI.new(:query => :bogus)
142
- end).to raise_error(TypeError)
142
+ end.to raise_error(TypeError)
143
143
  end
144
144
  end
145
145
 
146
146
  describe Addressable::URI, "when created with a non-string fragment" do
147
147
  it "should raise an error" do
148
- expect(lambda do
148
+ expect do
149
149
  Addressable::URI.new(:fragment => :bogus)
150
- end).to raise_error(TypeError)
150
+ end.to raise_error(TypeError)
151
151
  end
152
152
  end
153
153
 
154
154
  describe Addressable::URI, "when created with a scheme but no hierarchical " +
155
155
  "segment" do
156
156
  it "should raise an error" do
157
- expect(lambda do
157
+ expect do
158
158
  Addressable::URI.parse("http:")
159
- end).to raise_error(Addressable::URI::InvalidURIError)
159
+ end.to raise_error(Addressable::URI::InvalidURIError)
160
160
  end
161
161
  end
162
162
 
163
163
  describe Addressable::URI, "quote handling" do
164
164
  describe 'in host name' do
165
165
  it "should raise an error for single quote" do
166
- expect(lambda do
166
+ expect do
167
167
  Addressable::URI.parse("http://local\"host/")
168
- end).to raise_error(Addressable::URI::InvalidURIError)
168
+ end.to raise_error(Addressable::URI::InvalidURIError)
169
169
  end
170
170
  end
171
171
  end
172
172
 
173
173
  describe Addressable::URI, "newline normalization" do
174
174
  it "should not accept newlines in scheme" do
175
- expect(lambda do
175
+ expect do
176
176
  Addressable::URI.parse("ht%0atp://localhost/")
177
- end).to raise_error(Addressable::URI::InvalidURIError)
177
+ end.to raise_error(Addressable::URI::InvalidURIError)
178
178
  end
179
179
 
180
180
  it "should not unescape newline in path" do
@@ -199,47 +199,47 @@ describe Addressable::URI, "newline normalization" do
199
199
 
200
200
  it "should not accept newline in hostname" do
201
201
  uri = Addressable::URI.parse("http://localhost/")
202
- expect(lambda do
202
+ expect do
203
203
  uri.host = "local\nhost"
204
- end).to raise_error(Addressable::URI::InvalidURIError)
204
+ end.to raise_error(Addressable::URI::InvalidURIError)
205
205
  end
206
206
  end
207
207
 
208
208
  describe Addressable::URI, "when created with ambiguous path" do
209
209
  it "should raise an error" do
210
- expect(lambda do
210
+ expect do
211
211
  Addressable::URI.parse("::http")
212
- end).to raise_error(Addressable::URI::InvalidURIError)
212
+ end.to raise_error(Addressable::URI::InvalidURIError)
213
213
  end
214
214
  end
215
215
 
216
216
  describe Addressable::URI, "when created with an invalid host" do
217
217
  it "should raise an error" do
218
- expect(lambda do
218
+ expect do
219
219
  Addressable::URI.new(:host => "<invalid>")
220
- end).to raise_error(Addressable::URI::InvalidURIError)
220
+ end.to raise_error(Addressable::URI::InvalidURIError)
221
221
  end
222
222
  end
223
223
 
224
224
  describe Addressable::URI, "when created with a host consisting of " +
225
225
  "sub-delims characters" do
226
226
  it "should not raise an error" do
227
- expect(lambda do
227
+ expect do
228
228
  Addressable::URI.new(
229
229
  :host => Addressable::URI::CharacterClasses::SUB_DELIMS.gsub(/\\/, '')
230
230
  )
231
- end).not_to raise_error
231
+ end.not_to raise_error
232
232
  end
233
233
  end
234
234
 
235
235
  describe Addressable::URI, "when created with a host consisting of " +
236
236
  "unreserved characters" do
237
237
  it "should not raise an error" do
238
- expect(lambda do
238
+ expect do
239
239
  Addressable::URI.new(
240
240
  :host => Addressable::URI::CharacterClasses::UNRESERVED.gsub(/\\/, '')
241
241
  )
242
- end).not_to raise_error
242
+ end.not_to raise_error
243
243
  end
244
244
  end
245
245
 
@@ -269,83 +269,83 @@ describe Addressable::URI, "when created from nil components" do
269
269
  end
270
270
 
271
271
  it "should raise an error if the scheme is set to whitespace" do
272
- expect(lambda do
272
+ expect do
273
273
  @uri.scheme = "\t \n"
274
- end).to raise_error(Addressable::URI::InvalidURIError)
274
+ end.to raise_error(Addressable::URI::InvalidURIError, /'\t \n'/)
275
275
  end
276
276
 
277
277
  it "should raise an error if the scheme is set to all digits" do
278
- expect(lambda do
278
+ expect do
279
279
  @uri.scheme = "123"
280
- end).to raise_error(Addressable::URI::InvalidURIError)
280
+ end.to raise_error(Addressable::URI::InvalidURIError, /'123'/)
281
281
  end
282
282
 
283
283
  it "should raise an error if the scheme begins with a digit" do
284
- expect(lambda do
284
+ expect do
285
285
  @uri.scheme = "1scheme"
286
- end).to raise_error(Addressable::URI::InvalidURIError)
286
+ end.to raise_error(Addressable::URI::InvalidURIError, /'1scheme'/)
287
287
  end
288
288
 
289
289
  it "should raise an error if the scheme begins with a plus" do
290
- expect(lambda do
290
+ expect do
291
291
  @uri.scheme = "+scheme"
292
- end).to raise_error(Addressable::URI::InvalidURIError)
292
+ end.to raise_error(Addressable::URI::InvalidURIError, /'\+scheme'/)
293
293
  end
294
294
 
295
295
  it "should raise an error if the scheme begins with a dot" do
296
- expect(lambda do
296
+ expect do
297
297
  @uri.scheme = ".scheme"
298
- end).to raise_error(Addressable::URI::InvalidURIError)
298
+ end.to raise_error(Addressable::URI::InvalidURIError, /'\.scheme'/)
299
299
  end
300
300
 
301
301
  it "should raise an error if the scheme begins with a dash" do
302
- expect(lambda do
302
+ expect do
303
303
  @uri.scheme = "-scheme"
304
- end).to raise_error(Addressable::URI::InvalidURIError)
304
+ end.to raise_error(Addressable::URI::InvalidURIError, /'-scheme'/)
305
305
  end
306
306
 
307
307
  it "should raise an error if the scheme contains an illegal character" do
308
- expect(lambda do
308
+ expect do
309
309
  @uri.scheme = "scheme!"
310
- end).to raise_error(Addressable::URI::InvalidURIError)
310
+ end.to raise_error(Addressable::URI::InvalidURIError, /'scheme!'/)
311
311
  end
312
312
 
313
313
  it "should raise an error if the scheme contains whitespace" do
314
- expect(lambda do
314
+ expect do
315
315
  @uri.scheme = "sch eme"
316
- end).to raise_error(Addressable::URI::InvalidURIError)
316
+ end.to raise_error(Addressable::URI::InvalidURIError, /'sch eme'/)
317
317
  end
318
318
 
319
319
  it "should raise an error if the scheme contains a newline" do
320
- expect(lambda do
320
+ expect do
321
321
  @uri.scheme = "sch\neme"
322
- end).to raise_error(Addressable::URI::InvalidURIError)
322
+ end.to raise_error(Addressable::URI::InvalidURIError)
323
323
  end
324
324
 
325
325
  it "should raise an error if set into an invalid state" do
326
- expect(lambda do
326
+ expect do
327
327
  @uri.user = "user"
328
- end).to raise_error(Addressable::URI::InvalidURIError)
328
+ end.to raise_error(Addressable::URI::InvalidURIError)
329
329
  end
330
330
 
331
331
  it "should raise an error if set into an invalid state" do
332
- expect(lambda do
332
+ expect do
333
333
  @uri.password = "pass"
334
- end).to raise_error(Addressable::URI::InvalidURIError)
334
+ end.to raise_error(Addressable::URI::InvalidURIError)
335
335
  end
336
336
 
337
337
  it "should raise an error if set into an invalid state" do
338
- expect(lambda do
338
+ expect do
339
339
  @uri.scheme = "http"
340
340
  @uri.fragment = "fragment"
341
- end).to raise_error(Addressable::URI::InvalidURIError)
341
+ end.to raise_error(Addressable::URI::InvalidURIError)
342
342
  end
343
343
 
344
344
  it "should raise an error if set into an invalid state" do
345
- expect(lambda do
345
+ expect do
346
346
  @uri.fragment = "fragment"
347
347
  @uri.scheme = "http"
348
- end).to raise_error(Addressable::URI::InvalidURIError)
348
+ end.to raise_error(Addressable::URI::InvalidURIError)
349
349
  end
350
350
  end
351
351
 
@@ -1015,31 +1015,31 @@ describe Addressable::URI, "when created from string components" do
1015
1015
  end
1016
1016
 
1017
1017
  it "should raise an error if invalid components omitted" do
1018
- expect(lambda do
1018
+ expect do
1019
1019
  @uri.omit(:bogus)
1020
- end).to raise_error(ArgumentError)
1021
- expect(lambda do
1020
+ end.to raise_error(ArgumentError)
1021
+ expect do
1022
1022
  @uri.omit(:scheme, :bogus, :path)
1023
- end).to raise_error(ArgumentError)
1023
+ end.to raise_error(ArgumentError)
1024
1024
  end
1025
1025
  end
1026
1026
 
1027
1027
  describe Addressable::URI, "when created with a nil host but " +
1028
1028
  "non-nil authority components" do
1029
1029
  it "should raise an error" do
1030
- expect(lambda do
1030
+ expect do
1031
1031
  Addressable::URI.new(:user => "user", :password => "pass", :port => 80)
1032
- end).to raise_error(Addressable::URI::InvalidURIError)
1032
+ end.to raise_error(Addressable::URI::InvalidURIError)
1033
1033
  end
1034
1034
  end
1035
1035
 
1036
1036
  describe Addressable::URI, "when created with both an authority and a user" do
1037
1037
  it "should raise an error" do
1038
- expect(lambda do
1038
+ expect do
1039
1039
  Addressable::URI.new(
1040
1040
  :user => "user", :authority => "user@example.com:80"
1041
1041
  )
1042
- end).to raise_error(ArgumentError)
1042
+ end.to raise_error(ArgumentError)
1043
1043
  end
1044
1044
  end
1045
1045
 
@@ -1077,33 +1077,33 @@ end
1077
1077
 
1078
1078
  describe Addressable::URI, "when created with a host with a backslash" do
1079
1079
  it "should raise an error" do
1080
- expect(lambda do
1080
+ expect do
1081
1081
  Addressable::URI.new(:authority => "example\\example")
1082
- end).to raise_error(Addressable::URI::InvalidURIError)
1082
+ end.to raise_error(Addressable::URI::InvalidURIError)
1083
1083
  end
1084
1084
  end
1085
1085
 
1086
1086
  describe Addressable::URI, "when created with a host with a slash" do
1087
1087
  it "should raise an error" do
1088
- expect(lambda do
1088
+ expect do
1089
1089
  Addressable::URI.new(:authority => "example/example")
1090
- end).to raise_error(Addressable::URI::InvalidURIError)
1090
+ end.to raise_error(Addressable::URI::InvalidURIError)
1091
1091
  end
1092
1092
  end
1093
1093
 
1094
1094
  describe Addressable::URI, "when created with a host with a space" do
1095
1095
  it "should raise an error" do
1096
- expect(lambda do
1096
+ expect do
1097
1097
  Addressable::URI.new(:authority => "example example")
1098
- end).to raise_error(Addressable::URI::InvalidURIError)
1098
+ end.to raise_error(Addressable::URI::InvalidURIError)
1099
1099
  end
1100
1100
  end
1101
1101
 
1102
1102
  describe Addressable::URI, "when created with both a userinfo and a user" do
1103
1103
  it "should raise an error" do
1104
- expect(lambda do
1104
+ expect do
1105
1105
  Addressable::URI.new(:user => "user", :userinfo => "user:pass")
1106
- end).to raise_error(ArgumentError)
1106
+ end.to raise_error(ArgumentError)
1107
1107
  end
1108
1108
  end
1109
1109
 
@@ -1195,18 +1195,18 @@ describe Addressable::URI, "when parsed from something that looks " +
1195
1195
  "like a URI object" do
1196
1196
  it "should parse without error" do
1197
1197
  uri = Addressable::URI.parse(Fake::URI::HTTP.new("http://example.com/"))
1198
- expect(lambda do
1198
+ expect do
1199
1199
  Addressable::URI.parse(uri)
1200
- end).not_to raise_error
1200
+ end.not_to raise_error
1201
1201
  end
1202
1202
  end
1203
1203
 
1204
1204
  describe Addressable::URI, "when parsed from a standard library URI object" do
1205
1205
  it "should parse without error" do
1206
1206
  uri = Addressable::URI.parse(URI.parse("http://example.com/"))
1207
- expect(lambda do
1207
+ expect do
1208
1208
  Addressable::URI.parse(uri)
1209
- end).not_to raise_error
1209
+ end.not_to raise_error
1210
1210
  end
1211
1211
  end
1212
1212
 
@@ -1366,9 +1366,9 @@ describe Addressable::URI, "when parsed from " +
1366
1366
  end
1367
1367
 
1368
1368
  it "should not allow request URI assignment" do
1369
- expect(lambda do
1369
+ expect do
1370
1370
  @uri.request_uri = "/"
1371
- end).to raise_error(Addressable::URI::InvalidURIError)
1371
+ end.to raise_error(Addressable::URI::InvalidURIError)
1372
1372
  end
1373
1373
 
1374
1374
  it "should have a query of 'objectClass?one'" do
@@ -1390,9 +1390,9 @@ describe Addressable::URI, "when parsed from " +
1390
1390
  end
1391
1391
 
1392
1392
  it "should raise an error if omission would create an invalid URI" do
1393
- expect(lambda do
1393
+ expect do
1394
1394
  @uri.omit(:authority, :path)
1395
- end).to raise_error(Addressable::URI::InvalidURIError)
1395
+ end.to raise_error(Addressable::URI::InvalidURIError)
1396
1396
  end
1397
1397
 
1398
1398
  it "should have an origin of 'ldap://[2001:db8::7]'" do
@@ -1778,9 +1778,9 @@ describe Addressable::URI, "when parsed from " +
1778
1778
 
1779
1779
  it "should not be roughly equal to the string " +
1780
1780
  "'http://example.com:bogus/'" do
1781
- expect(lambda do
1781
+ expect do
1782
1782
  expect(@uri === "http://example.com:bogus/").to eq(false)
1783
- end).not_to raise_error
1783
+ end.not_to raise_error
1784
1784
  end
1785
1785
 
1786
1786
  it "should result in itself when joined with itself" do
@@ -1810,21 +1810,21 @@ describe Addressable::URI, "when parsed from " +
1810
1810
  end
1811
1811
 
1812
1812
  it "should not allow origin assignment without scheme" do
1813
- expect(lambda do
1813
+ expect do
1814
1814
  @uri.origin = "example.com"
1815
- end).to raise_error(Addressable::URI::InvalidURIError)
1815
+ end.to raise_error(Addressable::URI::InvalidURIError)
1816
1816
  end
1817
1817
 
1818
1818
  it "should not allow origin assignment without host" do
1819
- expect(lambda do
1819
+ expect do
1820
1820
  @uri.origin = "http://"
1821
- end).to raise_error(Addressable::URI::InvalidURIError)
1821
+ end.to raise_error(Addressable::URI::InvalidURIError)
1822
1822
  end
1823
1823
 
1824
1824
  it "should not allow origin assignment with bogus type" do
1825
- expect(lambda do
1825
+ expect do
1826
1826
  @uri.origin = :bogus
1827
- end).to raise_error(TypeError)
1827
+ end.to raise_error(TypeError)
1828
1828
  end
1829
1829
 
1830
1830
  # Section 6.2.3 of RFC 3986
@@ -1880,9 +1880,9 @@ describe Addressable::URI, "when parsed from " +
1880
1880
  end
1881
1881
 
1882
1882
  it "when joined with a bogus object a TypeError should be raised" do
1883
- expect(lambda do
1883
+ expect do
1884
1884
  @uri.join(42)
1885
- end).to raise_error(TypeError)
1885
+ end.to raise_error(TypeError)
1886
1886
  end
1887
1887
 
1888
1888
  it "should have the correct username after assignment" do
@@ -2015,15 +2015,15 @@ describe Addressable::URI, "when parsed from " +
2015
2015
  end
2016
2016
 
2017
2017
  it "should raise an error if the site value is set to something bogus" do
2018
- expect(lambda do
2018
+ expect do
2019
2019
  @uri.site = 42
2020
- end).to raise_error(TypeError)
2020
+ end.to raise_error(TypeError)
2021
2021
  end
2022
2022
 
2023
2023
  it "should raise an error if the request URI is set to something bogus" do
2024
- expect(lambda do
2024
+ expect do
2025
2025
  @uri.request_uri = 42
2026
- end).to raise_error(TypeError)
2026
+ end.to raise_error(TypeError)
2027
2027
  end
2028
2028
 
2029
2029
  it "should correctly convert to a hash" do
@@ -2072,9 +2072,9 @@ describe Addressable::URI, "when parsing IPv6 addresses" do
2072
2072
 
2073
2073
  it "should raise an error for " +
2074
2074
  "'http://[<invalid>]/'" do
2075
- expect(lambda do
2075
+ expect do
2076
2076
  Addressable::URI.parse("http://[<invalid>]/")
2077
- end).to raise_error(Addressable::URI::InvalidURIError)
2077
+ end.to raise_error(Addressable::URI::InvalidURIError)
2078
2078
  end
2079
2079
  end
2080
2080
 
@@ -2100,9 +2100,9 @@ describe Addressable::URI, "when assigning IPv6 address" do
2100
2100
  it "should not allow to set bare IPv6 address as host" do
2101
2101
  uri = Addressable::URI.parse("http://[::1]/")
2102
2102
  skip "not checked"
2103
- expect(lambda do
2103
+ expect do
2104
2104
  uri.host = '3ffe:1900:4545:3:200:f8ff:fe21:67cf'
2105
- end).to raise_error(Addressable::URI::InvalidURIError)
2105
+ end.to raise_error(Addressable::URI::InvalidURIError)
2106
2106
  end
2107
2107
  end
2108
2108
 
@@ -2134,9 +2134,9 @@ describe Addressable::URI, "when parsing IPvFuture addresses" do
2134
2134
 
2135
2135
  it "should raise an error for " +
2136
2136
  "'http://[v0.<invalid>]/'" do
2137
- expect(lambda do
2137
+ expect do
2138
2138
  Addressable::URI.parse("http://[v0.<invalid>]/")
2139
- end).to raise_error(Addressable::URI::InvalidURIError)
2139
+ end.to raise_error(Addressable::URI::InvalidURIError)
2140
2140
  end
2141
2141
  end
2142
2142
 
@@ -2480,9 +2480,9 @@ describe Addressable::URI, "when parsed from " +
2480
2480
  end
2481
2481
 
2482
2482
  it "should not raise an exception when normalized" do
2483
- expect(lambda do
2483
+ expect do
2484
2484
  @uri.normalize
2485
- end).not_to raise_error
2485
+ end.not_to raise_error
2486
2486
  end
2487
2487
 
2488
2488
  it "should be considered to be in normal form" do
@@ -2534,9 +2534,9 @@ describe Addressable::URI, "when parsed from " +
2534
2534
  end
2535
2535
 
2536
2536
  it "should not raise an exception when normalized" do
2537
- expect(lambda do
2537
+ expect do
2538
2538
  @uri.normalize
2539
- end).not_to raise_error
2539
+ end.not_to raise_error
2540
2540
  end
2541
2541
 
2542
2542
  it "should be considered to be in normal form" do
@@ -2559,9 +2559,9 @@ describe Addressable::URI, "when parsed from " +
2559
2559
  end
2560
2560
 
2561
2561
  it "should not raise an exception when normalized" do
2562
- expect(lambda do
2562
+ expect do
2563
2563
  @uri.normalize
2564
- end).not_to raise_error
2564
+ end.not_to raise_error
2565
2565
  end
2566
2566
 
2567
2567
  it "should be considered to be in normal form" do
@@ -2597,9 +2597,9 @@ describe Addressable::URI, "when parsed from " +
2597
2597
  end
2598
2598
 
2599
2599
  it "should raise an error if encoding with an unexpected return type" do
2600
- expect(lambda do
2600
+ expect do
2601
2601
  Addressable::URI.normalized_encode(@uri, Integer)
2602
- end).to raise_error(TypeError)
2602
+ end.to raise_error(TypeError)
2603
2603
  end
2604
2604
 
2605
2605
  it "if percent encoded should be 'http://example.com/C%25CC%25A7'" do
@@ -2615,9 +2615,9 @@ describe Addressable::URI, "when parsed from " +
2615
2615
  end
2616
2616
 
2617
2617
  it "should raise an error if encoding with an unexpected return type" do
2618
- expect(lambda do
2618
+ expect do
2619
2619
  Addressable::URI.encode(@uri, Integer)
2620
- end).to raise_error(TypeError)
2620
+ end.to raise_error(TypeError)
2621
2621
  end
2622
2622
 
2623
2623
  it "should be identical to its duplicate" do
@@ -2752,9 +2752,9 @@ describe Addressable::URI, "when parsed from " +
2752
2752
 
2753
2753
  it "should not be roughly equal to the string " +
2754
2754
  "'http://example.com:bogus/'" do
2755
- expect(lambda do
2755
+ expect do
2756
2756
  expect(@uri === "http://example.com:bogus/").to eq(false)
2757
- end).not_to raise_error
2757
+ end.not_to raise_error
2758
2758
  end
2759
2759
 
2760
2760
  it "should result in itself when joined with itself" do
@@ -3100,9 +3100,9 @@ describe Addressable::URI, "when parsed from " +
3100
3100
  end
3101
3101
 
3102
3102
  it "should become invalid when normalized" do
3103
- expect(lambda do
3103
+ expect do
3104
3104
  @uri.normalize
3105
- end).to raise_error(Addressable::URI::InvalidURIError, /authority/)
3105
+ end.to raise_error(Addressable::URI::InvalidURIError, /authority/)
3106
3106
  end
3107
3107
 
3108
3108
  it "should have a path of '/..//example.com'" do
@@ -3340,12 +3340,12 @@ describe Addressable::URI, "when parsed from " +
3340
3340
  end
3341
3341
 
3342
3342
  it "should raise an error if routing is attempted" do
3343
- expect(lambda do
3343
+ expect do
3344
3344
  @uri.route_to("http://example.com/")
3345
- end).to raise_error(ArgumentError, /relative\/path\/to\/resource/)
3346
- expect(lambda do
3345
+ end.to raise_error(ArgumentError, /relative\/path\/to\/resource/)
3346
+ expect do
3347
3347
  @uri.route_from("http://example.com/")
3348
- end).to raise_error(ArgumentError, /relative\/path\/to\/resource/)
3348
+ end.to raise_error(ArgumentError, /relative\/path\/to\/resource/)
3349
3349
  end
3350
3350
 
3351
3351
  it "when joined with 'another/relative/path' should be " +
@@ -3942,9 +3942,9 @@ describe Addressable::URI, "when parsed from " +
3942
3942
  end
3943
3943
 
3944
3944
  it "should raise an error if assigning a bogus object to the hostname" do
3945
- expect(lambda do
3945
+ expect do
3946
3946
  @uri.hostname = Object.new
3947
- end).to raise_error
3947
+ end.to raise_error(TypeError)
3948
3948
  end
3949
3949
 
3950
3950
  it "should have the correct port after assignment" do
@@ -4023,9 +4023,9 @@ describe Addressable::URI, "when parsed from " +
4023
4023
  end
4024
4024
 
4025
4025
  it "should raise an error if query values are set to a bogus type" do
4026
- expect(lambda do
4026
+ expect do
4027
4027
  @uri.query_values = "bogus"
4028
- end).to raise_error(TypeError)
4028
+ end.to raise_error(TypeError)
4029
4029
  end
4030
4030
 
4031
4031
  it "should have the correct fragment after assignment" do
@@ -4097,39 +4097,39 @@ describe Addressable::URI, "when parsed from " +
4097
4097
  end
4098
4098
 
4099
4099
  it "should fail to merge with bogus values" do
4100
- expect(lambda do
4100
+ expect do
4101
4101
  @uri.merge(:port => "bogus")
4102
- end).to raise_error(Addressable::URI::InvalidURIError)
4102
+ end.to raise_error(Addressable::URI::InvalidURIError)
4103
4103
  end
4104
4104
 
4105
4105
  it "should fail to merge with bogus values" do
4106
- expect(lambda do
4106
+ expect do
4107
4107
  @uri.merge(:authority => "bar@baz:bogus")
4108
- end).to raise_error(Addressable::URI::InvalidURIError)
4108
+ end.to raise_error(Addressable::URI::InvalidURIError)
4109
4109
  end
4110
4110
 
4111
4111
  it "should fail to merge with bogus parameters" do
4112
- expect(lambda do
4112
+ expect do
4113
4113
  @uri.merge(42)
4114
- end).to raise_error(TypeError)
4114
+ end.to raise_error(TypeError)
4115
4115
  end
4116
4116
 
4117
4117
  it "should fail to merge with bogus parameters" do
4118
- expect(lambda do
4118
+ expect do
4119
4119
  @uri.merge("http://example.com/")
4120
- end).to raise_error(TypeError)
4120
+ end.to raise_error(TypeError)
4121
4121
  end
4122
4122
 
4123
4123
  it "should fail to merge with both authority and subcomponents" do
4124
- expect(lambda do
4124
+ expect do
4125
4125
  @uri.merge(:authority => "foo:bar@baz:42", :port => "42")
4126
- end).to raise_error(ArgumentError)
4126
+ end.to raise_error(ArgumentError)
4127
4127
  end
4128
4128
 
4129
4129
  it "should fail to merge with both userinfo and subcomponents" do
4130
- expect(lambda do
4130
+ expect do
4131
4131
  @uri.merge(:userinfo => "foo:bar", :user => "foo")
4132
- end).to raise_error(ArgumentError)
4132
+ end.to raise_error(ArgumentError)
4133
4133
  end
4134
4134
 
4135
4135
  it "should be identical to its duplicate" do
@@ -4262,6 +4262,36 @@ describe Addressable::URI, "when parsed from " +
4262
4262
  end
4263
4263
  end
4264
4264
 
4265
+ describe Addressable::URI, "when parsed from 'https://example.com/?q=a+b'" do
4266
+ before do
4267
+ @uri = Addressable::URI.parse("https://example.com/?q=a+b")
4268
+ end
4269
+
4270
+ it "should have query_values of {'q' => 'a b'}" do
4271
+ expect(@uri.query_values).to eq("q" => "a b")
4272
+ end
4273
+ end
4274
+
4275
+ describe Addressable::URI, "when parsed from 'example.com?q=a+b'" do
4276
+ before do
4277
+ @uri = Addressable::URI.parse("example.com?q=a+b")
4278
+ end
4279
+
4280
+ it "should have query_values of {'q' => 'a b'}" do
4281
+ expect(@uri.query_values).to eq("q" => "a b")
4282
+ end
4283
+ end
4284
+
4285
+ describe Addressable::URI, "when parsed from 'mailto:?q=a+b'" do
4286
+ before do
4287
+ @uri = Addressable::URI.parse("mailto:?q=a+b")
4288
+ end
4289
+
4290
+ it "should have query_values of {'q' => 'a+b'}" do
4291
+ expect(@uri.query_values).to eq("q" => "a+b")
4292
+ end
4293
+ end
4294
+
4265
4295
  describe Addressable::URI, "when parsed from " +
4266
4296
  "'http://example.com/?q=a%2bb'" do
4267
4297
  before do
@@ -4303,6 +4333,46 @@ describe Addressable::URI, "when parsed from " +
4303
4333
  end
4304
4334
  end
4305
4335
 
4336
+ describe Addressable::URI, "when parsed from 'http://example/?b=1&a=2&c=3'" do
4337
+ before do
4338
+ @uri = Addressable::URI.parse("http://example/?b=1&a=2&c=3")
4339
+ end
4340
+
4341
+ it "should have a sorted normalized query of 'a=2&b=1&c=3'" do
4342
+ expect(@uri.normalized_query(:sorted)).to eq("a=2&b=1&c=3")
4343
+ end
4344
+ end
4345
+
4346
+ describe Addressable::URI, "when parsed from 'http://example/?&a&&c&'" do
4347
+ before do
4348
+ @uri = Addressable::URI.parse("http://example/?&a&&c&")
4349
+ end
4350
+
4351
+ it "should have a compacted normalized query of 'a&c'" do
4352
+ expect(@uri.normalized_query(:compacted)).to eq("a&c")
4353
+ end
4354
+ end
4355
+
4356
+ describe Addressable::URI, "when parsed from 'http://example.com/?a=1&a=1'" do
4357
+ before do
4358
+ @uri = Addressable::URI.parse("http://example.com/?a=1&a=1")
4359
+ end
4360
+
4361
+ it "should have a compacted normalized query of 'a=1'" do
4362
+ expect(@uri.normalized_query(:compacted)).to eq("a=1")
4363
+ end
4364
+ end
4365
+
4366
+ describe Addressable::URI, "when parsed from 'http://example.com/?a=1&a=2'" do
4367
+ before do
4368
+ @uri = Addressable::URI.parse("http://example.com/?a=1&a=2")
4369
+ end
4370
+
4371
+ it "should have a compacted normalized query of 'a=1&a=2'" do
4372
+ expect(@uri.normalized_query(:compacted)).to eq("a=1&a=2")
4373
+ end
4374
+ end
4375
+
4306
4376
  describe Addressable::URI, "when parsed from " +
4307
4377
  "'http://example.com/sound%2bvision'" do
4308
4378
  before do
@@ -4414,10 +4484,10 @@ describe Addressable::URI, "when parsed from " +
4414
4484
  end
4415
4485
 
4416
4486
  it "should raise an error after nil assignment of authority segment" do
4417
- expect(lambda do
4487
+ expect do
4418
4488
  # This would create an invalid URI
4419
4489
  @uri.authority = nil
4420
- end).to raise_error
4490
+ end.to raise_error(Addressable::URI::InvalidURIError)
4421
4491
  end
4422
4492
  end
4423
4493
 
@@ -4646,12 +4716,12 @@ describe Addressable::URI, "when parsed from " +
4646
4716
  end
4647
4717
 
4648
4718
  it "should raise an error if routing is attempted" do
4649
- expect(lambda do
4719
+ expect do
4650
4720
  @uri.route_to("http://example.com/")
4651
- end).to raise_error(ArgumentError, /\/\/example.com\//)
4652
- expect(lambda do
4721
+ end.to raise_error(ArgumentError, /\/\/example.com\//)
4722
+ expect do
4653
4723
  @uri.route_from("http://example.com/")
4654
- end).to raise_error(ArgumentError, /\/\/example.com\//)
4724
+ end.to raise_error(ArgumentError, /\/\/example.com\//)
4655
4725
  end
4656
4726
 
4657
4727
  it "should have a 'null' origin" do
@@ -4745,9 +4815,9 @@ end
4745
4815
  describe Addressable::URI, "when parsed from " +
4746
4816
  "'http://under_score.example.com/'" do
4747
4817
  it "should not cause an error" do
4748
- expect(lambda do
4818
+ expect do
4749
4819
  Addressable::URI.parse("http://under_score.example.com/")
4750
- end).not_to raise_error
4820
+ end.not_to raise_error
4751
4821
  end
4752
4822
  end
4753
4823
 
@@ -4819,9 +4889,9 @@ describe Addressable::URI, "when parsed from '?one=1&two=2&three=3'" do
4819
4889
  end
4820
4890
 
4821
4891
  it "should raise an error for invalid return type values" do
4822
- expect(lambda do
4823
- @uri.query_values(Fixnum)
4824
- end).to raise_error(ArgumentError)
4892
+ expect do
4893
+ @uri.query_values(Integer)
4894
+ end.to raise_error(ArgumentError)
4825
4895
  end
4826
4896
 
4827
4897
  it "should have the correct array query values" do
@@ -5422,9 +5492,9 @@ describe Addressable::URI, "with a base uri of 'http://a/b/c/d;p?q'" do
5422
5492
  end
5423
5493
 
5424
5494
  it "when joined with a bogus object a TypeError should be raised" do
5425
- expect(lambda do
5495
+ expect do
5426
5496
  Addressable::URI.join(@uri, 42)
5427
- end).to raise_error(TypeError)
5497
+ end.to raise_error(TypeError)
5428
5498
  end
5429
5499
  end
5430
5500
 
@@ -5451,9 +5521,9 @@ end
5451
5521
 
5452
5522
  describe Addressable::URI, "when converting a bogus path" do
5453
5523
  it "should raise a TypeError" do
5454
- expect(lambda do
5524
+ expect do
5455
5525
  Addressable::URI.convert_path(42)
5456
- end).to raise_error(TypeError)
5526
+ end.to raise_error(TypeError)
5457
5527
  end
5458
5528
  end
5459
5529
 
@@ -5515,18 +5585,18 @@ describe Addressable::URI, "when given the tld " do
5515
5585
  end
5516
5586
 
5517
5587
  context "which " do
5518
- let (:uri) { Addressable::URI.parse("http://comrade.net/path/to/source/") }
5588
+ let (:uri) { Addressable::URI.parse("http://www.comrade.net/path/to/source/") }
5519
5589
 
5520
5590
  it "contains a subdomain" do
5521
5591
  uri.tld = "co.uk"
5522
5592
 
5523
- expect(uri.to_s).to eq("http://comrade.co.uk/path/to/source/")
5593
+ expect(uri.to_s).to eq("http://www.comrade.co.uk/path/to/source/")
5524
5594
  end
5525
5595
 
5526
5596
  it "is part of the domain" do
5527
5597
  uri.tld = "com"
5528
5598
 
5529
- expect(uri.to_s).to eq("http://comrade.com/path/to/source/")
5599
+ expect(uri.to_s).to eq("http://www.comrade.com/path/to/source/")
5530
5600
  end
5531
5601
  end
5532
5602
  end
@@ -5648,9 +5718,9 @@ describe Addressable::URI, "when parsing a non-String object" do
5648
5718
  end
5649
5719
 
5650
5720
  it "should raise a TypeError for objects than cannot be converted" do
5651
- expect(lambda do
5721
+ expect do
5652
5722
  Addressable::URI.parse(42)
5653
- end).to raise_error(TypeError)
5723
+ end.to raise_error(TypeError)
5654
5724
  end
5655
5725
 
5656
5726
  it "should correctly parse heuristically anything with a 'to_str' method" do
@@ -5658,9 +5728,9 @@ describe Addressable::URI, "when parsing a non-String object" do
5658
5728
  end
5659
5729
 
5660
5730
  it "should raise a TypeError for objects than cannot be converted" do
5661
- expect(lambda do
5731
+ expect do
5662
5732
  Addressable::URI.heuristic_parse(42)
5663
- end).to raise_error(TypeError)
5733
+ end.to raise_error(TypeError)
5664
5734
  end
5665
5735
  end
5666
5736
 
@@ -5704,9 +5774,9 @@ end
5704
5774
 
5705
5775
  describe Addressable::URI, "when form encoding a non-Array object" do
5706
5776
  it "should raise a TypeError for objects than cannot be converted" do
5707
- expect(lambda do
5777
+ expect do
5708
5778
  Addressable::URI.form_encode(42)
5709
- end).to raise_error(TypeError)
5779
+ end.to raise_error(TypeError)
5710
5780
  end
5711
5781
  end
5712
5782
 
@@ -5772,9 +5842,9 @@ describe Addressable::URI, "when form unencoding a non-String object" do
5772
5842
  end
5773
5843
 
5774
5844
  it "should raise a TypeError for objects than cannot be converted" do
5775
- expect(lambda do
5845
+ expect do
5776
5846
  Addressable::URI.form_unencode(42)
5777
- end).to raise_error(TypeError)
5847
+ end.to raise_error(TypeError)
5778
5848
  end
5779
5849
  end
5780
5850
 
@@ -5784,15 +5854,15 @@ describe Addressable::URI, "when normalizing a non-String object" do
5784
5854
  end
5785
5855
 
5786
5856
  it "should raise a TypeError for objects than cannot be converted" do
5787
- expect(lambda do
5857
+ expect do
5788
5858
  Addressable::URI.normalize_component(42)
5789
- end).to raise_error(TypeError)
5859
+ end.to raise_error(TypeError)
5790
5860
  end
5791
5861
 
5792
5862
  it "should raise a TypeError for objects than cannot be converted" do
5793
- expect(lambda do
5863
+ expect do
5794
5864
  Addressable::URI.normalize_component("component", 42)
5795
- end).to raise_error(TypeError)
5865
+ end.to raise_error(TypeError)
5796
5866
  end
5797
5867
  end
5798
5868
 
@@ -5864,6 +5934,18 @@ describe Addressable::URI, "when normalizing a string but leaving some character
5864
5934
  end
5865
5935
  end
5866
5936
 
5937
+ describe Addressable::URI, "when encoding IP literals" do
5938
+ it "should work for IPv4" do
5939
+ input = "http://127.0.0.1/"
5940
+ expect(Addressable::URI.encode(input)).to eq(input)
5941
+ end
5942
+
5943
+ it "should work for IPv6" do
5944
+ input = "http://[fe80::200:f8ff:fe21:67cf]/"
5945
+ expect(Addressable::URI.encode(input)).to eq(input)
5946
+ end
5947
+ end
5948
+
5867
5949
  describe Addressable::URI, "when encoding a string with existing encodings to upcase" do
5868
5950
  it "should result in correct percent encoded sequence" do
5869
5951
  expect(Addressable::URI.encode_component("JK%4c", "0-9A-IKM-Za-z%", "L")).to eq("%4AK%4C")
@@ -5936,41 +6018,41 @@ end
5936
6018
 
5937
6019
  describe Addressable::URI, "when unencoding a bogus object" do
5938
6020
  it "should raise a TypeError" do
5939
- expect(lambda do
6021
+ expect do
5940
6022
  Addressable::URI.unencode_component(42)
5941
- end).to raise_error(TypeError)
6023
+ end.to raise_error(TypeError)
5942
6024
  end
5943
6025
 
5944
6026
  it "should raise a TypeError" do
5945
- expect(lambda do
6027
+ expect do
5946
6028
  Addressable::URI.unencode("/path?g%C3%BCnther", Integer)
5947
- end).to raise_error(TypeError)
6029
+ end.to raise_error(TypeError)
5948
6030
  end
5949
6031
  end
5950
6032
 
5951
6033
  describe Addressable::URI, "when encoding a bogus object" do
5952
6034
  it "should raise a TypeError" do
5953
- expect(lambda do
6035
+ expect do
5954
6036
  Addressable::URI.encode(Object.new)
5955
- end).to raise_error(TypeError)
6037
+ end.to raise_error(TypeError)
5956
6038
  end
5957
6039
 
5958
6040
  it "should raise a TypeError" do
5959
- expect(lambda do
6041
+ expect do
5960
6042
  Addressable::URI.normalized_encode(Object.new)
5961
- end).to raise_error(TypeError)
6043
+ end.to raise_error(TypeError)
5962
6044
  end
5963
6045
 
5964
6046
  it "should raise a TypeError" do
5965
- expect(lambda do
6047
+ expect do
5966
6048
  Addressable::URI.encode_component("günther", Object.new)
5967
- end).to raise_error(TypeError)
6049
+ end.to raise_error(TypeError)
5968
6050
  end
5969
6051
 
5970
6052
  it "should raise a TypeError" do
5971
- expect(lambda do
6053
+ expect do
5972
6054
  Addressable::URI.encode_component(Object.new)
5973
- end).to raise_error(TypeError)
6055
+ end.to raise_error(TypeError)
5974
6056
  end
5975
6057
  end
5976
6058
 
@@ -5986,9 +6068,9 @@ describe Addressable::URI, "when given the input " +
5986
6068
  end
5987
6069
 
5988
6070
  it "should not raise error when frozen" do
5989
- expect(lambda do
6071
+ expect do
5990
6072
  Addressable::URI.heuristic_parse(@input).freeze.to_s
5991
- end).not_to raise_error
6073
+ end.not_to raise_error
5992
6074
  end
5993
6075
  end
5994
6076
 
@@ -6352,6 +6434,44 @@ describe Addressable::URI, "when given the input " +
6352
6434
  end
6353
6435
  end
6354
6436
 
6437
+ describe Addressable::URI, "when given the input: 'user@domain.com'" do
6438
+ before do
6439
+ @input = "user@domain.com"
6440
+ end
6441
+
6442
+ context "for heuristic parse" do
6443
+ it "should remain 'mailto:user@domain.com'" do
6444
+ uri = Addressable::URI.heuristic_parse("mailto:#{@input}")
6445
+ expect(uri.to_s).to eq("mailto:user@domain.com")
6446
+ end
6447
+
6448
+ it "should have a scheme of 'mailto'" do
6449
+ uri = Addressable::URI.heuristic_parse(@input)
6450
+ expect(uri.to_s).to eq("mailto:user@domain.com")
6451
+ expect(uri.scheme).to eq("mailto")
6452
+ end
6453
+
6454
+ it "should remain 'acct:user@domain.com'" do
6455
+ uri = Addressable::URI.heuristic_parse("acct:#{@input}")
6456
+ expect(uri.to_s).to eq("acct:user@domain.com")
6457
+ end
6458
+
6459
+ context "HTTP" do
6460
+ before do
6461
+ @uri = Addressable::URI.heuristic_parse("http://#{@input}/")
6462
+ end
6463
+
6464
+ it "should remain 'http://user@domain.com/'" do
6465
+ expect(@uri.to_s).to eq("http://user@domain.com/")
6466
+ end
6467
+
6468
+ it "should have the username 'user' for HTTP basic authentication" do
6469
+ expect(@uri.user).to eq("user")
6470
+ end
6471
+ end
6472
+ end
6473
+ end
6474
+
6355
6475
  describe Addressable::URI, "when assigning query values" do
6356
6476
  before do
6357
6477
  @uri = Addressable::URI.new
@@ -6363,54 +6483,54 @@ describe Addressable::URI, "when assigning query values" do
6363
6483
  end
6364
6484
 
6365
6485
  it "should raise an error attempting to assign {'a' => {'b' => ['c']}}" do
6366
- expect(lambda do
6486
+ expect do
6367
6487
  @uri.query_values = { 'a' => {'b' => ['c'] } }
6368
- end).to raise_error(TypeError)
6488
+ end.to raise_error(TypeError)
6369
6489
  end
6370
6490
 
6371
6491
  it "should raise an error attempting to assign " +
6372
6492
  "{:b => '2', :a => {:c => '1'}}" do
6373
- expect(lambda do
6493
+ expect do
6374
6494
  @uri.query_values = {:b => '2', :a => {:c => '1'}}
6375
- end).to raise_error(TypeError)
6495
+ end.to raise_error(TypeError)
6376
6496
  end
6377
6497
 
6378
6498
  it "should raise an error attempting to assign " +
6379
6499
  "{:a => 'a', :b => [{:c => 'c', :d => 'd'}, " +
6380
6500
  "{:e => 'e', :f => 'f'}]}" do
6381
- expect(lambda do
6501
+ expect do
6382
6502
  @uri.query_values = {
6383
6503
  :a => "a", :b => [{:c => "c", :d => "d"}, {:e => "e", :f => "f"}]
6384
6504
  }
6385
- end).to raise_error(TypeError)
6505
+ end.to raise_error(TypeError)
6386
6506
  end
6387
6507
 
6388
6508
  it "should raise an error attempting to assign " +
6389
6509
  "{:a => 'a', :b => [{:c => true, :d => 'd'}, " +
6390
6510
  "{:e => 'e', :f => 'f'}]}" do
6391
- expect(lambda do
6511
+ expect do
6392
6512
  @uri.query_values = {
6393
6513
  :a => 'a', :b => [{:c => true, :d => 'd'}, {:e => 'e', :f => 'f'}]
6394
6514
  }
6395
- end).to raise_error(TypeError)
6515
+ end.to raise_error(TypeError)
6396
6516
  end
6397
6517
 
6398
6518
  it "should raise an error attempting to assign " +
6399
6519
  "{:a => 'a', :b => {:c => true, :d => 'd'}}" do
6400
- expect(lambda do
6520
+ expect do
6401
6521
  @uri.query_values = {
6402
6522
  :a => 'a', :b => {:c => true, :d => 'd'}
6403
6523
  }
6404
- end).to raise_error(TypeError)
6524
+ end.to raise_error(TypeError)
6405
6525
  end
6406
6526
 
6407
6527
  it "should raise an error attempting to assign " +
6408
6528
  "{:a => 'a', :b => {:c => true, :d => 'd'}}" do
6409
- expect(lambda do
6529
+ expect do
6410
6530
  @uri.query_values = {
6411
6531
  :a => 'a', :b => {:c => true, :d => 'd'}
6412
6532
  }
6413
- end).to raise_error(TypeError)
6533
+ end.to raise_error(TypeError)
6414
6534
  end
6415
6535
 
6416
6536
  it "should correctly assign {:a => 1, :b => 1.5}" do
@@ -6421,13 +6541,13 @@ describe Addressable::URI, "when assigning query values" do
6421
6541
  it "should raise an error attempting to assign " +
6422
6542
  "{:z => 1, :f => [2, {999.1 => [3,'4']}, ['h', 'i']], " +
6423
6543
  ":a => {:b => ['c', 'd'], :e => true, :y => 0.5}}" do
6424
- expect(lambda do
6544
+ expect do
6425
6545
  @uri.query_values = {
6426
6546
  :z => 1,
6427
6547
  :f => [ 2, {999.1 => [3,'4']}, ['h', 'i'] ],
6428
6548
  :a => { :b => ['c', 'd'], :e => true, :y => 0.5 }
6429
6549
  }
6430
- end).to raise_error(TypeError)
6550
+ end.to raise_error(TypeError)
6431
6551
  end
6432
6552
 
6433
6553
  it "should correctly assign {}" do
@@ -6477,7 +6597,7 @@ describe Addressable::URI, "when assigning path values" do
6477
6597
  @uri.path = "acct:bob@sporkmonger.com"
6478
6598
  expect(@uri.path).to eq("acct:bob@sporkmonger.com")
6479
6599
  expect(@uri.normalize.to_str).to eq("acct%2Fbob@sporkmonger.com")
6480
- expect(lambda { @uri.to_s }).to raise_error(
6600
+ expect { @uri.to_s }.to raise_error(
6481
6601
  Addressable::URI::InvalidURIError
6482
6602
  )
6483
6603
  end
@@ -6495,26 +6615,26 @@ describe Addressable::URI, "when assigning path values" do
6495
6615
  end
6496
6616
 
6497
6617
  it "should not allow relative paths to be assigned on absolute URIs" do
6498
- expect(lambda do
6618
+ expect do
6499
6619
  @uri.scheme = "http"
6500
6620
  @uri.host = "example.com"
6501
6621
  @uri.path = "acct:bob@sporkmonger.com"
6502
- end).to raise_error(Addressable::URI::InvalidURIError)
6622
+ end.to raise_error(Addressable::URI::InvalidURIError)
6503
6623
  end
6504
6624
 
6505
6625
  it "should not allow relative paths to be assigned on absolute URIs" do
6506
- expect(lambda do
6626
+ expect do
6507
6627
  @uri.path = "acct:bob@sporkmonger.com"
6508
6628
  @uri.scheme = "http"
6509
6629
  @uri.host = "example.com"
6510
- end).to raise_error(Addressable::URI::InvalidURIError)
6630
+ end.to raise_error(Addressable::URI::InvalidURIError)
6511
6631
  end
6512
6632
 
6513
6633
  it "should not allow relative paths to be assigned on absolute URIs" do
6514
- expect(lambda do
6634
+ expect do
6515
6635
  @uri.path = "uuid:0b3ecf60-3f93-11df-a9c3-001f5bfffe12"
6516
6636
  @uri.scheme = "urn"
6517
- end).not_to raise_error
6637
+ end.not_to raise_error
6518
6638
  end
6519
6639
  end
6520
6640