addressable 2.8.1 → 2.8.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,7 +23,7 @@ if !defined?(Addressable::VERSION)
23
23
  module VERSION
24
24
  MAJOR = 2
25
25
  MINOR = 8
26
- TINY = 1
26
+ TINY = 6
27
27
 
28
28
  STRING = [MAJOR, MINOR, TINY].join('.')
29
29
  end
@@ -38,6 +38,12 @@ shared_examples_for "converting from unicode to ASCII" do
38
38
  )).to eq("www.xn--8ws00zhy3a.com")
39
39
  end
40
40
 
41
+ it "also accepts unicode strings encoded as ascii-8bit" do
42
+ expect(Addressable::IDNA.to_ascii(
43
+ "www.詹姆斯.com".b
44
+ )).to eq("www.xn--8ws00zhy3a.com")
45
+ end
46
+
41
47
  it "should convert 'www.Iñtërnâtiônàlizætiøn.com' correctly" do
42
48
  "www.Iñtërnâtiônàlizætiøn.com"
43
49
  expect(Addressable::IDNA.to_ascii(
@@ -249,11 +255,6 @@ shared_examples_for "converting from ASCII to unicode" do
249
255
  "example..host"
250
256
  )).to eq("example..host")
251
257
  end
252
-
253
- it "should normalize 'string' correctly" do
254
- expect(Addressable::IDNA.unicode_normalize_kc(:'string')).to eq("string")
255
- expect(Addressable::IDNA.unicode_normalize_kc("string")).to eq("string")
256
- end
257
258
  end
258
259
 
259
260
  describe Addressable::IDNA, "when using the pure-Ruby implementation" do
@@ -26,11 +26,7 @@ shared_examples_for 'expands' do |tests|
26
26
  exp = expansion.is_a?(Array) ? expansion.first : expansion
27
27
  it "#{template} to #{exp}" do
28
28
  tmpl = Addressable::Template.new(template).expand(subject)
29
- if expansion.is_a?(Array)
30
- expect(expansion.any?{|i| i == tmpl.to_str}).to be true
31
- else
32
- expect(tmpl.to_str).to eq(expansion)
33
- end
29
+ expect(tmpl.to_str).to eq(expansion)
34
30
  end
35
31
  end
36
32
  end
@@ -209,7 +205,7 @@ describe "Level 4" do
209
205
  :path => "/foo/bar",
210
206
  :semi => ";",
211
207
  :list => %w(red green blue),
212
- :keys => {"semi" => ';', "dot" => '.', "comma" => ','}
208
+ :keys => {"semi" => ';', "dot" => '.', :comma => ','}
213
209
  }
214
210
  }
215
211
  context "Expansion with value modifiers" do
@@ -218,22 +214,8 @@ describe "Level 4" do
218
214
  '{var:30}' => 'value',
219
215
  '{list}' => 'red,green,blue',
220
216
  '{list*}' => 'red,green,blue',
221
- '{keys}' => [
222
- 'semi,%3B,dot,.,comma,%2C',
223
- 'dot,.,semi,%3B,comma,%2C',
224
- 'comma,%2C,semi,%3B,dot,.',
225
- 'semi,%3B,comma,%2C,dot,.',
226
- 'dot,.,comma,%2C,semi,%3B',
227
- 'comma,%2C,dot,.,semi,%3B'
228
- ],
229
- '{keys*}' => [
230
- 'semi=%3B,dot=.,comma=%2C',
231
- 'dot=.,semi=%3B,comma=%2C',
232
- 'comma=%2C,semi=%3B,dot=.',
233
- 'semi=%3B,comma=%2C,dot=.',
234
- 'dot=.,comma=%2C,semi=%3B',
235
- 'comma=%2C,dot=.,semi=%3B'
236
- ]
217
+ '{keys}' => 'semi,%3B,dot,.,comma,%2C',
218
+ '{keys*}' => 'semi=%3B,dot=.,comma=%2C',
237
219
  }
238
220
  end
239
221
  context "Operator + with value modifiers" do
@@ -241,22 +223,8 @@ describe "Level 4" do
241
223
  '{+path:6}/here' => '/foo/b/here',
242
224
  '{+list}' => 'red,green,blue',
243
225
  '{+list*}' => 'red,green,blue',
