1. Client结构体
1.1 从一个极简示例开始
先写一个Get的极简示例,访问gitlab的所有项目(因为极简示例没有加token,因此只能获取到gitlab中开放的项目)
func HiHttp(){
resp, err := http.Get("http://gitlabcto.xxx.com.cn/api/v4/projects")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
//body是一个二进制组,用string(body[:])转换为字串
fmt.Printf("%s",string(body[:]))
}
1.2 结构体定义
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
1.3 包含的方法
Client结构体有以下方法:
send(req *http.Request, deadline time.Time) (resp *http.Response, didTimeout func() bool, err error)
deadline() time.Time
transport() http.RoundTripper
Get(url string) (resp *http.Response, err error)
checkRedirect(req *http.Request, via []*http.Request) error
Do(req *http.Request) (*http.Response, error)
do(req *http.Request) (retres *http.Response, reterr error)
makeHeadersCopier(ireq *http.Request) func(*http.Request)
Post(url string, contentType string, body io.Reader) (resp *http.Response, err error)
PostForm(url string, data url.Values) (resp *http.Response, err error)
Head(url string) (resp *http.Response, err error)
CloseIdleConnections()
我们会在后文详细叙述
1.4 初始化结构体
var DefaultClient = &http.Client{}
- 示例
func HiHttp(){
var myClient = &http.Client{}
resp, err := myClient.Get("http://gitlabcto.xxx.com.cn/api/v4/projects")
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
fmt.Printf("%s",string(body[:]))
}
2. Get() 方法
2.1 语法
1.2.1 Get方法
语法
func Get(url string) (resp *Response, err error)
示例
resp, err := http.Get("http://xxxx.xxx.com")
2.1.1 url
- 将字串转换为URL
非必要,如果后边url要拼参数的话可以用这个
func ParseRequestURI(rawURL string) (*URL, error)
- 示例
apiUrl := "http://gitlabcto.xxx.com.cn/api/v4/projects"
u,err := url.ParseRequestURI(apiUrl)
2.1.2 params(参数)
作用:在url后拼接参数
初始化
data := url.Values{}
设定参数
data.Set("key","value")
将参数添加到url
u.RawQuery = data.Encode()
u是上文中初始化的url
2.2 示例(不自定义header)
func HiHttp(){
apiUrl := "http://gitlabcto.xxx.com.cn/api/v4/projects"
// URL param
data := url.Values{}
data.Set("private_token", "-raXU2B8rVbRAFxxxxxx")
data.Set("per_page", "100")
data.Set("page", "30")
//把string转换为url
u, err := url.ParseRequestURI(apiUrl)
if err != nil {
fmt.Printf("parse url requestUrl failed,err:%v\n", err)
}
//将参数添加到请求url
u.RawQuery = data.Encode() // URL encode
fmt.Println(u.String())
resp, err := http.Get(u.String())
if err != nil {
fmt.Println("post failed, err:%v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("get resp failed,err:%v\n", err)
return
}
fmt.Println(string(b))
}
3. Post()方法
注意:此处是http包提供的一个简单的post方法,不能添加header,如果要添加header需要使用Do()方法。
3.1 语法
3.1.1 Post()方法
func Post(url string, contentType string, body io.Reader) (resp *Response, err error)
示例
http.Post(url, contentType, strings.NewReader(data))
body的定义,参见本文 Do()方法
3.1.2 contentType
表单格式
contentType := "application/x-www-form-urlencoded"
data := "key01=value01&key02=value02"
&
是html的转义符,即 &
json格式
contentType := "application/json"
data := `{"project_name": "liuBei","metadata": {"public": "true"}}`
3.2 示例(不添加header)
- 因为http包的Post() 方法没有header,因此harbor的认证是过不去的。
- 建议使用Do()方法
func PostHttp(){
url := "https://harbocto.xxx.com.cn/api/v2.0/projects"
contentType := "application/json"
data := `{"project_name": "liuBei","metadata": {"public": "true"}}`
resp, err := http.Post(url, contentType, strings.NewReader(data))
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
fmt.Println(string(b))
}
4. Do() 方法
4.1 语法
4.1.1 Do()方法
func (c *Client) Do(req *Request) (*Response, error)
示例
resp, _ := client.Do(req)
request
定义见下文
4.1.2 NewRequest
语法
func NewRequest(method string, url string, body io.Reader) (*Request, error)
示例:Get 方法,没有body的情况
req, err := http.NewRequest("GET", ""https://xxxx.xxxx.com.cn", nil)
示例:Post方法,body是json字串
req, err := http.NewRequest("POST", url, strings.NewReader(`{"project_name": "liubei","metadata": {"public": "true"}}`)
示例:Post方法,body是[]byte
var js []byte = xxxxxx
req, err := http.NewRequest("POST", url, bytes.NewBuffer(js))
4.1.3 Header 添加头信息
Set 函数
相同key的值会被替换为最新的
- 语法
func (h Header) Set(key string, value string)
- 示例
req.Header.Set("aaa", "111")
req.Header.Set("aaa", "222")
req.Header.Set("aaa", "333")
fmt.Printf("%+v\n",req.Header)
输出
map[Aaa:[333] Authorization:[Basic 5YiY5aSHOuaIkeS4jeS8muWRiuivieS9oOWvhueggQ== ] Content-Type:[application/json]]
Add 函数
相同key的值会被追加
- 语法
func (h Header) Add(key string, value string)
- 示例
req.Header.Add("aaa", "111")
req.Header.Add("aaa", "222")
req.Header.Add("aaa", "333")
fmt.Printf("%+v\n",req.Header)
输出
map[Aaa:[111 222 333] Authorization:[Basic 5YiY5aSHOuaIkeS4jeS8muWRiuivieS9oOWvhueggQ==] Content-Type:[application/json]]
4.1.4 Query
定义Query
func (u *URL) Query() Values
示例
req, err := http.NewRequest("GET", ""https://xxxx.xxxx.com.cn", nil)
q := req.URL.Query()
添加 Query
func (v Values) Add(key string, value string)
示例
定义q 见定义Query
q.Add("per_page", "3")
q.Add("page", "1")
4.2 示例(添加header)
func GetHttpWithHeader(){
client := &http.Client{}
apiURL := "https://harbocto.xxxx.com.cn/api/v2.0/projects/9"
req, err := http.NewRequest("GET", apiURL, nil)
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
req.Header.Add("Authorization", "Basic 5YiY5aSHOuaIkeS4jeS8muWRiuivieS9oOWvhueggQ==")
req.Header.Add("Content-Type", "application/json")
resp, _ := client.Do(req)
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed,err:%v\n\n", err)
return
}
fmt.Println(string(b))
}
4.3 示例(Get请求,添加Query)
func GetHttp(){
client := &http.Client{}
apiURL := "http://gitlabcto.xxx.com.cn/api/v4/projects"
req, err := http.NewRequest("GET", apiURL, nil)
//添加查询参数
q := req.URL.Query()
q.Add("private_token", "-raXU2B8rVbRAFdYEqEg")
q.Add("per_page", "3")
q.Add("page", "1")
req.URL.RawQuery = q.Encode()
fmt.Println(req.URL.String())
req.Header.Add("Content-Type", "application/json")
if err != nil {
fmt.Printf("post failed, err:%v\n\n", err)
return
}
resp, _ := client.Do(req)
defer resp.Body.Close()
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("get resp failed,err:%v\n\n", err)
return
}
fmt.Println(string(b))
}
4.4 示例(Post请求,application/json)
func PostHttpWithJson() {
client := &http.Client{}
url := "https://harbocto.xxx.com.cn/api/v2.0/projects"
data := `{"project_name": "liubei","metadata": {"public": "true"}}`
req, err := http.NewRequest("POST", url, strings.NewReader(data))
if err != nil {
fmt.Printf("err: %v\n", err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Add("Authorization", "Basic 5YiY5aSHOuaIkeS4jeS8muWRiuivieS9oOWvhueggQ==")
resp,err := client.Do(req)
if err != nil {
fmt.Printf("err: %v\n", err)
}
fmt.Printf("执行状态为:%d",resp.StatusCode)
}
4.5 示例 (post请求,body使用定义的结构体)
type MyBody struct {
ProjectName string `json:"project_name"`
Metadata struct {
Public string `json:"public"`
} `json:"metadata"`
}
func PostHttpWithStruct() {
client := &http.Client{}
url := "https://harbocto.xxx.com.cn/api/v2.0/projects"
var s MyBody
s.ProjectName = "liubei-01"
s.Metadata.Public = "true"
js, err := json.MarshalIndent(&s, "", "\t")
fmt.Println(string(js))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(js))
if err != nil {
fmt.Printf("err: %v\n", err)
return
}
req.Header.Set("Authorization", "Basic 5YiY5aSHOuaIkeS4jeS8muWRiuivieS9oOWvhueggQ==")
req.Header.Set("Content-Type", "application/json")
resp, _ := client.Do(req)
defer resp.Body.Close()
fmt.Printf("执行状态为:%d",resp.StatusCode)
}