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) {
conn, err := net.Dial(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.
you also can build a request with trace:
request = request.WithContext(httptrace.WithClientTrace(request.Context(), &httptrace.ClientTrace{
GotConn: func(connInfo httptrace.GotConnInfo) {
fmt.Printf("target ip:%+v\n", connInfo.Conn.RemoteAddr().String())
},
}))
response, _:= client.Do(request)
httptrace form https://golang.org/pkg/net/http/httptrace/
req, err := http.NewRequest(method, url, strings.NewReader(body))
trace := &httptrace.ClientTrace{
GotConn: func(connInfo httptrace.GotConnInfo) {
fmt.Printf("Got Conn: %+v\n", connInfo)
},
DNSDone: func(dnsInfo httptrace.DNSDoneInfo) {
fmt.Printf("DNS Info: %+v\n", dnsInfo)
},
}
req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.