@@ -331,6 +331,11 @@ fn makeRequest(self: *Client, handle: *Handle, transfer: *Transfer) !void {
331331 try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_COOKIE , cookies ));
332332 }
333333
334+ // Proxy credentials
335+ if (req .credentials ) | creds | {
336+ try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_PROXYUSERPWD , creds .ptr ));
337+ }
338+
334339 try errorCheck (c .curl_easy_setopt (easy , c .CURLOPT_PRIVATE , transfer ));
335340 }
336341
@@ -383,7 +388,10 @@ fn perform(self: *Client, timeout_ms: c_int) !void {
383388 // If the transfer is waiting for auth challenge interception, don't
384389 // deinit the transfer and don't call the callbacks. All will be done
385390 // later during the interception's response.
391+ // we only reset the transfer to release the handle and be reused later.
386392 if (transfer ._auth_challenge ) {
393+ log .debug (.http , "transfer reset" , .{});
394+ transfer .reset ();
387395 continue ;
388396 }
389397
@@ -551,6 +559,7 @@ pub const Request = struct {
551559 body : ? []const u8 = null ,
552560 cookie_jar : * CookieJar ,
553561 resource_type : ResourceType ,
562+ credentials : ? [:0 ]const u8 = null ,
554563
555564 // arbitrary data that can be associated with this request
556565 ctx : * anyopaque = undefined ,
@@ -599,7 +608,7 @@ pub const Transfer = struct {
599608 // stateful variables used to parse responses headers.
600609 _resp_header_status : enum { empty , first , next , end } = .empty ,
601610
602- fn deinit (self : * Transfer ) void {
611+ pub fn deinit (self : * Transfer ) void {
603612 self .req .headers .deinit ();
604613 if (self ._handle ) | handle | {
605614 self .client .handles .release (handle );
@@ -608,6 +617,21 @@ pub const Transfer = struct {
608617 self .client .transfer_pool .destroy (self );
609618 }
610619
620+ fn reset (self : * Transfer ) void {
621+ if (self ._handle ) | handle | {
622+ self .client .handles .release (handle );
623+ self ._handle = null ;
624+ }
625+ self .bytes_received = 0 ;
626+ self .proxy_response_header = null ;
627+ self .response_header = null ;
628+ self ._notified_fail = false ;
629+ self ._redirecting = false ;
630+ self ._auth_challenge = false ;
631+ self ._use_proxy = false ;
632+ self ._resp_header_status = .empty ;
633+ }
634+
611635 pub fn format (self : * const Transfer , comptime _ : []const u8 , _ : std.fmt.FormatOptions , writer : anytype ) ! void {
612636 const req = self .req ;
613637 return writer .print ("{s} {s}" , .{ @tagName (req .method ), req .url });
@@ -623,6 +647,10 @@ pub const Transfer = struct {
623647 self ._request_header_list = c .curl_slist_append (self ._request_header_list , value );
624648 }
625649
650+ pub fn updateCredentials (self : * Transfer , userpwd : [:0 ]const u8 ) void {
651+ self .req .credentials = userpwd ;
652+ }
653+
626654 pub fn updateURL (self : * Transfer , url : [:0 ]const u8 ) ! void {
627655 // for cookies
628656 self .uri = try std .Uri .parse (url );
@@ -816,10 +844,12 @@ pub const Transfer = struct {
816844 // We won't call the req's callbacks now, but for the following request only.
817845 const status = transfer .response_header .? .status ;
818846 if (status == 401 or status == 407 ) {
847+ log .debug (.http , "FORBIDDEN" , .{});
819848 if (transfer .client .notification ) | notification | {
820849 var wait_for_interception = false ;
821850 notification .dispatch (.http_request_auth_required , &.{ .transfer = transfer , .wait_for_interception = & wait_for_interception });
822851 if (wait_for_interception ) {
852+ log .debug (.http , "WAIT FOR INTERCEPT" , .{});
823853 transfer ._auth_challenge = true ;
824854 // The user is send an invitation to intercept this request.
825855 return buf_len ;
0 commit comments