一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術(shù)及教程分享平臺(tái)!
分類導(dǎo)航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務(wù)器之家 - 腳本之家 - Golang - golang http請(qǐng)求封裝代碼

golang http請(qǐng)求封裝代碼

2021-02-28 01:01一名路過的小碼農(nóng) Golang

這篇文章主要介紹了golang http請(qǐng)求封裝代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧

在GOPATH 中創(chuàng)建 utils 文件夾 放置這兩個(gè)文件

http.go

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package utils
import (
 "crypto/tls"
 "encoding/json"
 "errors"
 "fmt"
 "io/ioutil"
 "net/http"
 "net/url"
 "strings"
 "sync"
)
var (
 GET_METHOD = "GET"
 POST_METHOD = "POST"
 SENDTYPE_FROM = "from"
 SENDTYPE_JSON = "json"
)
type HttpSend struct {
 Link  string
 SendType string
 Header map[string]string
 Body  map[string]string
 sync.RWMutex
}
func NewHttpSend(link string) *HttpSend {
 return &HttpSend{
  Link:  link,
  SendType: SENDTYPE_FROM,
 }
}
func (h *HttpSend) SetBody(body map[string]string) {
 h.Lock()
 defer h.Unlock()
 h.Body = body
}
func (h *HttpSend) SetHeader(header map[string]string) {
 h.Lock()
 defer h.Unlock()
 h.Header = header
}
func (h *HttpSend) SetSendType(send_type string) {
 h.Lock()
 defer h.Unlock()
 h.SendType = send_type
}
func (h *HttpSend) Get() ([]byte, error) {
 return h.send(GET_METHOD)
}
func (h *HttpSend) Post() ([]byte, error) {
 return h.send(POST_METHOD)
}
func GetUrlBuild(link string, data map[string]string) string {
 u, _ := url.Parse(link)
 q := u.Query()
 for k, v := range data {
  q.Set(k, v)
 }
 u.RawQuery = q.Encode()
 return u.String()
}
func (h *HttpSend) send(method string) ([]byte, error) {
 var (
  req  *http.Request
  resp  *http.Response
  client http.Client
  send_data string
  err  error
 )
 if len(h.Body) > 0 {
  if strings.ToLower(h.SendType) == SENDTYPE_JSON {
   send_body, json_err := json.Marshal(h.Body)
   if json_err != nil {
    return nil, json_err
   }
   send_data = string(send_body)
  } else {
   send_body := http.Request{}
   send_body.ParseForm()
   for k, v := range h.Body {
    send_body.Form.Add(k, v)
   }
   send_data = send_body.Form.Encode()
  }
 }
 //忽略https的證書
 client.Transport = &http.Transport{
  TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
 }
 req, err = http.NewRequest(method, h.Link, strings.NewReader(send_data))
 if err != nil {
  return nil, err
 }
 defer req.Body.Close()
 
 //設(shè)置默認(rèn)header
 if len(h.Header) == 0 {
  //json
  if strings.ToLower(h.SendType) == SENDTYPE_JSON {
   h.Header = map[string]string{
    "Content-Type": "application/json; charset=utf-8",
   }
  } else { //form
   h.Header = map[string]string{
    "Content-Type": "application/x-www-form-urlencoded",
   }
  }
 }
 for k, v := range h.Header {
  if strings.ToLower(k) == "host" {
   req.Host = v
  } else {
   req.Header.Add(k, v)
  }
 }
 resp, err = client.Do(req)
 if err != nil {
  return nil, err
 }
 defer resp.Body.Close()
 
 if resp.StatusCode != http.StatusOK {
  return nil, errors.New(fmt.Sprintf("error http code :%d", resp.StatusCode))
 }
 return ioutil.ReadAll(resp.Body)
}

