Golang发送HTTP、HTTPS请求(包含Token和证书的请求)

您所在的位置:网站首页 go接收http请求 Golang发送HTTP、HTTPS请求(包含Token和证书的请求)

Golang发送HTTP、HTTPS请求(包含Token和证书的请求)

2024-06-05 23:17| 来源: 网络整理| 查看: 265

Golang发送HTTP、HTTPS请求 高能预警正文1. 最简单的 HTTP 请求 —— Get 方法使用场景代码解释说明 2. 难度升级——加入证书的 HTTPS 请求使用场景代码解释说明 3. 在 Header 中添加 token 的 HTTPS 请求使用场景代码解释说明关于 client.Do() 方法 博主踩过的坑后记

高能预警 本文略长,请大家根据目录选段食用~本文源自于博主在编写获取 Kubernetes 集群组件的 /metrics 接口下的内容的程序时踩过的坑,所以 Demo 将结合 K8S 集群进行测试。当然也适用于发送一些常规的 HTTP 请求、带有证书的 HTTPS 请求和一些需要在 Header 中添加 token 的请求。目的是为了读者们能够“开箱即用”。请大家自行类推。 正文 1. 最简单的 HTTP 请求 —— Get 方法 使用场景 假设我们访问的目标是:http://10.10.102.91:10251/metrics,在浏览器中是这样的: http://10.10.102.91:10251/metrics 那么我们如何使用 Golang 代码拿到这个页面的数据呢?请君继续阅读: 代码 package xxxxxxxxxxxxxxxxxxxxxxxxxx import ( "io/ioutil" "net/http" "time" ) func GetHttp(url string) (body []byte, err error) { // 创建 client 和 resp 对象 var client http.Client var resp *http.Response // 这里博主设置了10秒钟的超时 client = http.Client{Timeout: 10 * time.Second} // 这里使用了 Get 方法,并判断异常 resp, err = client.Get(url) if err != nil { return nil, err } // 释放对象 defer resp.Body.Close() // 把获取到的页面作为返回值返回 body, err = ioutil.ReadAll(resp.Body) if err != nil { return nil, err } // 释放对象 defer client.CloseIdleConnections() return body, nil } 解释说明

这段代码模拟了我们在浏览器中输入这个网址的过程,我们调用一下,看看是否拿到了我们想要的内容:

func TestGetHttp(t *testing.T) { resp, err := GetHttp("http://10.10.102.91:10251/metrics") if err != nil { fmt.Println(err) } fmt.Println(string(resp)) }

输出如下: 输出结果截图 验证通过。

这里使用了 Golang 的标准库 "net/http" 中的 Get() 方法来获取 Response,并使用 "io/ioutil" 中的 ReadAll() 方法解析页面。 2. 难度升级——加入证书的 HTTPS 请求 使用场景 假设我们访问的目标是:https://10.10.102.91:2379/metrics,在浏览器中是这样的: https://10.10.102.91:2379/metrics 可以看到我们并没有权限访问这个URL,也就是说,如果我们访问时没有拿着他想要的证书和 key,他就不会给我们展示我们想要的数据。我们再用一个粗糙的方式,看看给他想要的证书和key到底能不能正确展示: 加入证书和 key,验证 验证成功。我们使用代码实现,请君继续阅读: 代码 package xxxxxxxxxxxxxxxxxxxxxxxxxx import ( "crypto/tls" "crypto/x509" "io/ioutil" "net/http" "time" ) func GetHttps(url, caCertPath, certFile, keyFile string) ([]byte, error) { // 创建证书池及各类对象 var pool *x509.CertPool // 我们要把一部分证书存到这个池中 var client *http.Client var resp *http.Response var body []byte var err error var caCrt []byte // 根证书 caCrt, err = ioutil.ReadFile(caCertPath) pool = x509.NewCertPool() if err != nil { return nil, err } pool.AppendCertsFromPEM(caCrt) var cliCrt tls.Certificate // 具体的证书加载对象 cliCrt, err = tls.LoadX509KeyPair(certFile, keyFile) if err != nil { return nil, err } // 把上面的准备内容传入 client client = &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: pool, Certificates: []tls.Certificate{cliCrt}, }, }, } // Get 请求 resp, err = client.Get(url) if err != nil { return nil, err } defer resp.Body.Close() body, err = ioutil.ReadAll(resp.Body) if err != nil { return nil, err } defer client.CloseIdleConnections() return body, nil } 解释说明

