【golang】当post https请求时,遇见301

今天遇到个奇葩问题,一直在使用的通知接口突然报错了

背景

我们提供了一个 post 通知接口(http://example.com/notify)突然失效了,导致三方发货失败,我们这边是java服务,三方是golang服务

我这边查了半天服务器日志,最后查到该请求报错是:Request method 'GET' not supported,很奇怪,为什么变成了 GET 请求;

为啥查了半天日志,因为这帮开发不知道为啥老喜欢把日志级别改成 INFO ,众所周知,spring-webmvc 只会在 DEBUG 级别打印请求信息,
就导致我看不到测试的请求,改成 DEBUG 之后才看到报错信息

虽然全局异常已经打印 GlobalBizExceptionHandler : Request method 'GET' not supported,但是鬼知道是谁的请求导致的

当跑到三方后台去调试接口的时候,发现填写的通知链接是:http://example.com/notify

由于前几天运维把公司全部域名都加上了重定向配置,那就先改成https 再试一把,果然成功了;

但是,为什么 POST 请求会变成 GET 请求?

当时想了很多可能引发的原因,但是首先还是从三方的golang服务来推测,golang 中请求接口用的是net/http,不管3721,直接去google一番,
果然查到相似问题 Why do POST request in the Go http.Client not follow 301 redirects?

文中提到 it seems like GET requests follow 301 redirects, but not POST requests: http://golang.org/src/net/http/client.go
似乎 GET 请求才能正常 301 重定向,而 POST 请求不会,还引导我们去看 net/http/client 源码:

/usr/local/Cellar/go@1.13/1.13.15/libexec/src/net/http/client.go:433

1
2
3
4
5
6
7
8
9
10
11
12
case 301, 302, 303:
redirectMethod = reqMethod
shouldRedirect = true
includeBody = false

// RFC 2616 allowed automatic redirection only with GET and
// HEAD requests. RFC 7231 lifts this restriction, but we still
// restrict other methods to GET to maintain compatibility.
// See Issue 18570.
if reqMethod != "GET" && reqMethod != "HEAD" {
redirectMethod = "GET"
}

这段代码意思即:当碰到 301, 302, 303 状态码,同时请求不是 GET, HEAD 方法时,强制把重定向请求的方法改成了 GET,到这里算是真相大白了!

同时,如果对这段代码感兴趣的话,也可以读读clientnet/http/client.go:393Get方法的注释

最后

  • 运维层修改配置,一定要确保通知到开发侧,否则找问题要费很大劲
  • 像日志级别配置这种看似没技术含量的东西,没有经验的开发人员不要去管它,直接设置DEBUG级别即可,不要过多考虑服务器硬盘不够这种小问题

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注