244
- '{+keys}' => [
245
- 'semi,;,dot,.,comma,,',
246
- 'dot,.,semi,;,comma,,',
247
- 'comma,,,semi,;,dot,.',
248
- 'semi,;,comma,,,dot,.',
249
- 'dot,.,comma,,,semi,;',
250
- 'comma,,,dot,.,semi,;'
251
- ],
252
- '{+keys*}' => [
253
- 'semi=;,dot=.,comma=,',
254
- 'dot=.,semi=;,comma=,',
255
- 'comma=,,semi=;,dot=.',
256
- 'semi=;,comma=,,dot=.',
257
- 'dot=.,comma=,,semi=;',
258
- 'comma=,,dot=.,semi=;'
259
- ]
226
+ '{+keys}' => 'semi,;,dot,.,comma,,',
227
+ '{+keys*}' => 'semi=;,dot=.,comma=,',
260
228
  }
261
229
  end
262
230
  context "Operator # with value modifiers" do
@@ -264,22 +232,8 @@ describe "Level 4" do
264
232
  '{#path:6}/here' => '#/foo/b/here',
265
233
  '{#list}' => '#red,green,blue',
266
234
  '{#list*}' => '#red,green,blue',
267
- '{#keys}' => [
268
- '#semi,;,dot,.,comma,,',
269
- '#dot,.,semi,;,comma,,',
270
- '#comma,,,semi,;,dot,.',
271
- '#semi,;,comma,,,dot,.',
272
- '#dot,.,comma,,,semi,;',
273
- '#comma,,,dot,.,semi,;'
274
- ],
275
- '{#keys*}' => [
276
- '#semi=;,dot=.,comma=,',
277
- '#dot=.,semi=;,comma=,',
278
- '#comma=,,semi=;,dot=.',
279
- '#semi=;,comma=,,dot=.',
280
- '#dot=.,comma=,,semi=;',
281
- '#comma=,,dot=.,semi=;'
282
- ]
235
+ '{#keys}' => '#semi,;,dot,.,comma,,',
236
+ '{#keys*}' => '#semi=;,dot=.,comma=,',
283
237
  }
284
238
  end
285
239
  context "Operator . with value modifiers" do
@@ -287,22 +241,8 @@ describe "Level 4" do
287
241
  'X{.var:3}' => 'X.val',
288
242
  'X{.list}' => 'X.red,green,blue',
289
243
  'X{.list*}' => 'X.red.green.blue',
290
- 'X{.keys}' => [
291
- 'X.semi,%3B,dot,.,comma,%2C',
292
- 'X.dot,.,semi,%3B,comma,%2C',
293
- 'X.comma,%2C,semi,%3B,dot,.',
294
- 'X.semi,%3B,comma,%2C,dot,.',
295
- 'X.dot,.,comma,%2C,semi,%3B',
296
- 'X.comma,%2C,dot,.,semi,%3B'
297
- ],
298
- 'X{.keys*}' => [
299
- 'X.semi=%3B.dot=..comma=%2C',
300
- 'X.dot=..semi=%3B.comma=%2C',
301
- 'X.comma=%2C.semi=%3B.dot=.',
302
- 'X.semi=%3B.comma=%2C.dot=.',
303
- 'X.dot=..comma=%2C.semi=%3B',
304
- 'X.comma=%2C.dot=..semi=%3B'
305
- ]
244
+ 'X{.keys}' => 'X.semi,%3B,dot,.,comma,%2C',
245
+ 'X{.keys*}' => 'X.semi=%3B.dot=..comma=%2C',
306
246
  }
307
247
  end
308
248
  context "Operator / with value modifiers" do
@@ -311,22 +251,8 @@ describe "Level 4" do
311
251
  '{/list}' => '/red,green,blue',
312
252
  '{/list*}' => '/red/green/blue',
313
253
  '{/list*,path:4}' => '/red/green/blue/%2Ffoo',