http_test.go

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package utils
import (
 "testing"
)
func Test_Get(t *testing.T) {
 h := NewHttpSend(GetUrlBuild("http://127.0.0.1/test.php", map[string]string{"name": "xiaochuan"}))
 _, err := h.Get()
 if err != nil {
 t.Error("請(qǐng)求錯(cuò)誤:", err)
 } else {
 t.Log("正常返回")
 }
}
func Test_Post(t *testing.T) {
 h := NewHttpSend("http://127.0.0.1/test.php")
 h.SetBody(map[string]string{"name": "xiaochuan"})
 _, err := h.Post()
 if err != nil {
 t.Error("請(qǐng)求錯(cuò)誤:", err)
 } else {
 t.Log("正常返回")
 }
}
func Test_Json(t *testing.T) {
 h := NewHttpSend("http://127.0.0.1/test.php")
 h.SetSendType("JSON")
 h.SetBody(map[string]string{"name": "xiaochuan"})
 _, err := h.Post()
 if err != nil {
 t.Error("請(qǐng)求錯(cuò)誤:", err)
 } else {
 t.Log("正常返回")
 }
}
func Benchmark_GET(b *testing.B) {
 for i := 0; i < b.N; i++ {
 h := NewHttpSend(GetUrlBuild("http://127.0.0.1/test.php", map[string]string{"name": "xiaochuan"}))
 _, err := h.Get()
 if err != nil {
 b.Error("請(qǐng)求錯(cuò)誤:", err)
 } else {
 b.Log("正常返回")
 }
 }
}

補(bǔ)充:golang中發(fā)送http請(qǐng)求的幾種常見情況

整理一下golang中各種http的發(fā)送方式

最初的一些項(xiàng)目中,很多的地方都使用到了golang發(fā)送http請(qǐng)求,之后再對(duì)請(qǐng)求收到的結(jié)果進(jìn)行一些處理,所用到的模式也比較固定,這里整理一下集中http的發(fā)送方式,先記錄這么多,再一點(diǎn)一點(diǎn)添加。

最基本的場(chǎng)景

方式一 使用http.Newrequest

先生成http.client -> 再生成 http.request -> 之后提交請(qǐng)求:client.Do(request) -> 處理返回結(jié)果,每一步的過程都可以設(shè)置一些具體的參數(shù),下面是一個(gè)最樸素最基本的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//question ???將stdout重定向?yàn)閞esponse信息???
package main
import (
 "fmt"
 "io"
 "net/http"
 "os"
)
func main() {
 //生成client 參數(shù)為默認(rèn)
 client := &http.Client{}
 //生成要訪問的url
 url := "http://www.baidu.com" 
 //提交請(qǐng)求
 reqest, err := http.NewRequest("GET", url, nil)
 if err != nil {
 panic(err)
 }
 //處理返回結(jié)果
 response, _ := client.Do(reqest)
 //將結(jié)果定位到標(biāo)準(zhǔn)輸出 也可以直接打印出來 或者定位到其他地方進(jìn)行相應(yīng)的處理
 stdout := os.Stdout
 _, err = io.Copy(stdout, response.Body)
 //返回的狀態(tài)碼
 status := response.StatusCode
 fmt.Println(status)
}

方式二 先生成client,之后用client.get/post..

client結(jié)構(gòu)自己也有一些發(fā)送api的方法,比如client.get,client.post,client.postform..等等。基本上涵蓋了主要的http請(qǐng)求的類型,通常不進(jìn)行什么特殊的配置的話,這樣就可以了,其實(shí)client的get或者post方法,也是對(duì)http.Newerequest方法的封裝,里面還額外添加了req.Header.Set("Content-Type", bodyType)一般用的話,也是ok的

方式三 http. Get/Post..

具體實(shí)現(xiàn)的時(shí)候,還是采用的先前提到的模式,先生成一個(gè)默認(rèn)的client,之后調(diào)用http.Newrequest方法。

對(duì)每個(gè)步驟進(jìn)行細(xì)節(jié)性的說明

生成client時(shí)候的參數(shù)配置

最常見的一個(gè)參數(shù)是使用https的方式發(fā)送信息時(shí)候client端的設(shè)置。如果生成client的時(shí)候,什么信息都不添加,就會(huì)使用默認(rèn)的值。具體的信息包括:

?
1
2
3
4
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration

第一個(gè)參數(shù)是一個(gè)RoundTripper接口,里面包含了一個(gè)RoundTrip函數(shù),指定了一些http請(qǐng)求的基本機(jī)制。

