7 http-client开发

7 http-client开发

所谓的 http-client 开发就是需要对服务方发起请求http.Client,如何在我们的 client 上提交数据。

提交数据的几种方式

  • 通过 RUL 提交参数

  • 通过 HTTP 协议进行提交

    • GET/POST

    • HEADER

    • BODY

7.1 客户端 Get 请求方式

1.编写一个 server 端

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "time"
)

func main() {
    addr := ":8888"
    http.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
        fmt.Println("method:", r.Method)
        fmt.Println("url:", r.URL)
        fmt.Println("protocol:", r.Proto)
        fmt.Println("Body:")
        io.Copy(os.Stdout, r.Body)

        fmt.Fprintln(rw, time.Now().Format("2006-01-02 15-04-05"))
    })

    http.ListenAndServe(addr, nil)
}

执行

[11:33:14 root@go webrequest]#go run main.go 

2.编写客户端

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    // 请求本机的 http://127.0.0.1:8888/
    res, err := http.Get("http://127.0.0.1:8888/")
    if err != nil {
        fmt.Println(err)
        return
    }

    // 将请求到的服务器端 body 信息输出
    io.Copy(os.Stdout, res.Body)
}

执行客户端

[11:38:35 root@go webclient]#go run main.go 
2021-07-23 11-38-41

此时服务器端输出 客户端的请求信息

[11:33:14 root@go webrequest]#go run main.go 
method: GET                 # 请求方法
url: /                      # 请求 url
protocol: HTTP/1.1          # 请求 http 协议
Body: {}                    # 客户端 body 信息为空

但是这个时候如果我客户端需要提交参数我该怎么提交,我们都知道 GET 方法的提交参数信息是在 URL 的位置进行提交,所以我们只需要在客户端的请求 URL 中提交即可

客户端提交参数如下图

然后再次执行客户端,此时服务器端就会获取到客户端的请求信息

7.2 客户端 Head 请求方式

Head(url string) (resp *http.Response, err error)

客户端代码

package main

import (
    "io"
    "log"
    "net/http"
    "os"
    "os/exec"
)

func main() {
    
    // 通过 http.Head 传入要访问的 url 请求
    resq, err := http.Head("http://127.0.0.1:8888/?x=1&y=2")
    if err != nil {
        log.Println(err)
        return
    }

    // 终端输出
    io.Copy(os.Stdout, resq.Body)
}

服务器端还是使用上面的代码

然后执行结果,服务器端输出请求方式为 head

7.3 客户端 POST 请求方式

在 post 请求的时候有两种方式:

  1. 比较常见的 x-www-form-urlencode

  2. 自定义类型如 json 格式

7.3.1 PostForm 请求方式

PostForm(url string, data url.Values) (resp *http.Response, err error)

客户端代码:

package main

import (
    "fmt"
    "io"
    "net/http"
    "net/url"
    "os"
)

func main() {
    // 赋值 values 为 url.Values 结构体
    values := url.Values{}

    // 添加请求数据
    values.Add("x", "1")
    values.Add("x", "2")

    // 更新请求数据
    values.Set("y", "1")
    values.Set("y", "2")

    // 请求 URL http://127.0.0.1:8888/ ,请求数据 values
    resq, err := http.PostForm("http://127.0.0.1:8888/", values)
    if err != nil {
        fmt.Println(err)
        return
    }

    io.Copy(os.Stdout, resq.Body)

}

服务器端代码依旧不变,执行结果,body 拿到数据

7.3.2 JSON 格式请求

自定义类型 json 格式请求,需要使用到 Post()

func http.Post(url string, contentType string, body io.Reader) (resp *http.Response, err error)

编写 test.json 文件

{
    "a":1,
    "b":2
}

客户端代码

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
)

func main() {
    // 打开 test.json 文件
    f, _ := os.Open("test.json")

    // 将 json 文件通过 http.Post 传递给 http://127.0.0.1:8888/ contentType(内容类型为 json)
    resq, err := http.Post("http://127.0.0.1:8888/", "application/json", f)
    if err != nil {
        fmt.Println(err)
        return
    }
    io.Copy(os.Stdout, resq.Body)
}

服务器端代码不变,最终执行并解析

但是我们现在有一个问题就是,假如我们想提交一个 json 文件还需要创建一个文件并编写内容,这样是不是特别麻烦,那么我们有没有比较简单的方法来实现,比如实现了一个 read 接口,然后又在内存里面呢?其实这个问题更是一个能不能在内存中对字符串进行操作,我们都知道在 strings,bytes 两个包中有大量对字符串的操作,由此引出下面操作

package main

import (
    "fmt"
    "io"
    "net/http"
    "os"
    "strings"
)

func main() {
    // 通过 strings.NewReader 的同时直接进行写入我们的 json 对象
    // 把 reader 变量变成了类似一个的流对象
    reader := strings.NewReader(`
        {"a":"x"}
    `)

    // 将 json 文件通过 http.Post 传递给 http://127.0.0.1:8888/ contentType(内容类型为 json),传入 reader 变量
    resq, err := http.Post("http://127.0.0.1:8888/", "application/json", reader)
    if err != nil {
        fmt.Println(err)
        return
    }
    io.Copy(os.Stdout, resq.Body)
}

执行

7.4 客户端文件上传

我们需要把我文件读取到内存中

package main

import (
    "bytes"
    "fmt"
    "io"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    // 初始化一个新的 buffer 缓冲区
    buffer := bytes.NewBuffer(nil)

    // 创建一个 multipart.Writer 对象,因为再 io.Copy 中第一个参数接收的是 writer 对象
    writer := multipart.NewWriter(buffer)

    // 然后上传到服务器上的新文件名 xx.json
    filewriter, err := writer.CreateFormFile("z", "xx.json")
    if err != nil {
        fmt.Println(err)
        return
    }

    // 打开文件 test.json
    f, _ := os.Open("test.json")

    // 然后把 test.json 文件中的内容读取并写入到 filewriter 变量中,filewriter 是等会再服务器上传后的文件
    io.Copy(filewriter, f)

    // 关闭写入
    writer.Close()
    resq, err := http.Post("http://127.0.0.1:8888/", "multipart/form-data", buffer)
    if err != nil {
        fmt.Println(err)
        return
    }

    // 在终端输出请求到的 服务器端 body
    io.Copy(os.Stdout, resq.Body)
}

服务器端代码不变

通过执行从 body 信息能够观察到文件已经上传

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