Skip to content
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c84cb6c
Consolidate client test files
gaby Oct 2, 2025
f92c34d
Handle nested load-balanced transports
gaby Oct 2, 2025
813b919
Handle nested LBClient traversal and adjust TLS helpers
gaby Oct 2, 2025
2117d43
Address lint feedback for transport helpers
gaby Oct 2, 2025
ac77149
Refine redirect handling and validation
gaby Oct 3, 2025
ba70ab7
Align redirect defaults with fasthttp
gaby Oct 3, 2025
38b741e
Refine redirect limit handling
gaby Oct 3, 2025
595eb4e
Refine redirect limit handling
gaby Oct 3, 2025
81c5bf1
Refine redirect guardrails
gaby Oct 3, 2025
e2333b8
Document redirect helpers and tighten validation
gaby Oct 3, 2025
338ba5a
Document redirect helpers and tighten URL validation
gaby Oct 3, 2025
b8bc157
Handle 303 redirect downgrades
gaby Oct 4, 2025
d506599
Use require.Empty in redirect tests
gaby Oct 4, 2025
edbde8c
Refine redirect cleanup and reuse traversal helper
gaby Oct 4, 2025
28e9d85
Reset clients to default transport
gaby Oct 4, 2025
a485dd8
Format transport test helpers
gaby Oct 6, 2025
e64d0e1
Make LB transport stateless for dial/TLS
gaby Oct 6, 2025
9755216
Clone LB TLS configs and drop unused dial helper
gaby Oct 7, 2025
821aad7
Refine TLS transport tests
gaby Oct 9, 2025
a75c746
Clone TLS configs in standard transports
gaby Oct 9, 2025
8854e3f
Return TLS config pointers from transports
gaby Oct 10, 2025
1c30776
Simplify LB transport TLS accessor
gaby Oct 10, 2025
73f97d2
Clarify required pre-submit checks
gaby Oct 10, 2025
e407c36
Guard SetProxyURL with client lock
gaby Oct 10, 2025
d1ce554
Guard TLS configuration updates with mutex
gaby Oct 11, 2025
2a2d012
Document client transports and reset behavior
gaby Oct 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 98 additions & 13 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ var ErrFailedToAppendCert = errors.New("failed to append certificate")
// The Fiber client also provides an option to override or merge most of the
// client settings at the request level.
type Client struct {
logger log.CommonLogger
fasthttp *fasthttp.Client
logger log.CommonLogger
transport httpClientTransport

header *Header
params *QueryParam
Expand Down Expand Up @@ -61,6 +61,72 @@ type Client struct {
disablePathNormalizing bool
}

// Do executes the request using the underlying fasthttp transport.
//
// It mirrors [fasthttp.Client.Do], [fasthttp.HostClient.Do], or
// [fasthttp.LBClient.Do] depending on how the Fiber client was constructed.
func (c *Client) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
return c.transport.Do(req, resp)
}

// DoTimeout executes the request and waits for a response up to the provided timeout.
// It mirrors the behavior of the respective fasthttp client's DoTimeout implementation.
func (c *Client) DoTimeout(req *fasthttp.Request, resp *fasthttp.Response, timeout time.Duration) error {
return c.transport.DoTimeout(req, resp, timeout)
}

// DoDeadline executes the request and waits for a response until the provided deadline.
// It mirrors the behavior of the respective fasthttp client's DoDeadline implementation.
func (c *Client) DoDeadline(req *fasthttp.Request, resp *fasthttp.Response, deadline time.Time) error {
return c.transport.DoDeadline(req, resp, deadline)
}

// DoRedirects executes the request following redirects up to maxRedirects.
func (c *Client) DoRedirects(req *fasthttp.Request, resp *fasthttp.Response, maxRedirects int) error {
return c.transport.DoRedirects(req, resp, maxRedirects)
}

// CloseIdleConnections closes idle connections on the underlying fasthttp transport when supported.
func (c *Client) CloseIdleConnections() {
c.transport.CloseIdleConnections()
}

func (c *Client) currentTLSConfig() *tls.Config {
return c.transport.TLSConfig()
}

func (c *Client) applyTLSConfig(config *tls.Config) {
c.transport.SetTLSConfig(config)
}