http.Transport中涉及到的參數(shù)較多,要是不指定的話,就會(huì)使用默認(rèn)的DefaultTransport參數(shù),里面包含一些默認(rèn)的請(qǐng)求時(shí)間以及proxy機(jī)制之類的。

具體的細(xì)節(jié)參數(shù)涉及到好多,有的都沒有使用到過比如那些我握手時(shí)間之類的,目前使用到的最多的就是https的相關(guān)參數(shù):TLSClientConfig,這是一個(gè)*tls.Config類型,其中涉及到的參數(shù)還是有很多,一個(gè)基本的是用案例如下,僅僅是在配置中制定了rooca以及客戶度端使用的證書。

通常發(fā)送https請(qǐng)求的時(shí)候,前面的參數(shù)可以使用如下方式進(jìn)行處理:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
pool := x509.NewCertPool()
 caCertPath := "certs/cert_server/ca.crt"
 caCrt, err := ioutil.ReadFile(caCertPath)
 if err != nil {
 fmt.Println("ReadFile err:", err)
 return
 }
 pool.AppendCertsFromPEM(caCrt)
 cliCrt, err := tls.LoadX509KeyPair("certs/cert_server/client.crt", "certs/cert_server/client.key")
 if err != nil {
 fmt.Println("Loadx509keypair err:", err)
 return
 }
 tr := &http.Transport{
 TLSClientConfig: &tls.Config{
 RootCAs:  pool,
 Certificates: []tls.Certificate{cliCrt},
 },
 }
 client := &http.Client{Transport: tr}

生成request時(shí)候的參數(shù)配置

生成request的時(shí)候,主要的是幾個(gè)基本的參數(shù)。NewRequest函數(shù)有三個(gè)基本的參數(shù),NewRequest(method, urlStr string, body io.Reader)第一個(gè)是請(qǐng)求的類型,GET, POST, PUT, etc.要設(shè)成大寫的形式。第二個(gè)參數(shù)是請(qǐng)求要訪問的url,第三個(gè)參數(shù)是請(qǐng)求的body中的內(nèi)容,需要是一個(gè)io.Reader的類型。

注意io.Reader的接口中是一個(gè)Read方法,實(shí)現(xiàn)了Read方法的類型應(yīng)該都可以作為io.Reader來返回,Read(p []byte) (n int, err error)函數(shù)具體的功能就是讀入len(p)長(zhǎng)度的內(nèi)容到p中,返回讀入的長(zhǎng)度以及錯(cuò)誤信息。

通常是采用strings.NewReader函數(shù),將一個(gè)string類型轉(zhuǎn)化為io.Reader類型,或者bytes.NewBuffer函數(shù),將[]byte類型轉(zhuǎn)化為io.Reader類型。

此外還可以給request的header中添加一些額外的信息,比如下面例子中添加了請(qǐng)求的body的類型以及token的信息。

reqest.Header.Set("Content-Type", "application/x-www-form-urlencoded")

reqest.Header.Set("Authorization", "qwertyuiopasdfghjklzxcvbnm1234567890")

還有比如模擬表單提交,可以把提交的類型設(shè)置為url.Values類型再進(jìn)行Encode:

?
1
2
3
4
5
6
7
8
9
10
11
// use map as struct
 var clusterinfo = url.Values{}
 //var clusterinfo = map[string]string{}
 clusterinfo.Add("userName", user)
 clusterinfo.Add("password", pw)
 clusterinfo.Add("cloudName", clustername)
 clusterinfo.Add("masterIp", masterip)
 clusterinfo.Add("cacrt", string(caCrt))
 data := clusterinfo.Encode()
 url := "https://10.10.105.124:8443/user/checkAndUpdate"
 reqest, err := http.NewRequest("POST", url, strings.NewReader(data))

最常見的一種情況是發(fā)送一個(gè)json文件過去,可以把Header的類型設(shè)置成為:

"Content-Type", "application/json; charset=utf-8"

其余的部分按照先前同樣的方式進(jìn)行設(shè)置發(fā)送提交就好。

request的類型的屬性還是比較多的,慢慢整理。

生成的response結(jié)果的處理

