@@ -17,11 +17,13 @@ package config
1717
1818import (
1919 "bytes"
20+ "context"
2021 "crypto/sha256"
2122 "crypto/tls"
2223 "crypto/x509"
2324 "fmt"
2425 "io/ioutil"
26+ "net"
2527 "net/http"
2628 "net/url"
2729 "strings"
@@ -100,6 +102,40 @@ func (u URL) MarshalYAML() (interface{}, error) {
100102 return nil , nil
101103}
102104
105+ // TCPAddr is a custom TCP address type that allows validation at configuration load time.
106+ type TCPAddr struct {
107+ * net.TCPAddr
108+ }
109+
110+ // UnmarshalYAML implements the yaml.Unmarshaler interface for TCP addresses.
111+ func (a TCPAddr ) UnmarshalYAML (unmarshal func (interface {}) error ) error {
112+ var s string
113+ if err := unmarshal (& s ); err != nil {
114+ return err
115+ }
116+
117+ if len (s ) == 0 {
118+ a .TCPAddr = nil
119+ }
120+
121+ ip := net .ParseIP (s )
122+ if ip == nil {
123+ return fmt .Errorf ("error parsing ip %q" , s )
124+ }
125+
126+ a .TCPAddr = & net.TCPAddr {IP : ip }
127+
128+ return nil
129+ }
130+
131+ // MarshalYAML implements the yaml.Marshaler interface for TCP addresses.
132+ func (a TCPAddr ) MarshalYAML () (interface {}, error ) {
133+ if a .TCPAddr != nil {
134+ return a .TCPAddr .String (), nil
135+ }
136+ return nil , nil
137+ }
138+
103139// HTTPClientConfig configures an HTTP client.
104140type HTTPClientConfig struct {
105141 // The HTTP basic authentication credentials for the targets.
@@ -120,6 +156,8 @@ type HTTPClientConfig struct {
120156 // The omitempty flag is not set, because it would be hidden from the
121157 // marshalled configuration when set to false.
122158 FollowRedirects bool `yaml:"follow_redirects"`
159+ // SourceAddress specifies a source address to use for outgoing connections.
160+ SourceAddress * TCPAddr `yaml:"source_address,omitempty"`
123161}
124162
125163// SetDirectory joins any relative file paths with dir.
@@ -236,6 +274,13 @@ func NewRoundTripperFromConfig(cfg HTTPClientConfig, name string, disableKeepAli
236274 DialContext : conntrack .NewDialContextFunc (
237275 conntrack .DialWithTracing (),
238276 conntrack .DialWithName (name ),
277+ conntrack .DialWithDialContextFunc (func (ctx context.Context , network string , address string ) (net.Conn , error ) {
278+ dialer := & net.Dialer {}
279+ if cfg .SourceAddress != nil {
280+ dialer .LocalAddr = cfg .SourceAddress .TCPAddr
281+ }
282+ return dialer .DialContext (ctx , network , address )
283+ }),
239284 ),
240285 }
241286 if enableHTTP2 {
0 commit comments