Go语言从HTTP请求中获取服务端IP地址

如果一个域名可以解析出多个IP地址,那想在http请求过程中知道程序实际请求的是哪个IP地址该怎么办?带着这个疑问我找到了两个方法来解决这个问题。

一个是通过httptrace.ClientTrace获取服务IP;

另一个是通过http.Transport中的DialContext获取服务IP;

 

具体代码如下:

package main

import (
	"context"
	"crypto/tls"
	"fmt"
	"log"
	"net"
	"net/http"
	"net/http/httptrace"
)

// 方法一:通过httptrace.ClientTrace获取服务IP地址
func m1() {
	trace := &httptrace.ClientTrace{
		DNSStart: func(_ httptrace.DNSStartInfo) {},
		DNSDone:  func(_ httptrace.DNSDoneInfo) {},
		ConnectStart: func(net, addr string) {
			fmt.Printf("ConnectStart addr=%s\n", addr)
		},
		ConnectDone: func(net, addr string, err error) {
			fmt.Printf("ConnectDone addr=%s\n", addr)
		},
		GotConn:              func(_ httptrace.GotConnInfo) {},
		GotFirstResponseByte: func() {},
		TLSHandshakeStart:    func() {},
		TLSHandshakeDone:     func(_ tls.ConnectionState, _ error) {},
	}

	req, err := http.NewRequest(http.MethodGet, "http://www.baidu.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	req = req.WithContext(httptrace.WithClientTrace(context.Background(), trace))

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()
}

// 方法二:通过DialContext获取服务IP地址
func m2() {
	req, err := http.NewRequest(http.MethodGet, "http://www.baidu.com", nil)
	if err != nil {
		log.Fatal(err)
	}

	client := http.Client{
		Transport: &http.Transport{
			DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
				conn, err := net.Dial(network, addr)
				req.RemoteAddr = conn.RemoteAddr().String()
				return conn, err
			},
		},
	}

	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	fmt.Println("RemoteAddr:", req.RemoteAddr)
}

func main() {
	m1()
	m2()
}

  

posted @ 2020-01-14 10:11  xiaoxiongfei  阅读(5836)  评论(0)    收藏  举报