golang 使用net/http的client请求数据


通常我们直接通过 client 向 http server 发送请求时,需要注意几点:

  • 1.请求方法,GET 还是 POST 还是有不同的,POST 需要携带 请求体数据,另外两者共性的是,在请求首部处需要指定对应字段
  • 2.如果是复杂点的请求,建议还是通过 http.Client 执行,而不通过 http.Get()/http.Post() 发送请求
  • 3.请求的 server 需要注意是否是 明文、加密 的

1.简单请求

1.1 Get请求

对于这种简单请求,通常我们不用关心 content-type 传输格式是明文还是加密,直接通过 http.Get() 发送请求就可以了,下面是代码示例。

func TestSimpleGetClient(t *testing.T) {
resp, _ := http.Get("http://172.22.22.22:8000/api/v1/task/info")
body := resp.Body
bodyBytes, _ := io.ReadAll(body)
// print resp body
fmt.Printf("%s", bodyBytes)
// unmarshal to app
var m map[string]interface{}
_ = json.Unmarshal(bodyBytes, &m)
fmt.Printf("m: %v", m)
}

http.Get()

func Get(url string) (resp *Response, err error) {
return DefaultClient.Get(url)
}
var DefaultClient = &Client{}

可以看出,该方法实际也是基于一个预先设定的默认 client 发送 Get 请求, 传入一个 url 就可以了。

1.2 POST请求

参照 Get 简单请求,此处主要需注意按照传入参数要求给定,下面是示例。

func TestSimplePostClient(t *testing.T) {
body := map[string]string{
"key": "value",
}
bodyBytes, _ := json.Marshal(body)
reqBody := bytes.NewReader(bodyBytes)
resp, _ := http.Post("http://172.22.22.22:8000/api/v1/task/info", "application/json", reqBody)
// read resp body
respBody, _ := io.ReadAll(resp.Body)
// 通常响应都是json格式,所以需要转回结构体或map
var m map[string]interface{}
_ = json.Unmarshal(respBody, &m)
// 使用map
fmt.Printf("m: %v", m)
}

http.Post()

func Post(url, contentType string, body io.Reader) (resp *Response, err error) {
return DefaultClient.Post(url, contentType, body)
}
// DefaultClient is the default Client and is used by Get, Head, and Post.
var DefaultClient = &Client{}

request body 的转换
只要实现了 io.Reader 接口 的都可以

// io包
// Implementations must not retain p.
type Reader interface {
Read(p []byte) (n int, err error)
}

所以我们的 request body 应该通过实现了 Reader 接口的传入,我们常用的有以下:

  • bytes
  • buffers
  • strings
  • jsonReader

比如我们有这样一个构建的 map 结构的请求体:

body := map[string]string{
"key": "value",
}

上述的这些实现 Reader 接口的有如下方法:

jsonBody, _ := json.Marshal(body)
// 1.bytes
bytesReader := bytes.NewReader(jsonBody)
// 2.strings
stringsReader := strings.NewReader(string(jsonBody))
// 3.buffers
bufferIns := bytes.NewBuffer(make([]byte, 1024))
bufferIns.Read(jsonBody)

2.复杂请求-用 http.Client

上面的主要针对一些简单的 http 请求,如果是更复杂的请求,如我们需要指定更多的请求首部等信息,这里就需要用到自己创建的 Client 实例,下面看看示例。

2.1 Get请求

func TestGetClient(t *testing.T) {
// 1.create client instance
myClient := http.Client{}
// 2.build request
// 2.1 Get req
getReq, _ := http.NewRequest(http.MethodGet, "http://172.22.22.22:8000/api/v1/task/info", nil)
// build headers
headers := map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", "12345678"),
"Content-Type": "application/json",
}
// add to req
for k, v := range headers {
getReq.Header.Set(k, v)
}
// 3.client exec req
resp, _ := myClient.Do(getReq)
// read resp body
respBody, _ := io.ReadAll(resp.Body)
// 通常响应都是json格式,所以需要转回结构体或map
var m map[string]interface{}
_ = json.Unmarshal(respBody, &m)
// 使用map
fmt.Printf("m: %v", m)
}

2.2 Post请求

func TestPostClient(t *testing.T) {
// 1.create client instance
myClient := http.Client{}
// 2.build request
// 2.2 Post req
// build body
body := map[string]string{
"key": "value",
}
bodyBytes, _ := json.Marshal(body)
reqBody := bytes.NewReader(bodyBytes)
postReq, _ := http.NewRequest(http.MethodPost, "http://172.22.22.22:8000/api/v1/task/info", reqBody)
// build headers
headers := map[string]string{
"Authorization": fmt.Sprintf("Bearer %s", "12345678"),
"Content-Type": "application/json",
}
// add to req
for k, v := range headers {
postReq.Header.Set(k, v)
}
// 3.client exec req
resp, _ := myClient.Do(postReq)
// read resp body
respBody, _ := io.ReadAll(resp.Body)
// 通常响应都是json格式,所以需要转回结构体或map
var m map[string]interface{}
_ = json.Unmarshal(respBody, &m)
// 使用map
fmt.Printf("m: %v", m)
}

