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

问题描述

我观察到没有为有效载荷为空/无的PATCH请求设置Content-Length标头。即使我们通过req.Header.Set("content-length","0")手动设置它,实际上也不在外发请求中设置它。 仅当PATCH请求且仅当有效载荷为空或为零(或设置为http.NoBody)时才会发生这种奇怪的行为(Go bug?)

package main

import (
    "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请求?

解决方法

您可以通过将TransferEncoding设置为Content-Length来告诉HTTP客户端包括值为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的传输编码未写入请求,因此,除了标头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 _,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" }) 

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...