使用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"}