使用Go语言构建HTTP服务并通过gzip压缩传输数据
发表时间: 2024-05-16 11:45
当我们用http发送消息时, 如果消息内容过多, 可以指定为gzip压缩, 对数据进行压缩后再传输不仅可以节省带宽还可以加快传输速度, 对于双方而言都是一件能够取得更大收益的事情。
一般情况下客户端发送的http请求不需要进行压缩, 服务端返回的数据会进行压缩。
我们使用标准库中的 compress/gzip 包来进行 gzip 压缩解压操作。请求时需要设置 Accept-Encoding:gzip 请求头, 响应时候需要根据响应头中是否包含 Content-Encoding:gzip 来判断是否需要进行解压操作。
服务端代码如下:
service.go
package mainimport ( "bytes" "compress/gzip" "encoding/json" "fmt" "io/ioutil" "net/http")type Response struct { Code string `json:"code"` Data string `json:"data"`}func handler(resp http.ResponseWriter, req *http.Request) { body, err := gzip.NewReader(req.Body) if err != nil { fmt.Println("unzip is failed, err:", err) } defer body.Close() data, err := ioutil.ReadAll(body) if err != nil { fmt.Println("read all is failed, err:", err) } fmt.Println("req data:", string(data)) response := &Response{ Code: "0", Data: "success", } data, err = json.Marshal(response) if err != nil { fmt.Println("marshal response msg is failed, err: ", err) } resp.Header().Set("Content-Encoding", "gzip") var zBuf bytes.Buffer zw := gzip.NewWriter(&zBuf) if _, err = zw.Write(data); err != nil { fmt.Println("gzip is faild,err:", err) } zw.Close() resp.Write(zBuf.Bytes())}func main() { http.HandleFunc("/request", handler) http.ListenAndServe(":9903", nil)}
客户端代码如下:
client.go
package mainimport ( "bytes" "compress/gzip" "encoding/json" "fmt" "io/ioutil" "net/http")type Request struct { ID int `json:"id"` Data string `json:"data"`}func main() { m := &Request{ ID: 5, Data: "hello world", } data, err := json.Marshal(m) if err != nil { fmt.Println("marshal is faild,err: ", err) } var zBuf bytes.Buffer zw := gzip.NewWriter(&zBuf) if _, err = zw.Write(data); err != nil { fmt.Println("gzip is faild,err:", err) } zw.Close() fmt.Println("req: ", string(data)) httpRequest, err := http.NewRequest("POST", "http://localhost:9903/request", &zBuf) if err != nil { fmt.Println("http request is failed, err: ", err) } httpRequest.Header.Set("Accept-Encoding", "gzip") client := http.Client{} httpResponse, err := client.Do(httpRequest) if err != nil { fmt.Println("httpResponse is failed, err: ", err) } defer httpResponse.Body.Close() body := httpResponse.Body if httpResponse.Header.Get("Content-Encoding") == "gzip" { body, err = gzip.NewReader(httpResponse.Body) if err != nil { fmt.Println("http resp unzip is failed,err: ", err) } } data, err = ioutil.ReadAll(body) if err != nil { fmt.Println("read resp is failed, err: ", err) } fmt.Println("data=", string(data))}
D:\work\src>go run service.goreq data: {"id":5,"data":"hello world"}
D:\work\src>go run client.goreq: {"id":5,"data":"hello world"}data= {"code":"0","data":"success"}