转到网络服务 - POST tar.gz 文件作为请求 body

Go web service - POST tar.gz file as request body

我需要在处理 tar.gz 文件的 go 中实现 Web 服务,我想知道什么是正确的方法,我需要定义什么内容类型等。

此外,我发现很多事情都是自动处理的 - 在客户端,我只是 post gzip reader 作为请求 body 和 Accept-Encoding: gzip header 是自动添加的,在服务器端 - 我不需要 gunzip 请求 body,它已经解压缩到 tar。那有意义吗?

我可以相信任何客户都会这样吗?

服务器:

func main() {

    router := mux.NewRouter().StrictSlash(true)
    router.Handle("/results", dataupload.NewUploadHandler()).Methods("POST")
    log.Fatal(http.ListenAndServe(*address, router))
}

上传者:

package dataupload

import (
    "errors"
    log "github.com/Sirupsen/logrus"
    "io"
    "net/http"
)

// UploadHandler responds to /results http request, which is the result-service rest API for uploading results
type UploadHandler struct {
    uploader Uploader
}

// NewUploadHandler creates UploadHandler instance
func NewUploadHandler() *UploadHandler {

    return &UploadHandler{
        uploader: TarUploader{},
    }
}

func (uh UploadHandler) ServeHTTP(writer http.ResponseWriter, request *http.Request) {

    retStatus := http.StatusOK
    body, err := getBody(request)
    if err != nil {
        retStatus = http.StatusBadRequest
        log.Error("Error fetching request body. ", err)
    } else {
        _, err := uh.uploader.Upload(body)
    }
    writer.WriteHeader(retStatus)
}

func getBody(request *http.Request) (io.ReadCloser, error) {

    requestBody := request.Body
    if requestBody == nil {
        return nil, errors.New("Empty request body")
    }
    var err error
    // this part is commented out since somehow the body is already gunzipped - no need to extract it.
    /*if strings.Contains(request.Header.Get("Accept-Encoding"), "gzip") {
        requestBody, err = gzip.NewReader(requestBody)
    }*/

    return requestBody, err
}

客户端

func main() {

    f, err := os.Open("test.tar.gz")
    if err != nil {
        log.Fatalf("error openning file %s", err)
    }
    defer f.Close()
    client := new(http.Client)
    reader, err := gzip.NewReader(f)
    if err != nil {
        log.Fatalf("error gzip file %s", err)
    }
    request, err := http.NewRequest("POST", "http://localhost:8080/results", reader)
    _, err = client.Do(request)
    if err != nil {
        log.Fatalf("error uploading file %s", err)
    }
}

显然不是,但也许...

Golang 为http 客户端(和服务器)提供了很好的支持。这是第一种支持 http2 的语言,API 的设计清楚地表明了他们对快速 http 的关注。

这就是他们自动添加 Accept-Econding: gzip 的原因。这将大大减少服务器响应的大小,然后优化传输。

但 gzip 仍然是 http 1 中的一个选项,并非所有客户端都会将此 header 推送到您的服务器。

请注意,Content-Type 描述了您要发送的数据类型(这里是 tar.gz,但也可能是 application/jsontest/javascript、...),当Accept-Encoding 描述了传输数据的编码方式

Go 会为你透明地处理 Accept-Encoding 因为它负责数据的传输。然后由您来处理 Content-Type 因为只有您知道如何理解您收到的内容

您为客户端编写的代码只是直接发送 tarfile,因为这段代码:

reader, err := gzip.NewReader(f)
...
request, err := http.NewRequest("POST", "http://localhost:8080/results", reader)

如果您直接发送 .tar.gz 文件内容,那么您 需要将其压缩到服务器上。例如:

request, err := http.NewRequest(..., f)

我认为这更接近您期望第三方客户端表现出的行为。