在如何在 Go 中使用 REST API 中,提供了完全有效的示例代码来调用公共 REST API。但如果我尝试示例,就会出现此错误:
error getting cat fact:
Get "https://catfact.ninja/fact":
proxyconnect tcp: tls: first record does not look like a TLS handshake
要控制代理、TLS 配置、保持活动、压缩和其他设置,请创建传输:
以及来自运输文档:
// DialContext specifies the dial function for creating unencrypted TCP connections.
// If DialContext is nil (and the deprecated Dial below is also nil),
// then the transport dials using package net.
//
// DialContext runs concurrently with calls to RoundTrip.
// A RoundTrip call that initiates a dial may end up using
// a connection dialed previously when the earlier connection
// becomes idle before the later DialContext completes.
DialContext func(ctx context.Context, network, addr string) (net.Conn, error)
所以我假设我必须配置 Dialcontext 才能启用从客户端到代理的不安全连接
without TLS
。但我不知道该怎么做。阅读这些:
也没有帮助。有些有同样的错误
proxyconnect tcp: tls: first record does not look like a TLS handshake
并解释原因:
这是因为代理以简单的 HTTP 错误响应奇怪的 HTTP 请求(这实际上是 TLS 握手的开始)。
但是Steffen的回复没有如何设置
DialContext func(ctx context.Context, network, addr string)
的示例代码,并且Bogdan和cyberdelia都建议设置tls.Config{InsecureSkipVerify: true}
,例如像这样
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := &http.Client{Transport: tr}
但是上面没有效果。我仍然遇到同样的错误。连接仍然调用
https://*
而不是 http://*
这是示例代码,我尝试包含上述建议并对其进行调整:
var tr = &http.Transport{ TLSClientConfig:
&tls.Config{InsecureSkipVerify: true}, }
// lacks DialContext config
var client* http.Client = &http.Client{Transport: tr} // modified * added
// var client *http.Client // code from tutorial
type CatFact struct {
Fact string `json:"fact"`
Length int `json:"length"`
}
func GetCatFact() {
url := "http://catfact.ninja/fact" // changed from https to http
var catFact CatFact
err := GetJson(url, &catFact)
if err != nil {
fmt.Printf("error getting cat fact: %s\n", err.Error())
} else {
fmt.Printf("A super interesting Cat Fact: %s\n", catFact.Fact)
}
}
func main() {
client = &http.Client{Timeout: 10 * time.Second}
GetCatFact()
// same error
// proxyconnect tcp: tls: first record does
// not look like a TLS handshake
// still uses https
// for GET catfact.ninja
}
如何将连接配置为使用从 myClient 通过代理到服务器的未加密连接?设置
DialContext func(ctx context.Context, network, addr string)
有助于做到这一点吗?怎么办?
我刚刚尝试过:
package main
import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"net"
"net/http"
"time"
)
type CatFact struct {
Fact string `json:"fact"`
Length int `json:"length"`
}
// Custom dialing function to handle connections
func customDialContext(ctx context.Context, network, addr string) (net.Conn, error) {
conn, err := net.Dial(network, addr)
return conn, err
}
// Function to get a cat fact
func GetCatFact(client *http.Client) {
url := "https://catfact.ninja/fact" // Reverted back to https
var catFact CatFact
err := GetJson(url, &catFact, client)
if err != nil {
fmt.Printf("error getting cat fact: %s\n", err.Error())
} else {
fmt.Printf("A super interesting Cat Fact: %s\n", catFact.Fact)
}
}
// Function to send a GET request and decode the JSON response
func GetJson(url string, target interface{}, client *http.Client) error {
resp, err := client.Get(url)
if err != nil {
return fmt.Errorf("error sending GET request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("received non-OK HTTP status: %d", resp.StatusCode)
}
err = json.NewDecoder(resp.Body).Decode(target)
if err != nil {
return fmt.Errorf("error decoding JSON response: %w", err)
}
return nil
}
func main() {
// Create a custom Transport with the desired settings
tr := &http.Transport{
Proxy: http.ProxyFromEnvironment, // Use the proxy settings from the environment
DialContext: customDialContext, // Use the custom dialing function
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true, // Skip certificate verification (not recommended in production)
},
}
// Create a new HTTP client using the custom Transport
client := &http.Client{
Transport: tr,
Timeout: 10 * time.Second,
}
// Call the function to get a cat fact
GetCatFact(client)
}
它包括:
自定义拨号功能
customDialContext
:net.Dial
的简单包装,但它提供了一个可以在必要时引入自定义拨号逻辑的地方。它用作自定义拨号功能,用于创建网络连接。
运输配置:
http.Transport
,包括自定义拨号功能、环境中的代理设置以及跳过证书验证的 TLS 配置(用于测试)。http.Transport
,但只包含了跳过证书验证的TLS配置,并没有设置自定义拨号功能或代理设置。客户端配置:
http.Client
创建新的 http.Transport
,并设置 10 秒的超时。http.Client
创建一个新的 http.Transport
,但后来在 main
函数中,它用带有默认 client
和一个新的 http.Client
覆盖了 Transport
变量。 10秒超时,有效丢弃自定义Transport
。函数签名:
GetCatFact
和 GetJson
函数以接受 *http.Client
参数,允许它们使用在 http.Client
中创建的自定义 main
。http.Client
传递给这些函数,因此它们会使用 http.Client
包提供的默认 net/http
。网址:
GetCatFact
函数中的“https://catfact.ninja/fact”,因为服务器无论如何都会将 HTTP 请求重定向到 HTTPS。