3.加密请求

如果发送 https,显然上面已经不满足需求了,这时需要注意在 client 实例中指定 transport。

func TestHttpsClient(t *testing.T) {
// 1.create client
myCLient := http.Client{
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
CheckRedirect: nil,
Jar: nil,
Timeout: time.Second * 10,
}
// 2.这里仅发送简单请求, 如复杂请求请先构建 request
resp, _ := myCLient.Get("http://172.22.22.22:8000/api/v1/task/info")
body := resp.Body
bodyBytes, _ := io.ReadAll(body)
// print resp body
fmt.Printf("%s", bodyBytes)
// unmarshal to app
var m map[string]interface{}
_ = json.Unmarshal(bodyBytes, &m)
fmt.Printf("m: %v", m)
}

4.multiPart示例 & postForm示例

参考:

multiPart

func newfileUploadRequest(uri string, params map[string]string, paramName, path string) (*http.Request, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
body := &bytes.Buffer{}
writer := multipart.NewWriter(body)
part, err := writer.CreateFormFile(paramName, path)
if err != nil {
return nil, err
}
_, err = io.Copy(part, file)
for key, val := range params {
_ = writer.WriteField(key, val)
}
err = writer.Close()
if err != nil {
return nil, err
}
request, err := http.NewRequest("POST", uri, body)
request.Header.Set("Content-Type", writer.FormDataContentType())
return request, err
}

http.PostForm

func httpPostForm() {
resp, err := http.PostForm("http://www.01happy.com/demo/accept.php",
url.Values{"key": {"Value"}, "id": {"123"}})
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
// handle error
}
fmt.Println(string(body))
}

更多示例:

client 简单 POST 请求

func main() {
reqBody, _ := json.Marshal(map[string]string{"key1": "val1", "key2": "val2"})
resp, _ := http.Post(":8091", "application/json", bytes.NewReader(reqBody))
defer resp.Body.Close()
respBody, _ := io.ReadAll(resp.Body)
fmt.Printf("resp: %s", respBody)
}

代码:

package main
import (
"bytes"
"crypto/sha256"
"crypto/tls"
"encoding/base64"
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/http"
"sync"
"time"
)
func main() {
sessionID, _ := checkIn()
fmt.Println("sessionID:", sessionID)
if sessionID != "" {
getArsModels(sessionID)
}
}
var (
username = "admin"
deviceID = "22241dc1-a7fc-d69e-5467-xxxxxxxxxxxx"
baseURL = "https://xxx:xxx"
v1URL = "/xxx/v1/"
sessionURL = baseURL + v1URL + "sessions"
arsModelsURL = baseURL + v1URL + fmt.Sprintf("devices/%s/xxx/xrs", deviceID)
)
var (
once sync.Once
client *http.Client
)
func init() {
getHttpClient()
}
func getHttpClient() *http.Client {
once.Do(func() {
client = &http.Client{
// 跳过证书验证
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
})
return client
}
// Get
func getArsModels(sessionID string) {
headers := map[string]string{
"Content-Type": "application/json",
"Accept-Type": "application/json",
"User-Agent": "QKAct-External-Client",
"Authorization": fmt.Sprintf("basic %s", (base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("client:%s", sessionID))))),
}
req, err := http.NewRequest(http.MethodGet, arsModelsURL, nil)
if err != nil {
panic(err)
}
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
respBody, err := ioutil.ReadAll(resp.Body)
var respParsed map[string]interface{}
json.Unmarshal(respBody, &respParsed)
fmt.Printf("resp: %s\n", respBody)
}
// Post
func checkIn() (sessionID string, err error) {
headers := map[string]string{
"Content-Type": "application/json", // 如果是post请求,需指定content-type
"Accept-Type": "application/json",
"User-Agent": "QKAct-External-Client",
}
now := time.Now().Unix()
password := fmt.Sprintf("%x", sha256.Sum256([]byte(username)))
combineString := fmt.Sprintf("%s%d%s", username, now, password)
hashString := fmt.Sprintf("%x", sha256.Sum256([]byte(combineString)))
hashPwd := base64.StdEncoding.EncodeToString([]byte(hashString))[:12]
body := map[string]string{
"username": username,
"timestamp": fmt.Sprintf("%d", now),
"passwordHash": hashPwd,
"deviceType": "1",
"connectionType": "0",
}
var reqBodyRd io.Reader
reqBody, _ := json.Marshal(body)
reqBodyRd = bytes.NewReader(reqBody)
req, _ := http.NewRequest(http.MethodPost, sessionURL, reqBodyRd)
for k, v := range headers {
req.Header.Set(k, v)
}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
respBody, err := ioutil.ReadAll(resp.Body)
var respParsed map[string]interface{}
json.Unmarshal(respBody, &respParsed)
fmt.Printf("resp: %v\n", respParsed)
for k, v := range respParsed {
if k == "sessionID" {
return v.(string), nil
}
}
return "", nil
}

posted on   进击的davis  阅读(337)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
历史上的今天:
2021-03-01 linux的目录系统
2021-03-01 docker容器之实现 nat 转换收发

导航

< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5
点击右上角即可分享
微信分享提示