I'm using toxiproxy. I'm having this exact issue. Both of the curl
solutions mentioned in the issue work (solution a, solution b), but I can't use curl. I need to use the go standard net/http
library.
Is there any way to use net/http
in such a fashion that I can explicitly tell it what host the proxy is using so it can see that the certificate is valid?
I've tried setting Host
and Authority
headers on the net/http.Request, but that didn't work.
Details
Toxiproxy output:
proxy=[::]:22002 upstream=maps.googleapis.com:443
My code:
url := "https://localhost:22002/maps/api/geocode/json..."
req, err := http.NewRequest("GET", url, nil)
req.Host = "maps.googleapis.com"
req.Header.Set("Host", "maps.googleapis.com")
res, err := httpClient.Do(req)
Error:
x509: certificate is valid for *.googleapis.com, *.clients6.google.com, *.cloudendpointsapis.com, cloudendpointsapis.com, googleapis.com, not localhost
You need to set the http.Request.Host
field so that the http request has the correct header
req.Host = "maps.googleapis.com"
An you also need to set the hostname in the tls.Config.ServerName
field for SNI and host name verification.
If you've already configured a transport for your httpClient
, you can set it like so:
httpClient.Transport.(*http.Transport).TLSClientConfig = &tls.Config{
ServerName: "maps.googleapis.com",
}
Or for small programs you can override the default:
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
ServerName: "maps.googleapis.com",
}
Or create a custom transport for your program
var httpTransport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: &tls.Config{
ServerName: "maps.googleapis.com",
},
}
Just make sure you reuse the Transport, and don't create a new one for each request.