英文:
How can I test HTTPS endpoints in go?
问题
所以我正在尝试使用httptest.TLSServer
来模拟对https请求的响应,但是发出请求的http.Client
告诉我服务器提供了无效的http响应。我猜这是因为没有实际的SSL证书。有没有办法在模拟https请求的同时让客户端忽略tls呢?
相关的测试代码如下:
func TestFacebookLogin(t *testing.T) {
db := glob.db
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
resp := `
{
"id": "123",
"email": "blah",
"first_name": "Ben",
"last_name": "Botwin"
}
`
w.Write([]byte(resp))
}))
defer server.Close()
transport := &http.Transport{
Proxy: func(r *http.Request) (*url.URL, error) {
return url.Parse(server.URL)
},
}
svc := userService{db: db, client: &http.Client{Transport: transport}}
_, err := svc.FacebookLogin("asdf")
if err != nil {
t.Errorf("Error found: %s", err)
}
}
我尝试发起的请求如下:
url := "https://<Some facebook api endpoint>"
req, err := http.NewRequest("GET", url, nil)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
英文:
So I'm trying to mock out a response to an https request using httptest.TLSServer
but the http.Client
making the request keeps telling me that the server is giving an invalid http response. I bet this is because there's no actual SSL cert. Is there any way I can get the client to ignore tls while still mocking out an https request?
The test code in question
func TestFacebookLogin(t *testing.T) {
db := glob.db
server := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
resp := `
{
"id": "123",
"email": "blah",
"first_name": "Ben",
"last_name": "Botwin"
}
`
w.Write([]byte(resp))
}))
defer server.Close()
transport := &http.Transport{
Proxy: func(r *http.Request) (*url.URL, error) {
return url.Parse(server.URL)
},
}
svc := userService{db: db, client: &http.Client{Transport: transport}}
_, err := svc.FacebookLogin("asdf")
if err != nil {
t.Errorf("Error found: %s", err)
}
}
And the request that I'm trying to make:
url := "https://<Some facebook api endpoint>"
req, err := http.NewRequest("GET", url, nil)
resp, err := client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
答案1
得分: 6
测试服务器使用自签名证书。有两种方法可以避免错误。第一种方法是使用配置了test server的证书的HTTP客户端:
certs := x509.NewCertPool()
for _, c := range server.TLS.Certificates {
roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
if err != nil {
log.Fatalf("error parsing server's root cert: %v", err)
}
for _, root := range roots {
certs.AddCert(root)
}
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certs,
},
},
}
更简单的选择是跳过证书验证:
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
还有一个额外的问题。客户端期望连接到代理服务器,但实际上它直接连接到了测试服务器。尝试钩住拨号函数而不是代理:
client := http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return net.Dial("tcp", server.URL[strings.LastIndex(server.URL, "/")+1:])
},
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
英文:
The test server uses a self signed certificate. There are two ways to avoid errors. The first is to use an HTTP client configured with the test server's certificates:
certs := x509.NewCertPool()
for _, c := range server.TLS.Certificates {
roots, err := x509.ParseCertificates(c.Certificate[len(c.Certificate)-1])
if err != nil {
log.Fatalf("error parsing server's root cert: %v", err)
}
for _, root := range roots {
certs.AddCert(root)
}
}
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certs,
},
},
}
An easier option is to skip cert verification:
client := http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
There's an additional issue. The client expects to connect to a proxy server, but the it's actually connecting to the test server directly. Try hooking the dial function instead of the proxy:
client := http.Client{
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error) {
return net.Dial("tcp", server.URL[strings.LastIndex(server.URL, "/")+1:])
},
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
},
}
答案2
得分: 0
你只需要使用测试服务器提供的HTTP客户端:
httpClient := server.Client()
英文:
You just need to use the http client provided by the test server:
httpClient := server.Client()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论