@@ -244,9 +244,6 @@ pub const Cookie = struct {
244244 }
245245 }
246246
247- var arena = ArenaAllocator .init (allocator );
248- errdefer arena .deinit ();
249-
250247 const cookie_name , const cookie_value , const rest = parseNameValue (str ) catch {
251248 return error .InvalidNameValue ;
252249 };
@@ -322,6 +319,12 @@ pub const Cookie = struct {
322319 }
323320 }
324321
322+ if (same_site == .none and secure == null ) {
323+ return error .InsecureSameSite ;
324+ }
325+
326+ var arena = ArenaAllocator .init (allocator );
327+ errdefer arena .deinit ();
325328 const aa = arena .allocator ();
326329 const owned_name = try aa .dupe (u8 , cookie_name );
327330 const owned_value = try aa .dupe (u8 , cookie_value );
@@ -505,7 +508,7 @@ test "Jar: forRequest" {
505508 try jar .add (try Cookie .parse (testing .allocator , test_uri , "path1=3;Path=/about" ), now );
506509 try jar .add (try Cookie .parse (testing .allocator , test_uri , "path2=4;Path=/docs/" ), now );
507510 try jar .add (try Cookie .parse (testing .allocator , test_uri , "secure=5;Secure" ), now );
508- try jar .add (try Cookie .parse (testing .allocator , test_uri , "sitenone=6;SameSite=None;Path=/x/" ), now );
511+ try jar .add (try Cookie .parse (testing .allocator , test_uri , "sitenone=6;SameSite=None;Path=/x/;Secure " ), now );
509512 try jar .add (try Cookie .parse (testing .allocator , test_uri , "sitelax=7;SameSite=Lax;Path=/x/" ), now );
510513 try jar .add (try Cookie .parse (testing .allocator , test_uri , "sitestrict=8;SameSite=Strict;Path=/x/" ), now );
511514 try jar .add (try Cookie .parse (testing .allocator , test_uri_2 , "domain1=9;domain=test.lightpanda.io" ), now );
@@ -518,55 +521,133 @@ test "Jar: forRequest" {
518521
519522 {
520523 // matching path without trailing /
521- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/about" ), true );
524+ var matches = try jar .forRequest (
525+ testing .allocator ,
526+ now ,
527+ test_uri ,
528+ try std .Uri .parse ("http://lightpanda.io/about" ),
529+ true ,
530+ );
522531 try expectCookies (&.{ "global1" , "global2" , "path1" }, & matches );
523532 }
524533
525534 {
526535 // incomplete prefix path
527- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/abou" ), true );
536+ var matches = try jar .forRequest (
537+ testing .allocator ,
538+ now ,
539+ test_uri ,
540+ try std .Uri .parse ("http://lightpanda.io/abou" ),
541+ true ,
542+ );
528543 try expectCookies (&.{ "global1" , "global2" }, & matches );
529544 }
530545
531546 {
532547 // path doesn't match
533- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/aboutus" ), true );
548+ var matches = try jar .forRequest (
549+ testing .allocator ,
550+ now ,
551+ test_uri ,
552+ try std .Uri .parse ("http://lightpanda.io/aboutus" ),
553+ true ,
554+ );
534555 try expectCookies (&.{ "global1" , "global2" }, & matches );
535556 }
536557
537558 {
538559 // path doesn't match cookie directory
539- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/docs" ), true );
560+ var matches = try jar .forRequest (
561+ testing .allocator ,
562+ now ,
563+ test_uri ,
564+ try std .Uri .parse ("http://lightpanda.io/docs" ),
565+ true ,
566+ );
540567 try expectCookies (&.{ "global1" , "global2" }, & matches );
541568 }
542569
543570 {
544571 // exact directory match
545- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/docs/" ), true );
572+ var matches = try jar .forRequest (
573+ testing .allocator ,
574+ now ,
575+ test_uri ,
576+ try std .Uri .parse ("http://lightpanda.io/docs/" ),
577+ true ,
578+ );
546579 try expectCookies (&.{ "global1" , "global2" , "path2" }, & matches );
547580 }
548581
549582 {
550583 // sub directory match
551- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://lightpanda.io/docs/more" ), true );
584+ var matches = try jar .forRequest (
585+ testing .allocator ,
586+ now ,
587+ test_uri ,
588+ try std .Uri .parse ("http://lightpanda.io/docs/more" ),
589+ true ,
590+ );
552591 try expectCookies (&.{ "global1" , "global2" , "path2" }, & matches );
553592 }
554593
555594 {
556595 // secure
557- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("https://lightpanda.io/" ), true );
596+ var matches = try jar .forRequest (
597+ testing .allocator ,
598+ now ,
599+ test_uri ,
600+ try std .Uri .parse ("https://lightpanda.io/" ),
601+ true ,
602+ );
558603 try expectCookies (&.{ "global1" , "global2" , "secure" }, & matches );
559604 }
560605
561606 {
562- // navigational cross domain
563- var matches = try jar .forRequest (testing .allocator , now , try std .Uri .parse ("http://example.com/" ), try std .Uri .parse ("http://lightpanda.io/x/" ), true );
564- try expectCookies (&.{ "global1" , "global2" , "sitenone" , "sitelax" }, & matches );
607+ // navigational cross domain, secure
608+ var matches = try jar .forRequest (
609+ testing .allocator ,
610+ now ,
611+ try std .Uri .parse ("https://example.com/" ),
612+ try std .Uri .parse ("https://lightpanda.io/x/" ),
613+ true ,
614+ );
615+ try expectCookies (&.{ "global1" , "global2" , "sitenone" , "sitelax" , "secure" }, & matches );
616+ }
617+
618+ {
619+ // navigational cross domain, insecure
620+ var matches = try jar .forRequest (
621+ testing .allocator ,
622+ now ,
623+ try std .Uri .parse ("http://example.com/" ),
624+ try std .Uri .parse ("http://lightpanda.io/x/" ),
625+ true ,
626+ );
627+ try expectCookies (&.{ "global1" , "global2" , "sitelax" }, & matches );
565628 }
566629
567630 {
568- // non-navigational cross domain
569- var matches = try jar .forRequest (testing .allocator , now , try std .Uri .parse ("http://example.com/" ), try std .Uri .parse ("http://lightpanda.io/x/" ), false );
631+ // non-navigational cross domain, insecure
632+ var matches = try jar .forRequest (
633+ testing .allocator ,
634+ now ,
635+ try std .Uri .parse ("http://example.com/" ),
636+ try std .Uri .parse ("http://lightpanda.io/x/" ),
637+ false ,
638+ );
639+ try expectCookies (&.{}, & matches );
640+ }
641+
642+ {
643+ // non-navigational cross domain, secure
644+ var matches = try jar .forRequest (
645+ testing .allocator ,
646+ now ,
647+ try std .Uri .parse ("https://example.com/" ),
648+ try std .Uri .parse ("https://lightpanda.io/x/" ),
649+ false ,
650+ );
570651 try expectCookies (&.{"sitenone" }, & matches );
571652 }
572653
@@ -579,24 +660,42 @@ test "Jar: forRequest" {
579660 try std .Uri .parse ("http://lightpanda.io/x/" ),
580661 false ,
581662 );
582- try expectCookies (&.{ "global1" , "global2" , "sitenone" , " sitelax" , "sitestrict" }, & matches );
663+ try expectCookies (&.{ "global1" , "global2" , "sitelax" , "sitestrict" }, & matches );
583664 }
584665
585666 {
586667 // exact domain match
587- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://test.lightpanda.io/" ), true );
668+ var matches = try jar .forRequest (
669+ testing .allocator ,
670+ now ,
671+ test_uri ,
672+ try std .Uri .parse ("http://test.lightpanda.io/" ),
673+ true ,
674+ );
588675 try expectCookies (&.{"domain1" }, & matches );
589676 }
590677
591678 {
592679 // domain suffix match
593- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://1.test.lightpanda.io/" ), true );
680+ var matches = try jar .forRequest (
681+ testing .allocator ,
682+ now ,
683+ test_uri ,
684+ try std .Uri .parse ("http://1.test.lightpanda.io/" ),
685+ true ,
686+ );
594687 try expectCookies (&.{"domain1" }, & matches );
595688 }
596689
597690 {
598691 // non-matching domain
599- var matches = try jar .forRequest (testing .allocator , now , test_uri , try std .Uri .parse ("http://other.lightpanda.io/" ), true );
692+ var matches = try jar .forRequest (
693+ testing .allocator ,
694+ now ,
695+ test_uri ,
696+ try std .Uri .parse ("http://other.lightpanda.io/" ),
697+ true ,
698+ );
600699 try expectCookies (&.{}, & matches );
601700 }
602701
@@ -677,7 +776,7 @@ test "Cookie: parse secure" {
677776 try expectAttribute (.{ .secure = true }, null , "b; seCUre=Off " );
678777}
679778
680- test "Cookie: parse httponly " {
779+ test "Cookie: parse HttpOnly " {
681780 try expectAttribute (.{ .http_only = false }, null , "b" );
682781 try expectAttribute (.{ .http_only = false }, null , "b;HttpOnly0" );
683782 try expectAttribute (.{ .http_only = false }, null , "b;H ttpOnly" );
@@ -689,24 +788,28 @@ test "Cookie: parse httponly" {
689788 try expectAttribute (.{ .http_only = true }, null , "b; HttpOnly=Off " );
690789}
691790
692- test "Cookie: parse strict " {
791+ test "Cookie: parse SameSite " {
693792 try expectAttribute (.{ .same_site = .lax }, null , "b;samesite" );
694793 try expectAttribute (.{ .same_site = .lax }, null , "b;samesite=lax" );
695794 try expectAttribute (.{ .same_site = .lax }, null , "b; SameSite=Lax " );
696795 try expectAttribute (.{ .same_site = .lax }, null , "b; SameSite=Other " );
697796 try expectAttribute (.{ .same_site = .lax }, null , "b; SameSite=Nope " );
698797
699- try expectAttribute (.{ .same_site = .none }, null , "b; samesite=none " );
700- try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=None " );
701- try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=None;" );
702- try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=None" );
798+ // SameSite=none is only valid when Secure is set. The whole cookie is
799+ // rejected otherwise
800+ try expectError (error .InsecureSameSite , null , "b;samesite=none" );
801+ try expectError (error .InsecureSameSite , null , "b;SameSite=None" );
802+ try expectAttribute (.{ .same_site = .none }, null , "b; samesite=none; secure " );
803+ try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=None ; SECURE" );
804+ try expectAttribute (.{ .same_site = .none }, null , "b;Secure; SameSite=None" );
805+ try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=None; Secure" );
703806
704807 try expectAttribute (.{ .same_site = .strict }, null , "b; samesite=Strict " );
705808 try expectAttribute (.{ .same_site = .strict }, null , "b; SameSite= STRICT " );
706809 try expectAttribute (.{ .same_site = .strict }, null , "b; SameSITE=strict;" );
707810 try expectAttribute (.{ .same_site = .strict }, null , "b; SameSite=Strict" );
708811
709- try expectAttribute (.{ .same_site = .none }, null , "b; SameSite=Strict ; SameSite=lax; SameSite=NONE " );
812+ try expectAttribute (.{ .same_site = .strict }, null , "b; SameSite=None ; SameSite=lax; SameSite=Strict " );
710813}
711814
712815test "Cookie: parse max-age" {
0 commit comments