一般在client構(gòu)建好之后,要采用client.Do(request)方法提交client請(qǐng)求,之后會(huì)返回一個(gè)*Response類型。response中的參數(shù)一般也比較多,我們需要的最多的通常是Body參數(shù),一般通過body, _ := ioutil.ReadAll(resp.Body)會(huì)把body轉(zhuǎn)化為[]byte類型返回過來, 之后再進(jìn)行其他的處理。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

原文鏈接:https://xiaochuan.blog.csdn.net/article/details/81539820

延伸 · 閱讀

精彩推薦
  • GolangGolang通脈之?dāng)?shù)據(jù)類型詳情

    Golang通脈之?dāng)?shù)據(jù)類型詳情

    這篇文章主要介紹了Golang通脈之?dāng)?shù)據(jù)類型,在編程語言中標(biāo)識(shí)符就是定義的具有某種意義的詞,比如變量名、常量名、函數(shù)名等等,Go語言中標(biāo)識(shí)符允許由...

    4272021-11-24
  • Golanggolang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法

    今天小編就為大家分享一篇golang json.Marshal 特殊html字符被轉(zhuǎn)義的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧 ...

    李浩的life12792020-05-27
  • Golanggolang的httpserver優(yōu)雅重啟方法詳解

    golang的httpserver優(yōu)雅重啟方法詳解

    這篇文章主要給大家介紹了關(guān)于golang的httpserver優(yōu)雅重啟的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,...

    helight2992020-05-14
  • Golanggo日志系統(tǒng)logrus顯示文件和行號(hào)的操作

    go日志系統(tǒng)logrus顯示文件和行號(hào)的操作

    這篇文章主要介紹了go日志系統(tǒng)logrus顯示文件和行號(hào)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧...

    SmallQinYan12302021-02-02
  • GolangGolang中Bit數(shù)組的實(shí)現(xiàn)方式

    Golang中Bit數(shù)組的實(shí)現(xiàn)方式

    這篇文章主要介紹了Golang中Bit數(shù)組的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧...

    天易獨(dú)尊11682021-06-09
  • Golanggo語言制作端口掃描器

    go語言制作端口掃描器

    本文給大家分享的是使用go語言編寫的TCP端口掃描器,可以選擇IP范圍,掃描的端口,以及多線程,有需要的小伙伴可以參考下。 ...

    腳本之家3642020-04-25
  • Golanggolang如何使用struct的tag屬性的詳細(xì)介紹

    golang如何使用struct的tag屬性的詳細(xì)介紹

    這篇文章主要介紹了golang如何使用struct的tag屬性的詳細(xì)介紹,從例子說起,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看...

    Go語言中文網(wǎng)11352020-05-21
  • Golanggolang 通過ssh代理連接mysql的操作

    golang 通過ssh代理連接mysql的操作

    這篇文章主要介紹了golang 通過ssh代理連接mysql的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧...

    a165861639710342021-03-08
主站蜘蛛池模板: 亚洲日本在线观看网址 | 操美女网址 | 国产精品一区二区久久不卡 | 99精品视频免费在线观看 | 成人α片| 日本天堂视频 | 青青草99热这里都是精品 | 18美女光胸光屁屁洗澡 | 国产精品成人一区二区 | 青青青视频免费线看 视频 青青青青青国产免费手机看视频 | 精品成人一区二区三区免费视频 | 日本激情小说 | 第四色男人天堂 | 涩涩国产精品福利在线观看 | 男人操女人动图 | 成功精品影院 | 91制片厂官网 | 亚洲国产精品综合福利专区 | 52av我爱avhaose01好 | 女八把屁股扒开让男生添 | 国产高清在线播放刘婷91 | 色综合天天娱乐综合网 | 午夜私人影院在线观看 视频 | 国产老村长足疗店对白 | 性欧美videosex18嫩 | 精品久久久久香蕉网 | 国产乱叫456在线 | 99久久国产综合精品女小说 | 91无毒不卡 | 亚洲男人第一天堂 | 日韩一区二区三区免费 | 夫妇野外交换激情 | 好涨好大我快受不了了视频网 | 亚洲精品高清中文字幕完整版 | 午夜精品在线视频 | 国产欧美精品一区二区三区 | 忘忧草在线 | 久久免费看少妇高潮A片2012 | 能播放18xxx18女同 | b站免费网站入口 | 猫咪社区免费资源在线观看 |