Skip to content

Commit a167c6f

Browse files
authored
🔥 feat: Add support for HostClient and LBClient (#3774)
1 parent 697f199 commit a167c6f

File tree

9 files changed

+1418
-27
lines changed

9 files changed

+1418
-27
lines changed

AGENTS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ These targets can be invoked via `make <target>` as needed during development an
4747

4848
## Programmatic checks
4949

50-
Before submitting generated changes for a pull request, run:
50+
Before presenting final changes or submitting a pull request, run each of the
51+
following commands and ensure they succeed. Include the command outputs in your
52+
final response to confirm they were executed:
5153

5254
```bash
5355
make audit

client/client.go

Lines changed: 119 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
// Package client exposes Fiber's HTTP client built on top of fasthttp.
2+
//
3+
// It allows constructing new clients or wrapping existing fasthttp transports
4+
// so applications can share pools, dialers, and TLS settings between Fiber and
5+
// lower-level fasthttp integrations.
16
package client
27

38
import (
@@ -24,14 +29,14 @@ import (
2429

2530
var ErrFailedToAppendCert = errors.New("failed to append certificate")
2631

27-
// Client is used to create a Fiber client with client-level settings that
28-
// apply to all requests made by the client.
32+
// Client provides Fiber's high-level HTTP API while delegating transport work
33+
// to fasthttp.Client, fasthttp.HostClient, or fasthttp.LBClient implementations.
2934
//
30-
// The Fiber client also provides an option to override or merge most of the
31-
// client settings at the request level.
35+
// Settings configured on the client are shared across every request and may be
36+
// overridden per request when needed.
3237
type Client struct {
33-
logger log.CommonLogger
34-
fasthttp *fasthttp.Client
38+
logger log.CommonLogger
39+
transport httpClientTransport
3540

3641
header *Header
3742
params *QueryParam
@@ -61,6 +66,72 @@ type Client struct {
6166
disablePathNormalizing bool
6267
}
6368

69+
// Do executes the request using the underlying fasthttp transport.
70+
//
71+
// It mirrors [fasthttp.Client.Do], [fasthttp.HostClient.Do], or
72+
// [fasthttp.LBClient.Do] depending on how the Fiber client was constructed.
73+
func (c *Client) Do(req *fasthttp.Request, resp *fasthttp.Response) error {
74+
return c.transport.Do(req, resp)
75+
}
76+
77+
// DoTimeout executes the request and waits for a response up to the provided timeout.
78+
// It mirrors the behavior of the respective fasthttp client's DoTimeout implementation.
79+
func (c *Client) DoTimeout(req *fasthttp.Request, resp *fasthttp.Response, timeout time.Duration) error {
80+
return c.transport.DoTimeout(req, resp, timeout)
81+
}
82+
83+
// DoDeadline executes the request and waits for a response until the provided deadline.
84+
// It mirrors the behavior of the respective fasthttp client's DoDeadline implementation.
85+
func (c *Client) DoDeadline(req *fasthttp.Request, resp *fasthttp.Response, deadline time.Time) error {
86+
return c.transport.DoDeadline(req, resp, deadline)
87+
}
88+
89+
// DoRedirects executes the request following redirects up to maxRedirects.
90+
func (c *Client) DoRedirects(req *fasthttp.Request, resp *fasthttp.Response, maxRedirects int) error {
91+
return c.transport.DoRedirects(req, resp, maxRedirects)
92+
}
93+
94+
// CloseIdleConnections closes idle connections on the underlying fasthttp transport when supported.
95+
func (c *Client) CloseIdleConnections() {
96+
c.transport.CloseIdleConnections()
97+
}
98+
99+
func (c *Client) currentTLSConfig() *tls.Config {
100+
return c.transport.TLSConfig()
101+
}
102+
103+
func (c *Client) applyTLSConfig(config *tls.Config) {
104+
c.transport.SetTLSConfig(config)
105+
}
106+
107+
func (c *Client) applyDial(dial fasthttp.DialFunc) {
108+
c.transport.SetDial(dial)
109+
}
110+
111+
// FasthttpClient returns the underlying *fasthttp.Client if the client was created with one.
112+
func (c *Client) FasthttpClient() *fasthttp.Client {
113+
if client, ok := c.transport.(*standardClientTransport); ok {
114+
return client.client
115+
}
116+
return nil
117+
}
118+
119+
// HostClient returns the underlying fasthttp.HostClient if the client was created with one.
120+
func (c *Client) HostClient() *fasthttp.HostClient {
121+
if client, ok := c.transport.(*hostClientTransport); ok {
122+
return client.client
123+
}
124+
return nil
125+
}
126+
127+
// LBClient returns the underlying fasthttp.LBClient if the client was created with one.
128+
func (c *Client) LBClient() *fasthttp.LBClient {
129+
if client, ok := c.transport.(*lbClientTransport); ok {
130+
return client.client
131+
}
132+
return nil
133+
}
134+
64135
// R creates a new Request associated with the client.
65136
func (c *Client) R() *Request {
66137
return AcquireRequest().SetClient(c)
@@ -163,18 +234,23 @@ func (c *Client) SetCBORUnmarshal(f utils.CBORUnmarshal) *Client {
163234
// TLSConfig returns the client's TLS configuration.
164235
// If none is set, it initializes a new one.
165236
func (c *Client) TLSConfig() *tls.Config {
166-
if c.fasthttp.TLSConfig == nil {
167-
c.fasthttp.TLSConfig = &tls.Config{
168-
MinVersion: tls.VersionTLS12,
169-
}
170-
}
237+
c.mu.Lock()
238+
defer c.mu.Unlock()
171239

172-
return c.fasthttp.TLSConfig
240+
if cfg := c.currentTLSConfig(); cfg != nil {
241+
return cfg
242+
}
243+
cfg := &tls.Config{MinVersion: tls.VersionTLS12}
244+
c.applyTLSConfig(cfg)
245+
return cfg
173246
}
174247

175248
// SetTLSConfig sets the TLS configuration for the client.
176249
func (c *Client) SetTLSConfig(config *tls.Config) *Client {
177-
c.fasthttp.TLSConfig = config
250+
c.mu.Lock()
251+
defer c.mu.Unlock()
252+
253+
c.applyTLSConfig(config)
178254
return c
179255
}
180256

@@ -232,7 +308,10 @@ func (c *Client) SetRootCertificateFromString(pem string) *Client {
232308

233309
// SetProxyURL sets the proxy URL for the client. This affects all subsequent requests.
234310
func (c *Client) SetProxyURL(proxyURL string) error {
235-
c.fasthttp.Dial = fasthttpproxy.FasthttpHTTPDialer(proxyURL)
311+
c.mu.Lock()
312+
defer c.mu.Unlock()
313+
314+
c.applyDial(fasthttpproxy.FasthttpHTTPDialer(proxyURL))
236315
return nil
237316
}
238317

@@ -514,7 +593,7 @@ func (c *Client) SetDial(dial fasthttp.DialFunc) *Client {
514593
c.mu.Lock()
515594
defer c.mu.Unlock()
516595

517-
c.fasthttp.Dial = dial
596+
c.applyDial(dial)
518597
return c
519598
}
520599

@@ -532,9 +611,11 @@ func (c *Client) Logger() log.CommonLogger {
532611
return c.logger
533612
}
534613

535-
// Reset resets the client to its default state, clearing most configurations.
614+
// Reset resets the client to its default state, clearing most configurations
615+
// and replacing the underlying transport with a new fasthttp.Client so future
616+
// requests resume with Fiber's standard transport settings.
536617
func (c *Client) Reset() {
537-
c.fasthttp = &fasthttp.Client{}
618+
c.transport = newStandardClientTransport(&fasthttp.Client{})
538619
c.baseURL = ""
539620
c.timeout = 0
540621
c.userAgent = ""
@@ -659,8 +740,28 @@ func NewWithClient(c *fasthttp.Client) *Client {
659740
if c == nil {
660741
panic("fasthttp.Client must not be nil")
661742
}
743+
return newClient(newStandardClientTransport(c))
744+
}
745+
746+
// NewWithHostClient creates and returns a new Client object from an existing fasthttp.HostClient.
747+
func NewWithHostClient(c *fasthttp.HostClient) *Client {
748+
if c == nil {
749+
panic("fasthttp.HostClient must not be nil")
750+
}
751+
return newClient(newHostClientTransport(c))
752+
}
753+
754+
// NewWithLBClient creates and returns a new Client object from an existing fasthttp.LBClient.
755+
func NewWithLBClient(c *fasthttp.LBClient) *Client {
756+
if c == nil {
757+
panic("fasthttp.LBClient must not be nil")
758+
}
759+
return newClient(newLBClientTransport(c))
760+
}
761+
762+
func newClient(transport httpClientTransport) *Client {
662763
return &Client{
663-
fasthttp: c,
764+
transport: transport,
664765
header: &Header{
665766
RequestHeader: &fasthttp.RequestHeader{},
666767
},

0 commit comments

Comments
 (0)