func (c *Client) applyDial(dial fasthttp.DialFunc) {
c.transport.SetDial(dial)
}

// FasthttpClient returns the underlying fasthttp.Client if the client was created with one.
Comment thread
gaby marked this conversation as resolved.
Outdated
func (c *Client) FasthttpClient() *fasthttp.Client {
if client, ok := c.transport.(*standardClientTransport); ok {
return client.client
}
return nil
}

// HostClient returns the underlying fasthttp.HostClient if the client was created with one.
func (c *Client) HostClient() *fasthttp.HostClient {
if client, ok := c.transport.(*hostClientTransport); ok {
return client.client
}
return nil
}

// LBClient returns the underlying fasthttp.LBClient if the client was created with one.
func (c *Client) LBClient() *fasthttp.LBClient {
if client, ok := c.transport.(*lbClientTransport); ok {
return client.client
}
return nil
}

// R creates a new Request associated with the client.
func (c *Client) R() *Request {
return AcquireRequest().SetClient(c)
Expand Down Expand Up @@ -163,18 +229,17 @@ func (c *Client) SetCBORUnmarshal(f utils.CBORUnmarshal) *Client {
// TLSConfig returns the client's TLS configuration.
// If none is set, it initializes a new one.
func (c *Client) TLSConfig() *tls.Config {
if c.fasthttp.TLSConfig == nil {
c.fasthttp.TLSConfig = &tls.Config{
MinVersion: tls.VersionTLS12,
}
if cfg := c.currentTLSConfig(); cfg != nil {
return cfg
}

return c.fasthttp.TLSConfig
cfg := &tls.Config{MinVersion: tls.VersionTLS12}
c.applyTLSConfig(cfg)
return cfg
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Comment thread
gaby marked this conversation as resolved.

// SetTLSConfig sets the TLS configuration for the client.
func (c *Client) SetTLSConfig(config *tls.Config) *Client {
c.fasthttp.TLSConfig = config
c.applyTLSConfig(config)
return c
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

Expand Down Expand Up @@ -232,7 +297,7 @@ func (c *Client) SetRootCertificateFromString(pem string) *Client {

// SetProxyURL sets the proxy URL for the client. This affects all subsequent requests.
func (c *Client) SetProxyURL(proxyURL string) error {
c.fasthttp.Dial = fasthttpproxy.FasthttpHTTPDialer(proxyURL)
c.applyDial(fasthttpproxy.FasthttpHTTPDialer(proxyURL))
return nil
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

Expand Down Expand Up @@ -514,7 +579,7 @@ func (c *Client) SetDial(dial fasthttp.DialFunc) *Client {
c.mu.Lock()
defer c.mu.Unlock()

c.fasthttp.Dial = dial
c.applyDial(dial)
return c
}

Expand All @@ -534,7 +599,7 @@ func (c *Client) Logger() log.CommonLogger {

// Reset resets the client to its default state, clearing most configurations.
Comment thread
gaby marked this conversation as resolved.
Outdated
func (c *Client) Reset() {
c.fasthttp = &fasthttp.Client{}
c.transport = newStandardClientTransport(&fasthttp.Client{})
c.baseURL = ""
c.timeout = 0
c.userAgent = ""
Expand Down Expand Up @@ -659,8 +724,28 @@ func NewWithClient(c *fasthttp.Client) *Client {
if c == nil {
panic("fasthttp.Client must not be nil")
}
return newClient(newStandardClientTransport(c))
}

// NewWithHostClient creates and returns a new Client object from an existing fasthttp.HostClient.
func NewWithHostClient(c *fasthttp.HostClient) *Client {
if c == nil {
panic("fasthttp.HostClient must not be nil")
}
return newClient(newHostClientTransport(c))
}

// NewWithLBClient creates and returns a new Client object from an existing fasthttp.LBClient.
func NewWithLBClient(c *fasthttp.LBClient) *Client {
if c == nil {
panic("fasthttp.LBClient must not be nil")
}
return newClient(newLBClientTransport(c))
}

func newClient(transport httpClientTransport) *Client {
return &Client{
fasthttp: c,
transport: transport,
header: &Header{
RequestHeader: &fasthttp.RequestHeader{},
},
Expand Down
Loading
Loading