首页 Golang net/http 大坑
文章
取消

Golang net/http 大坑

事物的本身不是表面看起来那么简单

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:
    1. 如果使用我们自己的 body 类型,像上面代码那样,是需要手动设置 Content-Length 请求头的
    2. 如果使用 bytes.Buffer bytes.Reader strings.Reader 会自动设置 Content-Length 请求头的
  • 被调用服务端:
    1. 如果对Content-Length 请求头要求比较严格,那么就不进行请求的响应

2. 解决

  如上面代码所示,给手动设置 Content-Length 请求头字段即可

本文由作者按照 CC BY 4.0 进行授权