【发布时间】:2015-03-08 23:25:51
【问题描述】:
我正在尝试为向 Web 服务发出请求的包编写测试。我遇到问题可能是因为我对 TLS 缺乏了解。
目前我的测试看起来像这样:
func TestSimple() {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(200)
fmt.Fprintf(w, `{ "fake" : "json data here" }`)
}))
transport := &http.Transport{
Proxy: func(req *http.Request) (*url.URL, error) {
return url.Parse(server.URL)
},
}
// Client is the type in my package that makes requests
client := Client{
c: http.Client{Transport: transport},
}
client.DoRequest() // ...
}
我的包有一个包变量(我希望它是一个常量..),用于查询 Web 服务的基地址。它是一个 https URL。我在上面创建的测试服务器是纯 HTTP,没有 TLS。
默认情况下,我的测试失败并显示错误“tls:第一条记录看起来不像 TLS 握手。”
为了让它工作,我的测试在进行查询之前将包变量更改为纯 http URL 而不是 https。
有没有办法解决这个问题?我可以将包变量设为常量 (https),然后设置一个“降级”为未加密 HTTP 的 http.Transport,还是改用 httptest.NewTLSServer()?
(当我尝试使用 NewTLSServer() 时,我收到“http: TLS 握手错误来自 127.0.0.1:45678: tls: 收到长度为 20037 的超大记录”)
【问题讨论】:
-
你真的需要模拟一个 TLS 请求吗? net/http 具有广泛的测试,因此针对本地 HTTPS 托管的测试实现进行测试是相当多余的。直接针对 HTTP 进行测试在语义上是等效的。
-
没有。事实上,我现在正在嘲笑 HTTP。我只是不喜欢我必须用来强制 HTTP 的解决方法。某些东西会自动尝试使用 TLS,因为请求 URL 以 https 开头。我很乐意仅为我的测试禁用此行为。
-
好的,在这种情况下,您可以创建一个 http.RoundTripper 的实现,它可以做任何您想做的事情(例如将 https:// 视为 http url)——您甚至可以使用自定义 RoundTripper 直接运行模拟 http.Handler,而无需通过 httptest.Server。你所要做的就是
http.DefaultClient.Transport = CustomRoundTripper。 -
自定义
http.RoundTripper就像一个魅力。您应该将您的评论转换为答案,以便我接受。