314
- '{/keys}' => [
315
- '/semi,%3B,dot,.,comma,%2C',
316
- '/dot,.,semi,%3B,comma,%2C',
317
- '/comma,%2C,semi,%3B,dot,.',
318
- '/semi,%3B,comma,%2C,dot,.',
319
- '/dot,.,comma,%2C,semi,%3B',
320
- '/comma,%2C,dot,.,semi,%3B'
321
- ],
322
- '{/keys*}' => [
323
- '/semi=%3B/dot=./comma=%2C',
324
- '/dot=./semi=%3B/comma=%2C',
325
- '/comma=%2C/semi=%3B/dot=.',
326
- '/semi=%3B/comma=%2C/dot=.',
327
- '/dot=./comma=%2C/semi=%3B',
328
- '/comma=%2C/dot=./semi=%3B'
329
- ]
254
+ '{/keys}' => '/semi,%3B,dot,.,comma,%2C',
255
+ '{/keys*}' => '/semi=%3B/dot=./comma=%2C',
330
256
  }
331
257
  end
332
258
  context "Operator ; with value modifiers" do
@@ -334,22 +260,8 @@ describe "Level 4" do
334
260
  '{;hello:5}' => ';hello=Hello',
335
261
  '{;list}' => ';list=red,green,blue',
336
262
  '{;list*}' => ';list=red;list=green;list=blue',
337
- '{;keys}' => [
338
- ';keys=semi,%3B,dot,.,comma,%2C',
339
- ';keys=dot,.,semi,%3B,comma,%2C',
340
- ';keys=comma,%2C,semi,%3B,dot,.',
341
- ';keys=semi,%3B,comma,%2C,dot,.',
342
- ';keys=dot,.,comma,%2C,semi,%3B',
343
- ';keys=comma,%2C,dot,.,semi,%3B'
344
- ],
345
- '{;keys*}' => [
346
- ';semi=%3B;dot=.;comma=%2C',
347
- ';dot=.;semi=%3B;comma=%2C',
348
- ';comma=%2C;semi=%3B;dot=.',
349
- ';semi=%3B;comma=%2C;dot=.',
350
- ';dot=.;comma=%2C;semi=%3B',
351
- ';comma=%2C;dot=.;semi=%3B'
352
- ]
263
+ '{;keys}' => ';keys=semi,%3B,dot,.,comma,%2C',
264
+ '{;keys*}' => ';semi=%3B;dot=.;comma=%2C',
353
265
  }
354
266
  end
355
267
  context "Operator ? with value modifiers" do
@@ -357,22 +269,8 @@ describe "Level 4" do
357
269
  '{?var:3}' => '?var=val',
358
270
  '{?list}' => '?list=red,green,blue',
359
271
  '{?list*}' => '?list=red&list=green&list=blue',
360
- '{?keys}' => [
361
- '?keys=semi,%3B,dot,.,comma,%2C',
362
- '?keys=dot,.,semi,%3B,comma,%2C',
363
- '?keys=comma,%2C,semi,%3B,dot,.',
364
- '?keys=semi,%3B,comma,%2C,dot,.',
365
- '?keys=dot,.,comma,%2C,semi,%3B',
366
- '?keys=comma,%2C,dot,.,semi,%3B'
367
- ],
368
- '{?keys*}' => [
369
- '?semi=%3B&dot=.&comma=%2C',
370
- '?dot=.&semi=%3B&comma=%2C',
371
- '?comma=%2C&semi=%3B&dot=.',
372
- '?semi=%3B&comma=%2C&dot=.',
373
- '?dot=.&comma=%2C&semi=%3B',
374
- '?comma=%2C&dot=.&semi=%3B'
375
- ]
272
+ '{?keys}' => '?keys=semi,%3B,dot,.,comma,%2C',
273
+ '{?keys*}' => '?semi=%3B&dot=.&comma=%2C',
376
274
  }
377
275
  end
378
276
  context "Operator & with value modifiers" do
@@ -380,22 +278,8 @@ describe "Level 4" do
380
278
  '{&var:3}' => '&var=val',
381
279
  '{&list}' => '&list=red,green,blue',
382
280
  '{&list*}' => '&list=red&list=green&list=blue',
