最近在学习Gin,今天在测试接受Post数据时,相当然的以为服务端使用PostForm就能接收数据,结果发现怎么也接收不到,看来还是太naive了。使用开发者工具查看显示的是Request Payload,不是通常表单提交时显示的Request Payload,这就有意思了,进入了知识盲区。

image-20200526184720690

谷歌找到了这个贴子:whats-the-difference-between-request-payload-vs-form-data-as-seen-in-chrome,高票答案中详细解释了它俩的区别。

Request Payload更准确的说是http request的payload body。一般用在数据通过POST请求或者PUT请求。它是HTTP请求中*空行*的后面那部分。(PS:这里涉及一个http常被问到的问题,http请求由哪几部分组成,一般是请求行,请求头,空行,请求体。payload body应该是对应请求体。)

一个请求伴随着header设置为Content-Type: application/json时候,看起来可能像这样:

1
2
3
4
POST /some-path HTTP/1.1
Content-Type: application/json

{ "foo" : "bar", "name" : "John" }

如果你正常请求一个ajax。浏览器会简单的将你提交的内容作为payload展示出来,这就是它所能做的,因为它不知道数据来自哪里。

如果你提交了一个html表单并且配置上了method="post",并且设置了Content-Type: application/x-www-form-urlencoded或者Content-Type: multipart/form-data。那么你的请求可能长这个样:

1
2
3
4
POST /some-path HTTP/1.1
Content-Type: application/x-www-form-urlencoded

foo=bar&name=John

这里的form-data就是request payload。在这里,浏览器知道更多:它知道bar是提交表单的输入字段foo的值。这就是它向你展示的。

所以区别就是,他们只是因为Content-Type设置的不同,并不是数据提交方式的不同,这两种提交都会将数据放在message-body中。但是chrome浏览器的开发者工具会根据这个ContentType区分显示方式。

我自己总结下关键还是在于Content-Type编码方式的区别:

  • 表单提交默认为Content-Type: application/x-www-form-urlencoded
  • ajax提交默认为Content-Type:application/json

前端在提交数据时使用什么编码,后端接收数据也得采用相应的编辑解析数据。

原来只了解gin的的BindJSONShouldBindJSON只是用来做模型绑定和验证的,而不了解要接收POST过来的json数据就得使用BindJSON,或者自己decode

参考

https://stackoverflow.com/questions/23118249/whats-the-difference-between-request-payload-vs-form-data-as-seen-in-chrome

https://segmentfault.com/a/1190000018774494