@@ -309,6 +309,9 @@ type HTTPClientConfig struct {
309
309
// The omitempty flag is not set, because it would be hidden from the
310
310
// marshalled configuration when set to false.
311
311
EnableHTTP2 bool `yaml:"enable_http2" json:"enable_http2"`
312
+ // Host optionally overrides the Host header to send.
313
+ // If empty, the host from the URL will be used.
314
+ Host string `yaml:"host,omitempty" json:"host,omitempty"`
312
315
// Proxy configuration.
313
316
ProxyConfig `yaml:",inline"`
314
317
}
@@ -427,6 +430,7 @@ type httpClientOptions struct {
427
430
http2Enabled bool
428
431
idleConnTimeout time.Duration
429
432
userAgent string
433
+ host string
430
434
}
431
435
432
436
// HTTPClientOption defines an option that can be applied to the HTTP client.
@@ -467,6 +471,13 @@ func WithUserAgent(ua string) HTTPClientOption {
467
471
}
468
472
}
469
473
474
+ // WithHost allows setting the host header.
475
+ func WithHost (host string ) HTTPClientOption {
476
+ return func (opts * httpClientOptions ) {
477
+ opts .host = host
478
+ }
479
+ }
480
+
470
481
// NewClient returns a http.Client using the specified http.RoundTripper.
471
482
func newClient (rt http.RoundTripper ) * http.Client {
472
483
return & http.Client {Transport : rt }
@@ -568,6 +579,10 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, optFuncs ...HT
568
579
rt = NewUserAgentRoundTripper (opts .userAgent , rt )
569
580
}
570
581
582
+ if opts .host != "" {
583
+ rt = NewHostRoundTripper (opts .host , rt )
584
+ }
585
+
571
586
// Return a new configured RoundTripper.
572
587
return rt , nil
573
588
}
@@ -1164,11 +1179,21 @@ type userAgentRoundTripper struct {
1164
1179
rt http.RoundTripper
1165
1180
}
1166
1181
1182
+ type hostRoundTripper struct {
1183
+ host string
1184
+ rt http.RoundTripper
1185
+ }
1186
+
1167
1187
// NewUserAgentRoundTripper adds the user agent every request header.
1168
1188
func NewUserAgentRoundTripper (userAgent string , rt http.RoundTripper ) http.RoundTripper {
1169
1189
return & userAgentRoundTripper {userAgent , rt }
1170
1190
}
1171
1191
1192
+ // NewHostRoundTripper sets the [http.Request.Host] of every request.
1193
+ func NewHostRoundTripper (host string , rt http.RoundTripper ) http.RoundTripper {
1194
+ return & hostRoundTripper {host , rt }
1195
+ }
1196
+
1172
1197
func (rt * userAgentRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
1173
1198
req = cloneRequest (req )
1174
1199
req .Header .Set ("User-Agent" , rt .userAgent )
@@ -1181,6 +1206,19 @@ func (rt *userAgentRoundTripper) CloseIdleConnections() {
1181
1206
}
1182
1207
}
1183
1208
1209
+ func (rt * hostRoundTripper ) RoundTrip (req * http.Request ) (* http.Response , error ) {
1210
+ req = cloneRequest (req )
1211
+ req .Host = rt .host
1212
+ req .Header .Set ("Host" , rt .host )
1213
+ return rt .rt .RoundTrip (req )
1214
+ }
1215
+
1216
+ func (rt * hostRoundTripper ) CloseIdleConnections () {
1217
+ if ci , ok := rt .rt .(closeIdler ); ok {
1218
+ ci .CloseIdleConnections ()
1219
+ }
1220
+ }
1221
+
1184
1222
func (c HTTPClientConfig ) String () string {
1185
1223
b , err := yaml .Marshal (c )
1186
1224
if err != nil {
0 commit comments