383
- '{&keys}' => [
384
- '&keys=semi,%3B,dot,.,comma,%2C',
385
- '&keys=dot,.,semi,%3B,comma,%2C',
386
- '&keys=comma,%2C,semi,%3B,dot,.',
387
- '&keys=semi,%3B,comma,%2C,dot,.',
388
- '&keys=dot,.,comma,%2C,semi,%3B',
389
- '&keys=comma,%2C,dot,.,semi,%3B'
390
- ],
391
- '{&keys*}' => [
392
- '&semi=%3B&dot=.&comma=%2C',
393
- '&dot=.&semi=%3B&comma=%2C',
394
- '&comma=%2C&semi=%3B&dot=.',
395
- '&semi=%3B&comma=%2C&dot=.',
396
- '&dot=.&comma=%2C&semi=%3B',
397
- '&comma=%2C&dot=.&semi=%3B'
398
- ]
281
+ '{&keys}' => '&keys=semi,%3B,dot,.,comma,%2C',
282
+ '{&keys*}' => '&semi=%3B&dot=.&comma=%2C',
399
283
  }
400
284
  end
401
285
  end
@@ -404,7 +288,7 @@ describe "Modifiers" do
404
288
  {
405
289
  :var => "value",
406
290
  :semi => ";",
407
- :year => %w(1965 2000 2012),
291
+ :year => [1965, 2000, 2012],
408
292
  :dom => %w(example com)
409
293
  }
410
294
  }
@@ -437,7 +321,7 @@ describe "Expansion" do
437
321
  :base => "http://example.com/home/",
438
322
  :path => "/foo/bar",
439
323
  :list => ["red", "green", "blue"],
440
- :keys => {"semi" => ";","dot" => ".","comma" => ","},
324
+ :keys => {"semi" => ";","dot" => ".",:comma => ","},
441
325
  :v => "6",
442
326
  :x => "1024",
443
327
  :y => "768",
@@ -475,22 +359,8 @@ describe "Expansion" do
475
359
  '{var:30}' => 'value',
476
360
  '{list}' => 'red,green,blue',
477
361
  '{list*}' => 'red,green,blue',
478
- '{keys}' => [
479
- 'semi,%3B,dot,.,comma,%2C',
480
- 'dot,.,semi,%3B,comma,%2C',
481
- 'comma,%2C,semi,%3B,dot,.',
482
- 'semi,%3B,comma,%2C,dot,.',
483
- 'dot,.,comma,%2C,semi,%3B',
484
- 'comma,%2C,dot,.,semi,%3B'
485
- ],
486
- '{keys*}' => [
487
- 'semi=%3B,dot=.,comma=%2C',
488
- 'dot=.,semi=%3B,comma=%2C',
489
- 'comma=%2C,semi=%3B,dot=.',
490
- 'semi=%3B,comma=%2C,dot=.',
491
- 'dot=.,comma=%2C,semi=%3B',
492
- 'comma=%2C,dot=.,semi=%3B'
493
- ]
362
+ '{keys}' => 'semi,%3B,dot,.,comma,%2C',
363
+ '{keys*}' => 'semi=%3B,dot=.,comma=%2C',
494
364
  }
495
365
  end
496
366
  context "reserved expansion (+)" do
@@ -510,22 +380,8 @@ describe "Expansion" do
510
380
  '{+path:6}/here' => '/foo/b/here',
511
381
  '{+list}' => 'red,green,blue',
512
382
  '{+list*}' => 'red,green,blue',
513
- '{+keys}' => [
514
- 'semi,;,dot,.,comma,,',
515
- 'dot,.,semi,;,comma,,',
516
- 'comma,,,semi,;,dot,.',
517
- 'semi,;,comma,,,dot,.',
518
- 'dot,.,comma,,,semi,;',
519
- 'comma,,,dot,.,semi,;'
520
- ],
521
- '{+keys*}' => [
522
- 'semi=;,dot=.,comma=,',
523
- 'dot=.,semi=;,comma=,',
524
- 'comma=,,semi=;,dot=.',
525
- 'semi=;,comma=,,dot=.',
526
- 'dot=.,comma=,,semi=;',
527
- 'comma=,,dot=.,semi=;'
528
- ]
383
+ '{+keys}' => 'semi,;,dot,.,comma,,',
384
+ '{+keys*}' => 'semi=;,dot=.,comma=,',
529
385
  }
530
386
  end
531
387
  context "fragment expansion (#)" do
@@ -540,22 +396,8 @@ describe "Expansion" do
540
396
  '{#path:6}/here' => '#/foo/b/here',
