Go HTTP GET 请求可以发送 body 吗

大家好,我是煎鱼。

前段时间遇到一个朋友,他跟我说他们在开发一个 Go 项目时,遇到了一个争议点,说来也好理解。WEB UI 端选择 GET、POST 类型时,程序是否要区分所传递的值(例如:Body),还是不管是什么类型都传。

一派认为无所谓,反正都能传。又没限制。

一派认为规范如此,不应该传。应该针对 HTTP POST 类型,使用 POST 请求的 body 来传递参数。在 GET 请求里使用 URI 来进行参数传递。

看着似乎都有各自的道理,僵持不下。

RFC7231 怎么说

要看互联网协议的相关标准,必然是 RFC 了。首先看看 RFC7231 中的 4.3.1 小节是怎么说的。

如下摘抄:

A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.

大概意思:在 GET 类型的请求里使用 body 是一个没有定义的语义。如果在 GET 请求的 body 里传递参数可能会被某些实现方拒绝该请求。

也就是这个混着传的行为并不符合 RFC 规范,至少官方是不推荐不鼓励这样的使用方式。但并没有禁止这个行为。

记住这个结论。接下来我们进行测试。

程序支持程度

我们起一个 HTTP Sever 用于测试和验证,看看在具体的编程语言的实现中师傅可以支持。

如下 Go 代码:

go 复制代码
func hello(w http.ResponseWriter, req *http.Request) {
	b, _ := io.ReadAll(req.Body)
	w.Write(b)
}

func main() {
	http.HandleFunc("/hello_world", hello)
	http.ListenAndServe(":7001", nil)
}

在命令行执行 CURL 进行测试:

shell 复制代码
$ curl -X GET localhost:7001/hello_world -d '煎鱼'
煎鱼

看来在 Go 里面是可以的。

那既然 RFC 没有禁止,Go 的测试也正常。看来就是只是口头上的 "不鼓励" 和 "不推荐" 吗?

那别的场景也都支持吗?

实际上也不是,例如:XMLHttpRequest 规范 中有明确提到:

如果请求方法为 GET 或 HEAD,body 参数会被忽略。

总结

在 GET 类型里传 body 参数,从 RFC7231 标准来定义。官方是不推荐、不鼓励这么去使用的。

但是呢,这是一个没有明确禁止的事。

而从各个 HTTP 实现的客户端来看,一开始还是有不少不支持的。但掰扯了好多年后,大多数都支持了。(毕竟用户的诉求也是很重要的)

甚至印象最深的,ES 直接就在 GET 请求里传了 body:

对应的 CURL:

curl 复制代码
curl -X GET "localhost:9200/my-index-000001/_search?from=40&size=20&pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "term": {
      "user.id": "kimchy"
    }
  }
}
'

但也有不支持的,例如在 Chrome 浏览器下测试 XMLHttpRequest、Fetch 对此都会忽略或出现报错。

结论上来讲,GET 请求能不能传 body,这是一个 RFC 规范不鼓励。但是实现方大部分都支持的一个情况。

企业和团队内部的话,建议达成研发规范的共识即可。不过我个人而言,都会区分开。

文章持续更新,可以微信搜【脑子进煎鱼了】阅读,本文 GitHub github.com/eddycjy/blo... 已收录,学习 Go 语言可以看 Go 学习地图和路线,欢迎 Star 催更。

推荐阅读

相关推荐
煎鱼eddycjy3 小时前
新提案:由迭代器启发的 Go 错误函数处理
go
煎鱼eddycjy3 小时前
Go 语言十五周年!权力交接、回顾与展望
go
不爱说话郭德纲20 小时前
聚焦 Go 语言框架,探索创新实践过程
go·编程语言
0x派大星2 天前
【Golang】——Gin 框架中的 API 请求处理与 JSON 数据绑定
开发语言·后端·golang·go·json·gin
IT书架2 天前
golang高频面试真题
面试·go
郝同学的测开笔记2 天前
云原生探索系列(十四):Go 语言panic、defer以及recover函数
后端·云原生·go
秋落风声3 天前
【滑动窗口入门篇】
java·算法·leetcode·go·哈希表
0x派大星5 天前
【Golang】——Gin 框架中的模板渲染详解
开发语言·后端·golang·go·gin
0x派大星5 天前
【Golang】——Gin 框架中的表单处理与数据绑定
开发语言·后端·golang·go·gin
三里清风_6 天前
如何使用Casbin设计后台权限管理系统
golang·go·casbin