背景
curl --location 'http://127.0.0.1:5555/album/enjoy/list' \
--header 'content-type: application/json' \
--header 'Authorization: Basic ZHJlYW1lX2FwcHYxOkFQXmR2QHpAU1FZVnhOODg=' \
--header 'Tenant-Id: 000000' \
--header 'Dreame-Auth: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiJ6UTQwMTMxOTA4IiwiVXNlck5hbWUiOiIiLCJOaWNrTmFtZSI6IiIsIkVtYWlsIjoid2FuZ2t1bkBkcmVhbWUudGVjaCIsIkJ1ZmZlclRpbWUiOjg2NDAwLCJpc3MiOiJxbVBsdXMiLCJhdWQiOlsiR1ZBIl0sImV4cCI6MTcyMjgyMzkyMCwibmJmIjoxNzIyMjE5MTIwfQ.QxeLdiO2RDHKTaE8SuVG0zAj2yCPFplqJwMpd0F4mdE' \
--header 'Dreame-RLC: HICzcGYiZncM7QQKlxynIoLYEsIXq23r' \
--header 'Plan: B' \
--header 'dreame-api-sign: 981ccb65923b38ec2a93e6cdd344d38b' \
--header 'dreame-api-timestamp: 1722231686659' \
--header 'content-length: 102' \
--data '{"ids":[6579],"report_status":2,"timestamp":"1722231686660","sign":"f09d2a383b9781e15274bdeddc47ceea"
}'
if c.Request.Body != nil {bodyBytes, _ := io.ReadAll(c.Request.Body)defer c.Request.Body.Close()if len(bodyBytes) > 0 {//err := json.Unmarshal(bodyBytes, &formParams)d := json.NewDecoder(bytes.NewReader([]byte(bodyBytes)))d.UseNumber()err := d.Decode(&formParams)if err != nil {return "", err}}// 创建新的reader,使用bytes.NewReader// 恢复r.Body,以便可以多次读取r.Body = io.NopCloser(bytes.NewReader(bodyBytes))}
程序中有个地方需要读取body内容,打印bodyBytes的内容总是少了一截。接口还返回了unexpected EOF这个错误。之前遇到这个错误都是因为传参不是个json格式,用json在线工具验证了一下,是个正确的json格式。
问题定位
查了一下,程序中没有其他的地方执行了io.ReadAll(c.Request.Body)这个方法的地方,也不存在并发读取的情况。我把这个请求体拷贝到我的另一个程序中,没有出现读取出来的body内容被截断的情形。
这种情况可以说明传参是没有问题的,问题还是出在http底层获取body的地方。
把这个有问题的请求和调用我程序的请求对比,发现了一个不一样的地方,有问题的请求中多了一个头文件:content-length。
于是乎怀疑是这个头文件导致的。把这个头文件去掉,果然问题得以解决。
到net/http的源码中找了半天,没有找到这个逻辑。后续有时间再来寻找这个逻辑。
问题原因
确保HTTP请求头中的Content-Length
字段正确反映了请求体的长度。如果Content-Length
不正确,服务器可能无法读取完整的请求体。