541
397
  '{#list}' => '#red,green,blue',
542
398
  '{#list*}' => '#red,green,blue',
543
- '{#keys}' => [
544
- '#semi,;,dot,.,comma,,',
545
- '#dot,.,semi,;,comma,,',
546
- '#comma,,,semi,;,dot,.',
547
- '#semi,;,comma,,,dot,.',
548
- '#dot,.,comma,,,semi,;',
549
- '#comma,,,dot,.,semi,;'
550
- ],
551
- '{#keys*}' => [
552
- '#semi=;,dot=.,comma=,',
553
- '#dot=.,semi=;,comma=,',
554
- '#comma=,,semi=;,dot=.',
555
- '#semi=;,comma=,,dot=.',
556
- '#dot=.,comma=,,semi=;',
557
- '#comma=,,dot=.,semi=;'
558
- ]
399
+ '{#keys}' => '#semi,;,dot,.,comma,,',
400
+ '{#keys*}' => '#semi=;,dot=.,comma=,',
559
401
  }
560
402
  end
561
403
  context "label expansion (.)" do
@@ -570,22 +412,8 @@ describe "Expansion" do
570
412
  'X{.var:3}' => 'X.val',
571
413
  'X{.list}' => 'X.red,green,blue',
572
414
  'X{.list*}' => 'X.red.green.blue',
573
- 'X{.keys}' => [
574
- 'X.semi,%3B,dot,.,comma,%2C',
575
- 'X.dot,.,semi,%3B,comma,%2C',
576
- 'X.comma,%2C,semi,%3B,dot,.',
577
- 'X.semi,%3B,comma,%2C,dot,.',
578
- 'X.dot,.,comma,%2C,semi,%3B',
579
- 'X.comma,%2C,dot,.,semi,%3B'
580
- ],
581
- 'X{.keys*}' => [
582
- 'X.semi=%3B.dot=..comma=%2C',
583
- 'X.dot=..semi=%3B.comma=%2C',
584
- 'X.comma=%2C.semi=%3B.dot=.',
585
- 'X.semi=%3B.comma=%2C.dot=.',
586
- 'X.dot=..comma=%2C.semi=%3B',
587
- 'X.comma=%2C.dot=..semi=%3B'
588
- ],
415
+ 'X{.keys}' => 'X.semi,%3B,dot,.,comma,%2C',
416
+ 'X{.keys*}' => 'X.semi=%3B.dot=..comma=%2C',
589
417
  'X{.empty_keys}' => 'X',
590
418
  'X{.empty_keys*}' => 'X'
591
419
  }
@@ -604,22 +432,8 @@ describe "Expansion" do
604
432
  '{/list}' => '/red,green,blue',
605
433
  '{/list*}' => '/red/green/blue',
606
434
  '{/list*,path:4}' => '/red/green/blue/%2Ffoo',
607
- '{/keys}' => [
608
- '/semi,%3B,dot,.,comma,%2C',
609
- '/dot,.,semi,%3B,comma,%2C',
610
- '/comma,%2C,semi,%3B,dot,.',
611
- '/semi,%3B,comma,%2C,dot,.',
612
- '/dot,.,comma,%2C,semi,%3B',
613
- '/comma,%2C,dot,.,semi,%3B'
614
- ],
615
- '{/keys*}' => [
616
- '/semi=%3B/dot=./comma=%2C',
617
- '/dot=./semi=%3B/comma=%2C',
618
- '/comma=%2C/semi=%3B/dot=.',
619
- '/semi=%3B/comma=%2C/dot=.',
620
- '/dot=./comma=%2C/semi=%3B',
621
- '/comma=%2C/dot=./semi=%3B'
622
- ]
435
+ '{/keys}' => '/semi,%3B,dot,.,comma,%2C',
436
+ '{/keys*}' => '/semi=%3B/dot=./comma=%2C',
623
437
  }
624
438
  end
625
439
  context "path-style expansion (;)" do
@@ -635,22 +449,8 @@ describe "Expansion" do
635
449
  '{;hello:5}' => ';hello=Hello',
636
450
  '{;list}' => ';list=red,green,blue',
637
451
  '{;list*}' => ';list=red;list=green;list=blue',
