addressable 2.8.1 → 2.8.7
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +81 -42
- data/Gemfile +1 -0
- data/Rakefile +11 -8
- data/addressable.gemspec +28 -0
- data/lib/addressable/idna/native.rb +8 -2
- data/lib/addressable/idna/pure.rb +10 -182
- data/lib/addressable/template.rb +10 -11
- data/lib/addressable/uri.rb +177 -135
- data/lib/addressable/version.rb +1 -1
- data/spec/addressable/idna_spec.rb +6 -5
- data/spec/addressable/template_spec.rb +60 -264
- data/spec/addressable/uri_spec.rb +95 -0
- data/tasks/gem.rake +4 -4
- metadata +10 -9
data/lib/addressable/version.rb
CHANGED
@@ -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
|
-
|
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" => '.',
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 =>
|
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" => "."
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
@@ -21,7 +21,7 @@ namespace :gem do
|
|
21
21
|
|
22
22
|
s.required_ruby_version = ">= 2.2"
|
23
23
|
|
24
|
-
s.add_runtime_dependency "public_suffix", ">= 2.0.2", "<
|
24
|
+
s.add_runtime_dependency "public_suffix", ">= 2.0.2", "< 7.0"
|
25
25
|
s.add_development_dependency "bundler", ">= 1.0", "< 3.0"
|
26
26
|
|
27
27
|
s.require_path = "lib"
|
@@ -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
|
|
@@ -56,7 +56,7 @@ namespace :gem do
|
|
56
56
|
|
57
57
|
desc "Install the gem"
|
58
58
|
task :install => ["clobber", "gem:package"] do
|
59
|
-
sh "
|
59
|
+
sh "gem install --local ./pkg/#{GEM_SPEC.full_name}.gem"
|
60
60
|
end
|
61
61
|
|
62
62
|
desc "Uninstall the gem"
|
@@ -65,7 +65,7 @@ namespace :gem do
|
|
65
65
|
if installed_list &&
|
66
66
|
(installed_list.collect { |s| s.version.to_s}.include?(PKG_VERSION))
|
67
67
|
sh(
|
68
|
-
"
|
68
|
+
"gem uninstall --version '#{PKG_VERSION}' " +
|
69
69
|
"--ignore-dependencies --executables #{PKG_NAME}"
|
70
70
|
)
|
71
71
|
end
|