转到Web服务 - POST tar.gz文件作为请求正文

时间:2016-06-21 05:30:33

标签: rest go gzip

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

另外,我发现很多东西都是自动处理的 - 在客户端我只是发布了一个gzip阅读器作为请求体,Accept-Encoding: gzip标题是自动添加的,而在服务器端 - 我不需要枪杀请求体,它已被提取到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)
    }
}

2 个答案:

答案 0 :(得分:1)

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

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

如果您直接发送了.tar.gz文件内容,那么 需要在服务器上进行gunzip。 E.g:

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

我认为这更接近您应该期望第三方客户展示的行为。

答案 1 :(得分:0)

克莱尔没有,但也许......

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

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

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

请注意,Content-Type描述了您要发送的数据类型(此处为tar.gz但可以是application/jsontest/javascript,...),{{1}描述了为传输

编码数据的方式

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