Golang中net/http包POST请求的content-length与body长度不符问题
Golang中net/http包POST请求的content-length与body长度不符问题
我正在使用 net/http 模块向一个网站发送 POST 请求。通常它工作正常,但有时我会收到以下错误信息:
Post "<URL>": http: ContentLength=47 with Body length 0
这是服务器的问题还是我的代码问题?
3 回复
我们既不了解服务器,也不了解你的代码。因此很难说……
更多关于Golang中net/http包POST请求的content-length与body长度不符问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
深入研究标准库源代码,错误是在这里创建的。 如果需要,我可以分享我的代码,但我想问的是,是否存在一个已知的(或许是常见的)条件/原因会触发(即返回)这个错误?
这是你的代码问题。这个错误表明你设置了 Content-Length 头为 47,但实际请求体长度为 0,两者不匹配。
最常见的原因是你在创建请求后修改了请求体,但没有更新 Content-Length 头,或者请求体在发送前被意外清空。
问题示例
package main
import (
"bytes"
"net/http"
)
func main() {
// 创建请求体
body := bytes.NewBufferString("example request body data")
// 创建请求
req, err := http.NewRequest("POST", "https://example.com", body)
if err != nil {
panic(err)
}
// 错误:修改请求体但没有更新 Content-Length
req.Body = bytes.NewBufferString("shorter") // 新body长度只有7字节
// 此时 Content-Length 仍然是原body的长度,导致不匹配
client := &http.Client{}
resp, err := client.Do(req) // 这里可能报错
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
正确做法
方法1:让 http 包自动处理
package main
import (
"bytes"
"net/http"
)
func main() {
// 直接使用 http.Post
body := bytes.NewBufferString("example request body data")
resp, err := http.Post("https://example.com", "application/json", body)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// 或者使用 http.NewRequest 但不手动设置 Content-Length
req, err := http.NewRequest("POST", "https://example.com", body)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err = client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
方法2:需要修改请求体时重新创建请求
package main
import (
"bytes"
"net/http"
)
func main() {
// 如果需要不同的请求体,重新创建请求
newBody := bytes.NewBufferString("new body content")
req, err := http.NewRequest("POST", "https://example.com", newBody)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
方法3:使用 io.ReadSeeker 类型的请求体
package main
import (
"bytes"
"net/http"
)
func main() {
// bytes.Reader 实现了 io.ReadSeeker
body := bytes.NewReader([]byte("request body data"))
req, err := http.NewRequest("POST", "https://example.com", body)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
}
调试建议
检查你的代码中是否有以下情况:
- 在创建请求后重新赋值
req.Body - 手动设置了
Content-Length头 - 请求体被多次读取
- 使用了不可重读的请求体(如
bytes.Buffer被读取后)
使用 http.NewRequest 时,如果请求体实现了 Len() 方法,net/http 包会自动计算并设置正确的 Content-Length。如果请求体被修改或替换,这个长度就会失效。

