使用 Go 的 default HTTP client ,我无法直接确定处理请求的服务器的 IP 地址。例如,当请求 example.com
时,example.com
在请求时解析到的 IP 地址是什么?
import "net/http"
resp, err := http.Get("http://example.com/")
resp
对象包含 resp.RemoteAddr
属性,但如下所述,在客户端操作期间不会使用它。
// 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
有没有一种简单的方法可以做到这一点?我最初的想法是:
- 启动对远程域的 DNS 查找
- 使用返回的 A/AAAA 记录创建新的
http
传输 - 提出要求
- 在响应对象上设置
RemoteAddr
属性
有没有更好的办法?
已更新 - 使用@flimzy 的建议。此方法将远程 IP:PORT 存储到 request.RemoteAddr
属性中。我还添加了对多个重定向的支持,以便每个后续请求都填充其 RemoteAddr
。
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)
最佳答案
据我所知,使用标准库实现此目的的唯一方法是使用自定义 http.Transport记录远程 IP 地址,例如在 DialContext
函数中。
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")
将连接 IP 绑定(bind)到响应留给读者作为练习。
关于http - 如何捕获提供 HTTP 响应的服务器的 IP 地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49384786/