33

[GO语言] 构造带有请求体的HTTP GET

 5 years ago
source link: https://studygolang.com/articles/18871?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

前言

传统的 web 应用约定 http.GET 请求不允许携带请求体。然而现在已是 9102 年,restful style的接口逐渐流行,通常我们在查询某个资源的时候会使用 http.GET 作为请求方法,使用 json 格式的请求体作为查询条件 (举个例子,elasticsearch 的查询接口就是 http.GET,并把查询条件放在请求体里面)

使用 net/http Client

Golang 有原生的 httpclient (java 11 终于也有原生的 httpclient 了),通过以下代码可以得到:

import  "net/http"

func main() {
    client := &http.Client{}
}

我们来看看 http.Client 上都有些什么常用方法:

bVbpKpE?w=557&h=75

bVbpKpq?w=567&h=78

从 Get 方法的签名看出,http.Get 不能附带请求体,看来 Golang 的 httpclient 也没有摒弃老旧的思想呢。别急,接着往下看

深入到 Post 方法内部,有以下源码

func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) {
    req, err := NewRequest("POST", url, body)
    if err != nil {
        return nil, err
    }
    req.Header.Set("Content-Type", contentType)
    return c.Do(req)
}

不难看出,Post 方法内部是先使用 NewRequest() 构造出 http 请求,然后使用 client.Do(request) 来执行 http 请求,那么我们是否能使用 NewRequest() 构造出带有请求体的 http.GET 请求? 依照源码,我给出以下代码:

client := &http.Client{}
//构造http请求,设置GET方法和请求体
request, _ := http.NewRequest(http.MethodGet, "http://127.0.0.1:8000/test", bytes.NewReader(requestBodyBytes))
//设置Content-Type
request.Header.Set("Content-Type", "application/json")
//发送请求,获取响应
response, err := client.Do(request)
defer response.Body.Close()
//取出响应体(字节流),转成字符串打印到控制台
responseBodyBytes, err := ioutil.ReadAll(response.Body)
fmt.Println("response:", string(responseBodyBytes))

实践结果也是正确的,使用 NewRequest() 确实可以构造附带请求体的 http.GET 请求 (Golang 并没有拒绝这样的构造),只是 net/http 并没有对外暴露相应的 Get 方法


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK