@@ -24,6 +24,8 @@ pub const Headers = Http.Headers;
24
24
const Notification = @import ("../notification.zig" ).Notification ;
25
25
const storage = @import ("../browser/storage/storage.zig" );
26
26
27
+ const urlStitch = @import ("../url.zig" ).URL .stitch ;
28
+
27
29
const c = Http .c ;
28
30
29
31
const Allocator = std .mem .Allocator ;
@@ -321,8 +323,6 @@ fn makeRequest(self: *Client, handle: *Handle, transfer: *Transfer) !void {
321
323
try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_HTTPHEADER , header_list .headers ));
322
324
323
325
// Add cookies.
324
- // Clear cookies from Curl's engine.
325
- try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIELIST , "ALL" ));
326
326
if (header_list .cookies ) | cookies | {
327
327
try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIE , cookies ));
328
328
}
@@ -595,6 +595,42 @@ pub const Transfer = struct {
595
595
self .deinit ();
596
596
}
597
597
598
+ // redirectionCookies manages cookies during redirections handled by Curl.
599
+ // It sets the cookies from the current response to the cookie jar.
600
+ // It also immediately sets cookies for the following request.
601
+ fn redirectionCookies (arena : std.mem.Allocator , easy : * c.CURL , cookie_jar : * storage.CookieJar , origin : * const std.Uri ) ! void {
602
+ // retrieve cookies from the redirect's response.
603
+ var i : usize = 0 ;
604
+ while (true ) {
605
+ const ct = getResponseHeader (easy , "set-cookie" , i );
606
+ if (ct == null ) break ;
607
+ try cookie_jar .populateFromResponse (origin , ct .? .value );
608
+ i += 1 ;
609
+ if (i >= ct .? .amount ) break ;
610
+ }
611
+
612
+ // set cookies for the following redirection's request.
613
+ const hlocation = getResponseHeader (easy , "location" , 0 );
614
+ if (hlocation == null ) {
615
+ return error .LocationNotFound ;
616
+ }
617
+
618
+ var baseurl : [* c ]u8 = undefined ;
619
+ try errorCheck (c .curl_easy_getinfo (easy , c .CURLINFO_EFFECTIVE_URL , & baseurl ));
620
+
621
+ const url = try urlStitch (arena , hlocation .? .value , std .mem .span (baseurl ), .{});
622
+ const uri = try std .Uri .parse (url );
623
+
624
+ var cookies : std .ArrayListUnmanaged (u8 ) = .{};
625
+ try cookie_jar .forRequest (& uri , cookies .writer (arena ), .{
626
+ .is_http = true ,
627
+ .is_navigation = true ,
628
+ .origin_uri = origin ,
629
+ });
630
+ try cookies .append (arena , 0 ); //null terminate
631
+ try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIE , @as ([* c ]const u8 , @ptrCast (cookies .items .ptr ))));
632
+ }
633
+
598
634
fn headerCallback (buffer : [* ]const u8 , header_count : usize , buf_len : usize , data : * anyopaque ) callconv (.c ) usize {
599
635
// libcurl should only ever emit 1 header at a time
600
636
std .debug .assert (header_count == 1 );
@@ -611,18 +647,16 @@ pub const Transfer = struct {
611
647
612
648
if (transfer .response_header == null ) {
613
649
if (transfer ._redirecting and buf_len == 2 ) {
614
- // retrieve cookies from the redirect's response.
615
- var i : usize = 0 ;
616
- while (true ) {
617
- const ct = getResponseHeader (easy , "set-cookie" , i );
618
- if (ct == null ) break ;
619
- transfer .req .cookie_jar .populateFromResponse (& transfer .uri , ct .? .value ) catch | err | {
620
- log .err (.http , "set cookie" , .{ .err = err , .req = transfer });
621
- };
622
- i += 1 ;
623
- if (i >= ct .? .amount ) break ;
624
- }
625
-
650
+ // parse and set cookies for the redirection.
651
+ redirectionCookies (
652
+ transfer .client .arena .allocator (),
653
+ easy ,
654
+ transfer .req .cookie_jar ,
655
+ & transfer .uri ,
656
+ ) catch | err | {
657
+ log .debug (.http , "redirection cookies" , .{ .err = err });
658
+ return 0 ;
659
+ };
626
660
return buf_len ;
627
661
}
628
662
0 commit comments