@@ -10,6 +10,7 @@ import (
1010 "fmt"
1111 "io"
1212 "mime/multipart"
13+ "net"
1314 "net/http"
1415 "net/url"
1516 "os"
@@ -41,12 +42,13 @@ var (
4142)
4243
4344type Client struct {
44- proxy string // set to all requests
45- timeout time.Duration
46- crt * tls.Certificate
47- opts * requestOptions
48- httpVersion string // "1.0", "1.1", "2", "3"
49- insecure bool // allow insecure SSL
45+ proxy string // set to all requests
46+ timeout time.Duration
47+ connectTimeout time.Duration // connection timeout separate from request timeout
48+ crt * tls.Certificate
49+ opts * requestOptions
50+ httpVersion string // "1.0", "1.1", "2", "3"
51+ insecure bool // allow insecure SSL
5052 // Authentication fields
5153 authType string // "basic", "digest", "ntlm", "negotiate"
5254 username string
@@ -85,6 +87,11 @@ func (c *Client) SetTimeout(duration time.Duration) *Client {
8587 return c
8688}
8789
90+ func (c * Client ) SetConnectTimeout (duration time.Duration ) * Client {
91+ c .connectTimeout = duration
92+ return c
93+ }
94+
8895func (c * Client ) SetHTTPVersion (version string ) * Client {
8996 c .httpVersion = version
9097 return c
@@ -464,6 +471,28 @@ func (c *Client) callFastHTTP(url, method string, headers requestHeaders, body [
464471 client := & fasthttp.Client {
465472 ReadTimeout : c .timeout ,
466473 }
474+
475+ // Set connect timeout if specified
476+ if c .connectTimeout > 0 {
477+ client .WriteTimeout = c .connectTimeout
478+ client .ReadTimeout = c .timeout
479+ // Create a custom dialer with connect timeout
480+ if c .proxy != "" {
481+ // Use proxy dialer with connect timeout
482+ client .Dial = func (addr string ) (net.Conn , error ) {
483+ proxyDialer := fasthttpproxy .FasthttpHTTPDialer (c .proxy )
484+ return proxyDialer (addr )
485+ }
486+ } else {
487+ // Use direct dialer with connect timeout
488+ client .Dial = func (addr string ) (net.Conn , error ) {
489+ return net .DialTimeout ("tcp" , addr , c .connectTimeout )
490+ }
491+ }
492+ } else if c .proxy != "" {
493+ client .Dial = fasthttpproxy .FasthttpHTTPDialer (c .proxy )
494+ }
495+
467496 if c .crt != nil {
468497 client .TLSConfig = & tls.Config {
469498 InsecureSkipVerify : c .insecure ,
@@ -474,9 +503,6 @@ func (c *Client) callFastHTTP(url, method string, headers requestHeaders, body [
474503 InsecureSkipVerify : true ,
475504 }
476505 }
477- if c .proxy != "" {
478- client .Dial = fasthttpproxy .FasthttpHTTPDialer (c .proxy )
479- }
480506
481507 if err := client .Do (req , resp ); err != nil {
482508 return nil , err
@@ -490,13 +516,28 @@ func (c *Client) callFastHTTP(url, method string, headers requestHeaders, body [
490516 }
491517 resp .Header .VisitAll (func (key , value []byte ) {
492518 ret .Header .Set (string (key ), string (value ))
493- })
494- resp .Header .VisitAllCookie (func (key , value []byte ) {
495- ret .Cookie .Set (string (key ), string (value ))
519+ // Parse Set-Cookie headers manually
520+ if strings .ToLower (string (key )) == "set-cookie" {
521+ parseCookieFromSetCookie (string (value ), ret .Cookie )
522+ }
496523 })
497524 return ret , nil
498525}
499526
527+ // parseCookieFromSetCookie parses a Set-Cookie header value and extracts the cookie name and value
528+ func parseCookieFromSetCookie (setCookieValue string , cookies RequestCookies ) {
529+ // Simple parsing: extract name=value from "name=value; Path=/; ..."
530+ parts := strings .Split (setCookieValue , ";" )
531+ if len (parts ) > 0 {
532+ nameValue := strings .TrimSpace (parts [0 ])
533+ if idx := strings .Index (nameValue , "=" ); idx > 0 {
534+ name := strings .TrimSpace (nameValue [:idx ])
535+ value := strings .TrimSpace (nameValue [idx + 1 :])
536+ cookies .Set (name , value )
537+ }
538+ }
539+ }
540+
500541func (c * Client ) callHTTP2OrHTTP3 (url , method string , headers requestHeaders , body []byte ) (* Response , error ) {
501542 var client * http.Client
502543
@@ -523,6 +564,16 @@ func (c *Client) callHTTP2OrHTTP3(url, method string, headers requestHeaders, bo
523564 TLSClientConfig : tlsConfig ,
524565 }
525566
567+ // Set dial timeout if connectTimeout is specified
568+ if c .connectTimeout > 0 {
569+ transport .DialTLS = func (network , addr string , cfg * tls.Config ) (net.Conn , error ) {
570+ dialer := & net.Dialer {
571+ Timeout : c .connectTimeout ,
572+ }
573+ return tls .DialWithDialer (dialer , network , addr , cfg )
574+ }
575+ }
576+
526577 client = & http.Client {
527578 Transport : transport ,
528579 Timeout : c .timeout ,
0 commit comments