638
- '{;keys}' => [
639
- ';keys=semi,%3B,dot,.,comma,%2C',
640
- ';keys=dot,.,semi,%3B,comma,%2C',
641
- ';keys=comma,%2C,semi,%3B,dot,.',
642
- ';keys=semi,%3B,comma,%2C,dot,.',
643
- ';keys=dot,.,comma,%2C,semi,%3B',
644
- ';keys=comma,%2C,dot,.,semi,%3B'
645
- ],
646
- '{;keys*}' => [
647
- ';semi=%3B;dot=.;comma=%2C',
648
- ';dot=.;semi=%3B;comma=%2C',
649
- ';comma=%2C;semi=%3B;dot=.',
650
- ';semi=%3B;comma=%2C;dot=.',
651
- ';dot=.;comma=%2C;semi=%3B',
652
- ';comma=%2C;dot=.;semi=%3B'
653
- ]
452
+ '{;keys}' => ';keys=semi,%3B,dot,.,comma,%2C',
453
+ '{;keys*}' => ';semi=%3B;dot=.;comma=%2C',
654
454
  }
655
455
  end
656
456
  context "form query expansion (?)" do
@@ -663,22 +463,8 @@ describe "Expansion" do
663
463
  '{?var:3}' => '?var=val',
664
464
  '{?list}' => '?list=red,green,blue',
665
465
  '{?list*}' => '?list=red&list=green&list=blue',
666
- '{?keys}' => [
667
- '?keys=semi,%3B,dot,.,comma,%2C',
668
- '?keys=dot,.,semi,%3B,comma,%2C',
669
- '?keys=comma,%2C,semi,%3B,dot,.',
670
- '?keys=semi,%3B,comma,%2C,dot,.',
671
- '?keys=dot,.,comma,%2C,semi,%3B',
672
- '?keys=comma,%2C,dot,.,semi,%3B'
673
- ],
674
- '{?keys*}' => [
675
- '?semi=%3B&dot=.&comma=%2C',
676
- '?dot=.&semi=%3B&comma=%2C',
677
- '?comma=%2C&semi=%3B&dot=.',
678
- '?semi=%3B&comma=%2C&dot=.',
679
- '?dot=.&comma=%2C&semi=%3B',
680
- '?comma=%2C&dot=.&semi=%3B'
681
- ]
466
+ '{?keys}' => '?keys=semi,%3B,dot,.,comma,%2C',
467
+ '{?keys*}' => '?semi=%3B&dot=.&comma=%2C',
682
468
  }
683
469
  end
684
470
  context "form query expansion (&)" do
@@ -691,22 +477,8 @@ describe "Expansion" do
691
477
  '{&var:3}' => '&var=val',
692
478
  '{&list}' => '&list=red,green,blue',
693
479
  '{&list*}' => '&list=red&list=green&list=blue',
694
- '{&keys}' => [
695
- '&keys=semi,%3B,dot,.,comma,%2C',
696
- '&keys=dot,.,semi,%3B,comma,%2C',
697
- '&keys=comma,%2C,semi,%3B,dot,.',
698
- '&keys=semi,%3B,comma,%2C,dot,.',
699
- '&keys=dot,.,comma,%2C,semi,%3B',
700
- '&keys=comma,%2C,dot,.,semi,%3B'
701
- ],
702
- '{&keys*}' => [
703
- '&semi=%3B&dot=.&comma=%2C',
704
- '&dot=.&semi=%3B&comma=%2C',
705
- '&comma=%2C&semi=%3B&dot=.',
706
- '&semi=%3B&comma=%2C&dot=.',
707
- '&dot=.&comma=%2C&semi=%3B',
708
- '&comma=%2C&dot=.&semi=%3B'
709
- ]
480
+ '{&keys}' => '&keys=semi,%3B,dot,.,comma,%2C',
481
+ '{&keys*}' => '&semi=%3B&dot=.&comma=%2C',
710
482
  }
711
483
  end
712
484
  context "non-string key in match data" do
@@ -1021,6 +793,19 @@ describe Addressable::Template do
1021
793
  )
1022
794
  end
1023
795
 
