事物的本身不是表面看起来那么简单
1. 问题来源
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main
import (
"bytes"
"crypto/tls"
"io"
"net/http"
"time"
)
type myReader struct {
*bytes.Buffer
}
func main() {
c := http.Client{
Timeout: time.Second,
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
}
req, err := http.NewRequest("GET", "https://192.168.0.181:8834", &myReader{Buffer: bytes.NewBuffer([]byte("{}"))})
//req.ContentLength = 2
//req, err := http.NewRequest("GET", "https://192.168.0.181:8834", bytes.NewBuffer([]byte("{}")))
if err != nil {
panic(err)
}
resp, err := c.Do(req)
if err != nil {
panic(err)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
println(string(data))
}
事情的起因是这样的,由于我们的一些底层服务,需要基于golang
进行重写,那么有部分对外部的http
调用我们,我们打算构建自己的body
类型
,通过 代码 http.NewRequest
而至,我们如果想实现自己的 body
需要实现 io.Reader
接口
如上所示, 我们的的确确这么干了!但是在测试的过程中发现,请求老是超时,最开始我们怀疑是第三方服务器问题。 经过好几个小时的排查我们发现问题有几个地方:
Content-Length
:- 如果使用我们自己的
body
类型,像上面代码那样,是需要手动设置Content-Length
请求头的 - 如果使用
bytes.Buffer
bytes.Reader
strings.Reader
会自动设置Content-Length
请求头的
- 如果使用我们自己的
- 被调用服务端:
- 如果对
Content-Length
请求头要求比较严格,那么就不进行请求的响应
- 如果对
2. 解决
如上面代码所示,给手动设置 Content-Length
请求头字段即可