Using Go's default HTTP client, I am unable to directly determine the IP address of the server that processed the request. For instance, when requesting example.com
, what is the IP address that example.com
resolved to at the time of the request?
import "net/http"
resp, err := http.Get("http://example.com/")
The resp
object contains the resp.RemoteAddr
property, but as detailed below it is not utilized during client operations.
// RemoteAddr allows HTTP servers and other software to record
// the network address that sent the request, usually for
// logging. This field is not filled in by ReadRequest and
// has no defined format. The HTTP server in this package
// sets RemoteAddr to an "IP:port" address before invoking a
// handler.
// This field is ignored by the HTTP client.
RemoteAddr string
Is there a straightforward way to accomplish this? My initial thought would be to:
http
transport using returned A/AAAA recordsRemoteAddr
property on the response objectIs there a better way?
UPDATED - to use @flimzy's suggestion. This method stores the remote IP:PORT into the request.RemoteAddr
property. I've also added support for multiple redirects so that each subsequent request has its RemoteAddr
populated.
request, _ := http.NewRequest("GET", "http://www.google.com", nil)
client := &http.Client{
Transport:&http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := net.Dial(network, addr)
request.RemoteAddr = conn.RemoteAddr().String()
return conn, err
},
},
CheckRedirect: func(req *http.Request, via []*http.Request) error {
request = req
return nil
},
}
resp, _ := client.Do(request)
As far as I can tell, the only way to accomplish this with the standard library is with a custom http.Transport that records the remote IP address, for example in the DialContext
function.
client := &http.Client{
Transport: &http.Transport{
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
var d net.Dialer
conn, err := d.DialContext(ctx, network, addr)
fmt.Printf("Remote IP: %s\n", conn.RemoteAddr())
return conn, err
},
},
}
resp, _ := client.Get("http://www.google.com")
Tying the connection IP to the response is left as an exercise for the reader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With