796
+ it "normalizes as unicode even with wrong encoding specified" do
797
+ template = subject.partial_expand("query" => "Cafe\u0301".b)
798
+ expect(template.pattern).to eq(
799
+ "http://example.com/{resource}/Caf%C3%A9/"
800
+ )
801
+ end
802
+
803
+ it "raises on invalid unicode input" do
804
+ expect {
805
+ subject.partial_expand("query" => "M\xE9thode".b)
806
+ }.to raise_error(ArgumentError, "invalid byte sequence in UTF-8")
807
+ end
808
+
1024
809
  it "does not normalize unicode when byte semantics requested" do
1025
810
  template = subject.partial_expand({"query" => "Cafe\u0301"}, nil, false)
1026
811
  expect(template.pattern).to eq(
@@ -1081,6 +866,17 @@ describe Addressable::Template do
1081
866
  expect(uri).to eq("http://example.com/search/Caf%C3%A9/")
1082
867
  end
1083
868
 
869
+ it "normalizes as unicode even with wrong encoding specified" do
870
+ uri = subject.expand("query" => "Cafe\u0301".b).to_str
871
+ expect(uri).to eq("http://example.com/search/Caf%C3%A9/")
872
+ end
873
+
874
+ it "raises on invalid unicode input" do
875
+ expect {
876
+ subject.expand("query" => "M\xE9thode".b).to_str
877
+ }.to raise_error(ArgumentError, "invalid byte sequence in UTF-8")
878
+ end
879
+
1084
880
  it "does not normalize unicode when byte semantics requested" do
1085
881
  uri = subject.expand({ "query" => "Cafe\u0301" }, nil, false).to_str
1086
882
  expect(uri).to eq("http://example.com/search/Cafe%CC%81/")
@@ -20,6 +20,7 @@ require "spec_helper"
20
20
  require "addressable/uri"
21
21
  require "uri"
22
22
  require "ipaddr"
23
+ require "yaml"
23
24
 
24
25
  if !"".respond_to?("force_encoding")
25
26
  class String
@@ -3021,6 +3022,20 @@ describe Addressable::URI, "when parsed from " +
3021
3022
  end
3022
3023
  end
3023
3024
 
3025
+ describe Addressable::URI, "when parsed with empty port" do
3026
+ subject(:uri) do
3027
+ Addressable::URI.parse("//example.com:")
3028
+ end
3029
+
3030
+ it "should not infer a port" do
3031
+ expect(uri.port).to be(nil)
3032
+ end
3033
+
3034
+ it "should have a site value of '//example.com'" do
3035
+ expect(uri.site).to eq("//example.com")
3036
+ end
3037
+ end
3038
+
3024
3039
  describe Addressable::URI, "when parsed from " +
3025
3040
  "'http://example.com/%2E/'" do
3026
3041
  before do
@@ -5939,6 +5954,26 @@ describe Addressable::URI, "when normalizing a path with an encoded slash" do
5939
5954
  end
5940
5955
  end
5941
5956
 
5957
+ describe Addressable::URI, "when normalizing a path with special unicode" do
5958
+ it "does not stop at or ignore null bytes" do
5959
+ expect(Addressable::URI.parse("/path%00segment/").normalize.path).to eq(
5960
+ "/path%00segment/"
5961
+ )
5962
+ end
5963
+
5964
+ it "does apply NFC unicode normalization" do
5965
+ expect(Addressable::URI.parse("/%E2%84%A6").normalize.path).to eq(
5966
+ "/%CE%A9"
5967
+ )
5968
+ end
5969
+
5970
+ it "does not apply NFKC unicode normalization" do
5971
+ expect(Addressable::URI.parse("/%C2%AF%C2%A0").normalize.path).to eq(
5972
+ "/%C2%AF%C2%A0"
5973
+ )
5974
+ end
5975
+ end
5976
+
5942
5977
  describe Addressable::URI, "when normalizing a partially encoded string" do
5943
5978
  it "should result in correct percent encoded sequence" do
5944
5979
  expect(Addressable::URI.normalize_component(
@@ -6734,6 +6769,37 @@ describe Addressable::URI, "when initializing a subclass of Addressable::URI" do
6734
6769
  end
6735
6770
  end
6736
6771
 
6772
+ describe Addressable::URI, "support serialization roundtrip" do
6773
+ before do
6774
+ @uri = Addressable::URI.new(
6775
+ :scheme => "http",
6776
+ :user => "user",
6777
+ :password => "password",
6778
+ :host => "example.com",
6779
+ :port => 80,
6780
+ :path => "/path",
6781
+ :query => "query=value",
6782
+ :fragment => "fragment"
6783
+ )
6784
+ end
6785
+
6786
+ it "is in a working state after being serialized with Marshal" do
6787
+ @uri = Addressable::URI.parse("http://example.com")
6788
+ cloned_uri = Marshal.load(Marshal.dump(@uri))
6789
+ expect(cloned_uri.normalized_scheme).to be == @uri.normalized_scheme
6790
+ end
6791
+
6792
+ it "is in a working state after being serialized with YAML" do
6793
+ @uri = Addressable::URI.parse("http://example.com")
6794
+ cloned_uri = if YAML.respond_to?(:unsafe_load)
6795
+ YAML.unsafe_load(YAML.dump(@uri))
6796
+ else
6797
+ YAML.load(YAML.dump(@uri))
6798
+ end
6799
+ expect(cloned_uri.normalized_scheme).to be == @uri.normalized_scheme
6800
+ end
6801
+ end
6802
+
6737
6803
  describe Addressable::URI, "when initialized in a non-main `Ractor`" do
6738
6804
  it "should have the same value as if used in the main `Ractor`" do
6739
6805
  pending("Ruby 3.0+ for `Ractor` support") unless defined?(Ractor)
@@ -6743,3 +6809,32 @@ describe Addressable::URI, "when initialized in a non-main `Ractor`" do
6743
6809
  ).to eq(main)
6744
6810
  end
6745
6811
  end
6812
+
6813
+ describe Addressable::URI, "when deferring validation" do
6814
+ subject(:deferred) { uri.instance_variable_get(:@validation_deferred) }
6815
+
6816
+ let(:uri) { Addressable::URI.parse("http://example.com") }
6817
+
6818
+ it "defers validation within the block" do
6819
+ uri.defer_validation do
6820
+ expect(deferred).to be true
6821
+ end
6822
+ end
6823
+
6824
+ it "always resets deferral afterward" do
6825
+ expect { uri.defer_validation { raise "boom" } }.to raise_error("boom")
6826
+ expect(deferred).to be false
6827
+ end
6828
+
6829
+ it "returns nil" do
6830
+ res = uri.defer_validation {}
6831
+ expect(res).to be nil
6832
+ end
6833
+ end
6834
+
6835
+ describe Addressable::URI, "YAML safe loading" do
6836
+ it "doesn't serialize anonymous objects" do
6837
+ url = Addressable::URI.parse("http://example.com/")
6838
+ expect(YAML.dump(url)).to_not include("!ruby/object {}")
6839
+ end
6840
+ end
data/tasks/gem.rake CHANGED
@@ -31,7 +31,7 @@ namespace :gem do
31
31
  s.homepage = "https://github.com/sporkmonger/addressable"
32
32
  s.license = "Apache-2.0"
33
33
  s.metadata = {
34
- "changelog_uri" => "https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md"
34
+ "changelog_uri" => "https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md#v#{PKG_VERSION}"
35
35
  }
36
36
  end
37
37
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: addressable
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.8.1
4
+ version: 2.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Aman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-19 00:00:00.000000000 Z
11
+ date: 2023-12-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: public_suffix
@@ -65,6 +65,7 @@ files:
65
65
  - LICENSE.txt
66
66
  - README.md
67
67
  - Rakefile
68
+ - addressable.gemspec
68
69
  - data/unicode.data
69
70
  - lib/addressable.rb
70
71
  - lib/addressable/idna.rb
@@ -90,7 +91,7 @@ homepage: https://github.com/sporkmonger/addressable
90
91
  licenses:
91
92
  - Apache-2.0
92
93
  metadata:
93
- changelog_uri: https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md
94
+ changelog_uri: https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md#v2.8.6
94
95
  post_install_message:
95
96
  rdoc_options:
96
97
  - "--main"
@@ -108,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
108
109
  - !ruby/object:Gem::Version
109
110
  version: '0'
110
111
  requirements: []
111
- rubygems_version: 3.3.7
112
+ rubygems_version: 3.4.22
112
113
  signing_key:
113
114
  specification_version: 4
114
115
  summary: URI Implementation