@@ -24,6 +24,8 @@ pub const Headers = Http.Headers;
2424const Notification = @import ("../notification.zig" ).Notification ;
2525const storage = @import ("../browser/storage/storage.zig" );
2626
27+ const urlStitch = @import ("../url.zig" ).URL .stitch ;
28+
2729const c = Http .c ;
2830
2931const Allocator = std .mem .Allocator ;
@@ -321,8 +323,6 @@ fn makeRequest(self: *Client, handle: *Handle, transfer: *Transfer) !void {
321323 try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_HTTPHEADER , header_list .headers ));
322324
323325 // Add cookies.
324- // Clear cookies from Curl's engine.
325- try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIELIST , "ALL" ));
326326 if (header_list .cookies ) | cookies | {
327327 try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIE , cookies ));
328328 }
@@ -595,6 +595,42 @@ pub const Transfer = struct {
595595 self .deinit ();
596596 }
597597
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+
598634 fn headerCallback (buffer : [* ]const u8 , header_count : usize , buf_len : usize , data : * anyopaque ) callconv (.c ) usize {
599635 // libcurl should only ever emit 1 header at a time
600636 std .debug .assert (header_count == 1 );
@@ -611,18 +647,16 @@ pub const Transfer = struct {
611647
612648 if (transfer .response_header == null ) {
613649 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+ };
626660 return buf_len ;
627661 }
628662
0 commit comments