Force ipv4 for golang http client

Sometimes you want to prevent your http client from using ipv6/tcp6.
That’s how you do it.

dialer := &net.Dialer{
	Timeout:   dialTimeout,
	KeepAlive: keepAliveTimeout,
}

transport := &http.Transport{
	Proxy:             http.ProxyFromEnvironment,
	ForceAttemptHTTP2: false,
	DialContext: func(ctx context.Context, network string, addr string) (net.Conn, error) {
		ipv4, err := resolveIPv4(addr)
		if err != nil {
			return nil, err
		}

		return dialer.DialContext(ctx, network, ipv4)
	},
}

httpClient := &http.Client{
	Transport: transport,
	Timeout:   args.HTTPTimeout,
}

// resolveIPv4 resolves an address to IPv4 address.
func resolveIPv4(addr string) (string, error) {
	url := strings.Split(addr, ":")

	m := new(dns.Msg)
	m.SetQuestion(dns.Fqdn(url[0]), dns.TypeA)
	m.RecursionDesired = true

	config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
	c := new(dns.Client)
	r, _, err := c.Exchange(m, net.JoinHostPort(config.Servers[0], config.Port))
	if err != nil {
		return "", err
	}
	for _, ans := range r.Answer {
		if a, ok := ans.(*dns.A); ok {
			url[0] = a.A.String()
		}
	}

	return strings.Join(url, ":"), nil
}

LEAVE A COMMENT