如何找到Go http.Response的远程IP地址?

时间:2017-02-17 19:07:37

标签: http go

http.Request结构包括请求发送方的远程IP和端口:

    // 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**

http.Response对象没有这样的字段。

我想知道响应我发送的请求的IP地址,即使我将其发送到DNS地址。

我认为net.LookupHost()可能会有所帮助,但1)它可以为单个主机名返回多个IP,2)它会忽略hosts文件,除非cgo可用,这不是我的情况。

是否可以检索http.Response的远程IP地址?

1 个答案:

答案 0 :(得分:4)

使用net/http/httptrace包并使用GotConnInfo挂钩捕获net.Conn及其对应的Conn.RemoteAddr()

这将为您提供Transport实际拨打的地址,而不是DNSDoneInfo中已解决的地址:

package main

import (
    "log"
    "net/http"
    "net/http/httptrace"
)

func main() {
    req, err := http.NewRequest("GET", "https://example.com/", nil)
    if err != nil {
        log.Fatal(err)
    }

    trace := &httptrace.ClientTrace{
        GotConn: func(connInfo httptrace.GotConnInfo) {
            log.Printf("resolved to: %s", connInfo.Conn.RemoteAddr())
        },
    }

    req = req.WithContext(httptrace.WithClientTrace(req.Context(), trace))

    client := &http.Client{}
    _, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
}

输出:

~ go run ip.go
2017/02/18 19:38:11 resolved to: 104.16.xx.xxx:443