我们把服务器中的证书文件拿到本地,作为参数传入程序。

func TestGetHttps(t *testing.T) { resp, err := GetHttps("https://10.10.102.91:2379/metrics", "C:/Users/Liing/Desktop/ca.crt", "C:/Users/Liing/Desktop/healthcheck-client.crt", "C:/Users/Liing/Desktop/healthcheck-client.key") if err != nil { fmt.Println(err) } fmt.Println(string(resp)) }

输出如下: 输出结果截图 验证通过。

这里使用了 “crypto” 标准库,其中,我们使用 tls.LoadX509KeyPair()方法读取证书路径,转换为证书对象; x509.NewCertPool()方法创建证书池; pool.AppendCertsFromPEM(caCrt)方法将根证书加入到证书池中。 3. 在 Header 中添加 token 的 HTTPS 请求 使用场景 假设我们访问的目标是:https://10.10.102.91:10250/metrics,在浏览器中是这样的: https://10.10.102.91:10250/metrics 可以看到屏幕上赫然的Unauthorized把我们劝退,浏览器并没有提示缺失证书,那我们试试在请求中加入 token。同样使用粗糙的办法验证: 加入 token,验证 验证成功。接下来我们使用代码实现,请君继续阅读: 代码 func GetHttpsSkip(url, token string) ([]byte, error) { // 创建各类对象 var client *http.Client var request *http.Request var resp *http.Response var body []byte var err error `这里请注意,使用 InsecureSkipVerify: true 来跳过证书验证` client = &http.Client{Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }} // 获取 request请求 request, err = http.NewRequest("GET", url, nil) if err != nil { log.Println("GetHttpSkip Request Error:", err) return nil, nil } // 加入 token request.Header.Add("Authorization", token) resp, err = client.Do(request) if err != nil { log.Println("GetHttpSkip Response Error:", err) return nil, nil } defer resp.Body.Close() body, err = ioutil.ReadAll(resp.Body) defer client.CloseIdleConnections() return body, nil } 解释说明

传入 token,验证

func TestGetHttps(t *testing.T) { resp, err := GetHttpsSkip("https://10.10.102.91:10250/metrics", "Bearer eyxxxxxxxxxxxxxxxxxxxx....xxxxx") if err != nil { fmt.Println(err) } fmt.Println(string(resp)) }

输出如下: 输出结果截图 验证通过。

这里使用了 “crypto” 标准库,其中,我们使用 InsecureSkipVerify: true 来跳过证书验证; http.NewRequest()创建一个新的请求; request.Header.Add()加入请求头的键与值; client.Do()完成本次request请求。 关于 client.Do() 方法

功能说明:

`标准库代码上方的部分注释文字` Do sends an HTTP request and returns an HTTP response, following policy (such as redirects, cookies, auth) as configured on the client. `机翻` 遵循客户端上配置的策略(例如重定向,Cookie,身份验证),发送 HTTP 请求并返回 HTTP 响应。

博主在理解这个方法时脑筋没有急转弯,所以在此也给大家简单解释一下,在http.NewRequest()时并没有发送这个请求,而是在做准备工作,创建好对象后还要向请求头中添加信息,比如重定向、Cookie还有上文提到的token等,这些工作准备完毕后,我们才会调用client.Do()方法进行一次“准备充分”的request请求。

博主踩过的坑 client.CloseIdleConnections() 如果我们重复发送 HTTP 请求时没有调用这个方法来关闭空闲连接,会导致内存泄漏!博主写完代码满心欢喜地在机器上跑着,结果发现短短几个小时 Demo 的内存占用已经达到了几百 MB。最终调用了这个方法才得以解决。 后记 因为本文内容较多,所以没有提到 post 请求的实现方式。在以后的时间里,博主会尽快更新,期待着和读者们一起进步。

感谢阅读。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3