为了账号安全,请及时绑定邮箱和手机立即绑定

没有为具有空/无负载的 PATCH 请求设置 Content-Length 标头 - GoLang

没有为具有空/无负载的 PATCH 请求设置 Content-Length 标头 - GoLang

Go
沧海一幻觉 2022-06-27 10:42:55
我观察到 Content-Length 标头没有为具有空/nil 有效负载的 PATCH 请求设置。即使我们手动设置它,req.Header.Set("content-length", "0")它实际上并没有在发出的请求中设置。这种奇怪的行为(Go bug?)仅发生在 PATCH 请求中,并且仅在有效负载为空或 nil(或设置为 http.NoBody)时发生package mainimport (    "fmt"    "io/ioutil"    "net/http"    "strings")func main() {    url := "http://localhost:9999"    method := "PATCH"    payload := strings.NewReader("")    client := &http.Client {    }    req, err := http.NewRequest(method, url, payload)    if err != nil {        fmt.Println(err)    }    req.Header.Set("Authorization", "Bearer my-token")    req.Header.Set("Content-Length", "0") //this is not honoured    res, err := client.Do(req)    defer res.Body.Close()    body, err := ioutil.ReadAll(res.Body)    fmt.Println(string(body))}即使在最新的 go 版本中,这也是可重现的1.15。只需在一个简单的 http 服务器上运行上面的代码,然后自己看看。是否有任何解决方案/解决方法可以发送 Content-Length 设置为 0 的 PATCH 请求?
查看完整描述

1 回答

?
慕姐8265434

TA贡献1813条经验 获得超2个赞

您可以通过将 TransferEncoding 设置为如下方式来告诉 HTTP 客户端包含Content-Length值为 0 的标头:identity


  url := "http://localhost:9999"

  method := "PATCH"

  

  client := &http.Client{}

  req, err := http.NewRequest(method, url, http.NoBody)

  if err != nil {

    panic(err)

  } 


  req.TransferEncoding = []string{"identity"} 

  req.Header.Set("Authorization", "Bearer my-token")

  //  req.Header.Set("Content-Length", "0")

请注意对原始代码的以下更改:

  • 重要的是req.TransferEncoding = []string{"identity"}

  • 指定空主体的惯用方式:(http.NoBody对发送长度没有影响)

  • 注释掉req.Header.Set("Content-Length", "0"),客户自己填写

  • 也更改为出现错误时恐慌,您可能不想继续

的传输编码identity没有写入请求,所以除了 header 之外Content-Length = 0请求看起来和以前一样。

不幸的是,这没有记录(请随时向 Go 团队提出问题),但可以在以下代码中看到:

繁琐的细节

transferWriter.writeHeader检查以下内容以写入Content-Length标头:

    // Write Content-Length and/or Transfer-Encoding whose values are a

    // function of the sanitized field triple (Body, ContentLength,

    // TransferEncoding)

    if t.shouldSendContentLength() {

        if _, err := io.WriteString(w, "Content-Length: "); err != nil {

            return err

        }

        if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {

            return err

        }

反过来,shouldCheckContentLength在长度为零的情况下查看传输编码:


    if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {

        if t.Method == "GET" || t.Method == "HEAD" {

            return false

        }

        return true

    }

isIdentity验证这TransferEncoding正是:_ []string{"identity"}


func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }) 


查看完整回答
反对 回复 2022-06-27
  • 1 回答
  • 0 关注
  • 151 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号