Http Client
Http Client 设置
设置超时机制
参考文档:https://stackoverflow.com/questions/16895294/how-to-set-timeout-for-http-get-requests-in-golang/16895878
client := http.Client{
Timeout: 5 * time.Second,
}
client.Get(url)
Http Client 使用
Get 获取内容
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET",
"https://raw.githubusercontent.com/wanglu119/HDoc/master/README.md", nil)
resp, err := client.Do(req)
if err != nil {
println("ifDnsmasq Fails: cannot connect")
} else {
println("ifDnsmasq Success")
s, _ := ioutil.ReadAll(resp.Body)
if err == nil {
fmt.Printf("%s", s)
}
defer resp.Body.Close()
}
}
输出:
ifDnsmasq Success
# HDoc
发送Get和Post请求(Json ),带参数
参看文档:https://www.cnblogs.com/junneyang/p/6211190.html
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
resp, _ := http.Get("http://localhost:2050/?a=123456&b=aaa&b=bbb")
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
var user User
user.Name = "aaa"
user.Age = 99
if bs, err := json.Marshal(user); err == nil {
req := bytes.NewBuffer([]byte(bs))
body_type := "application/json;charset=utf-8"
resp, _ = http.Post("http://localhost:2050/test", body_type, req)
body, _ = ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
} else {
fmt.Println(err)
}
client := &http.Client{}
request, _ := http.NewRequest("GET",
"http://localhost:2050/?a=123456&b=aaa&b=bbb", nil)
request.Header.Set("Connection", "keep-alive")
response, _ := client.Do(request)
if response.StatusCode == 200 {
body, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(body))
}
req := `{"name":"test", "age":88}`
req_new := bytes.NewBuffer([]byte(req))
request, _ = http.NewRequest("POST", "http://localhost:2050/test", req_new)
request.Header.Set("Content-Type", "application/json")
response, _ = client.Do(request)
if response.StatusCode == 200 {
body, _ = ioutil.ReadAll(response.Body)
fmt.Println(string(body))
}
}
输出:
It works!
{"name":"aaa","age":199}
It works!
{"name":"test","age":188}
请求配置 Basic Auth
参考文档: https://stackoverflow.com/questions/16673766/basic-http-auth-in-go
示例:
func basicAuth(username, password string) string {
auth := username + ":" + password
return base64.StdEncoding.EncodeToString([]byte(auth))
}
func redirectPolicyFunc(req *http.Request, via []*http.Request) error{
req.Header.Add("Authorization","Basic " + basicAuth("username1","password123"))
return nil
}
func main() {
client := &http.Client{
Jar: cookieJar,
CheckRedirect: redirectPolicyFunc,
}
req, err := http.NewRequest("GET", "http://localhost/", nil)
req.Header.Add("Authorization","Basic " + basicAuth("username1","password123"))
resp, err := client.Do(req)
}
发送application/x-www-form-urlencoded类型请求
参考文档: https://blog.csdn.net/liu822665/article/details/120428868
需要结合标准库url
的Values
结构体,比如:
postData := url.Values{}
postData.Add("name", "Chris")
postData.Add("language", "golang")
普通post
请求可以直接使用http.Post
方法,第二个参数为application/x-www-form-urlencoded
,如:
response, err := http.Post("https://xorpay.com/api/pay/aid",
"application/x-www-form-urlencoded", strings.NewReader(postData.Encode()))
调用gitea示例:
func basicAuth(username, password string) string {
auth := username + ":" + password
return base64.StdEncoding.EncodeToString([]byte(auth))
}
func runMigrate(ctx *cli.Context) error {
migrateUrl := fmt.Sprintf("%s%s", ctx.GlobalString("url"), "/api/v1/repos/migrate")
fmt.Println(migrateUrl)
postData := url.Values{}
postData.Add("clone_addr", "http://wl.gitlab/root/simple_shell.git")
postData.Add("repo_name", "simple_shell")
postData.Add("auth_token", "xxxxxx")
if ctx.IsSet("mirror") {
postData.Add("mirror", "true")
postData.Add("mirror_interval", "2h0m0s")
}
req, err := http.NewRequest("POST", migrateUrl, strings.NewReader(postData.Encode()))
if err != nil {
log.Fatal("migrate create req error: %v", err)
}
req.Header.Add("Authorization", "Basic "+basicAuth(Username, Password))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("migrate error: %v", err)
return err
}
bs, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(bs))
fmt.Println("migrate finish")
return nil
}
http.client实现访问网站保持同一会话
参考文档: https://blog.csdn.net/qq_34068584/article/details/121559832
背景:
有些网站需要登录后才能查看或者进一步操作,比如下单等等。那在python上requests库的session可以帮助我们在这种业务场景下,只需要执行请求、而不需要每一步都写代码携带cookie。因为session帮助我们做了这件事。那么在go语言中,有没有这种类型的东西呢?
http.client 是用来创建一个客户端,模拟客户端发送请求,可以通过它来实现设置请求头部、重定向等等操作。
我们先来看看client的定义。从这段话中,可以知道 Jar这个变量的作用就是:
- 每次发送请求时,带上cookie
- 每次接收响应时,更新cookie
type Client struct {
...
// Jar specifies the cookie jar.
//
// The Jar is used to insert relevant cookies into every
// outbound Request and is updated with the cookie values
// of every inbound Response. The Jar is consulted for every
// redirect that the Client follows.
//
// If Jar is nil, cookies are only sent if they are explicitly
// set on the Request.
Jar CookieJar
...
}
所以实际操作为:
// 1、首先声明一个用来管理cookie的变量jar
jar,_ := cookiejar.New(nil)
// 2、创建一个客户端
client := &http.Client{
Jar: jar,
}
// 3、构造并发送请求1
res1,_ := client.do(req1) //发送请求时自动带上cookie,并在返回响应时更新cookie
// 4、构造并发送请求2
res2,_ := client.do(req2) //发送请求
示例: gitea的更新repo的mirror,需要先登录:
func getCsrf(giteaUrl string, client *http.Client) string {
loginUrl := fmt.Sprintf("%s%s", giteaUrl, "/user/login")
postData := url.Values{}
postData.Add("user_name", Username)
postData.Add("password", Password)
postData.Add("remember", "true")
req, err := http.NewRequest("POST", loginUrl,
strings.NewReader(postData.Encode()))
if err != nil {
log.Fatal("migrate create req error: %v", err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
log.Fatal("migrate error: %v", err)
}
_csrf := ""
fmt.Println(resp.Cookies())
for _, c := range resp.Cookies() {
if c.Name == "_csrf" {
_csrf = c.Value
}
}
return _csrf
}
func runMirror(ctx *cli.Context) error {
jar, _ := cookiejar.New(nil)
client := &http.Client{
Jar: jar,
}
giteaUrl := ctx.GlobalString("url")
mirrorUrl := ctx.String("url")
_csrf := getCsrf(giteaUrl, client)
postData := url.Values{}
postData.Add("_csrf", _csrf)
postData.Add("action", "mirror")
postData.Add("interval", "3h0m0s")
mirror_address := fmt.Sprintf("%s/%s/%s.git", mirrorUrl, Username, "simple_shell")
fmt.Println("mirror_address:", mirror_address)
postData.Add("mirror_address", mirror_address)
setttingUrl := fmt.Sprintf("%s/%s/%s/settings", giteaUrl, Username, "simple_shell")
fmt.Println("setttingUrl: ", setttingUrl)
req, err := http.NewRequest("POST", setttingUrl,
strings.NewReader(postData.Encode()))
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
resp, err := client.Do(req)
if err != nil {
log.Fatal("migrate error: %v", err)
return err
}
bs, _ := ioutil.ReadAll(resp.Body)
respStr := string(bs)
idx := strings.Index(respStr, "ui negative message flash-error")
if idx > 0 {
fmt.Println(string(bs)[idx : idx+100])
}
fmt.Println(respStr)
return nil
}
golang 请求 https 网站跳过证书验证
参考文档:https://www.jianshu.com/p/3e9893a2eaf5
在用 Golang 访问 IPPBX 的管理页面时出现以下错误,因为证书是未经过认证的,而是自己创建的。
错误信息:Get https://192.168.0.199:8443/config/app:
x509: certificate signed by unknown authority
所以需要忽略检查证书,以下是部分代码
import (
"crypto/tls"
"net/http"
"net/http/cookiejar"
)
...
//跳过证书验证
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
//http cookie接口
cookieJar, _ := cookiejar.New(nil)
c := &http.Client{
Jar: cookieJar,
Transport: tr,
}
c.Get("https://192.168.0.199:8443/config/app: ")
...