Reputation: 1061
I dont know if it's possible as the std lib does not state anything about the current address being used:
http://golang.org/pkg/net/http/
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
What I'm trying to do is set the source address for that http request, why? because I don't want to use my primary ip address for that kind of stuff...
Upvotes: 12
Views: 9831
Reputation: 71
Setting up a custom dialer with the specify IP works sometimes, but it is weird since sometimes it failed to work, while curl
works normally.
After checking the source code of curl
, I figured out why curl
is able to specify what network interface to be used: SO_BINDTODEVICE
. Unfortunately this is a Linux thing.
So compared to JimB's answer, my method has:
curl
, which is irrelevant from routing tablesdialer := &net.Dialer{
Control: func(network, address string, conn syscall.RawConn) error {
var operr error
if err := conn.Control(func(fd uintptr) {
operr = unix.BindToDevice(int(fd), forceNetworkInterface)
}); err != nil {
return err
}
return operr
},
}
client = http.Client{
Transport = &http.Transport{
DialContext: dialer.DialContext,
},
}
In addition, curl
performs SO_BINDTODEVICE
which behaves like the above code. And for non-Linux platforms, or when SO_BINDTODEVICE
fails, curl
sets the local IP address just as JimB's answer does. So you can first try my code and then use JimB's answer as a fallback.
See the source code of curl for details.
Upvotes: 0
Reputation: 109357
You can set a custom Dialer in the Client's Transport.
// Create a transport like http.DefaultTransport, but with a specified localAddr
transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
LocalAddr: localAddr,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
client := &http.Client{
Transport: transport,
}
Upvotes: 27