起因

同事请求第三方接口,需要传送的header需要区分大小写。如:
2022-10-19T02:12:49.png

然而第三方说接收到的header全部变成小写了,签名验证不通过。。。

于是找遍了各种有可能导致异常的情况,最后发现是请求协议的问题。如果不指定协议,双方连接会默认使用双方都支持的最高协议进行数据传输。

http1.* http/2 header区别

2022-10-19T02:19:54.png

从上文可知,HTTP/2 和 HTTP/1.x 同样使用 ASCII 字符集,但 HTTP/2 头部必须使用小写,而不像 HTTP/1.x 大小写均可。也正是碰上终端业务代码实现不严谨,引发上述问题。

解决方法

由于go http请求如果不指定http.Transport,默认会检测服务端是否支持http2,如果支持的话会使用http2,所以请求的header会全部转为小写,导致了这个问题。
2022-10-19T02:23:42.png

最后验证问题:

header := make(http.Header)
header[`accessToken`] = []string{"test"}

request, err := http.NewRequest("GET", "https://nghttp2.org", nil)
if err != nil {
    panic(err)
}

//关键代码,如果没有这个设置,默认走的时候http2,有的话会走http1.1
tr := &http.Transport{
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}

request.Header = make(http.Header)
request.Header = header
request.Header.Set("Content-Type", "application/json;charset=UTF-8") //添加请求头

client := http.Client{
    Timeout:   time.Second * 10,
    Transport: tr,
}
//创建客户端
resp, err := client.Do(request.WithContext(context.TODO())) //发送请求
if resp == nil && err != nil {
    panic(err)
}

//_, _ := ioutil.ReadAll(resp.Body)
fmt.Println("====", resp.Proto)