最近在使用 Spring 的 RestTemplate 类发送 POST 和 GET 请求,当中碰到了一些关于 HTTP Headers 的问题,这里先记录下。

在 HTTP 中 Headers 的 Content Type 就是设置 MediaType 类型的,也就是 MIME 类型。它的作用是给在互联网上传输的内容赋予分类类型,跟文件扩展名的作用相对应(不同的文件扩展名对应不同的 MIME 类型)。详细情况可以参考 互联网媒体类型 常见 MIME 类型列表

我们要发送 POST 请求,HTTP POST 方法是发送数据给服务器。请求主体的类型由 Content-Type 首部指定。

PUT 和POST方法的区别是,PUT 方法是幂等的:连续调用一次或者多次的效果相同(无副作用)。连续调用同一个 POST 可能会带来额外的影响,比如多次提交订单。

一个 POST 请求通常是通过 HTML 表单发送,并返回服务器的修改结果。在这种情况下,content type 是通过在 <form> 元素中设置正确的 enctype 属性,或是在 <input><button> 元素中设置 formenctype 属性来选择的:

  • application/x-www-form-urlencoded: 数据被编码成以 '&' 分隔的键 - 值对,同时以 '=' 分隔键和值。非字母或数字的字符会被 percent-encoding,这也就是为什么这种类型不支持二进制数据 (应使用 multipart/form-data 代替)。
  • multipart/form-data
  • text/plain

当 POST 请求是通过除 HTML 表单之外的方式发送时,例如使用 XMLHttpRequest, 那么请求主体可以是任何类型。

示例

使用默认的 application/x-www-form-urlencoded 做为 content type 的简单表单:

POST / HTTP/1.1
Host: foo.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 13

say=Hi&to=Mom

使用 multipart/form-data 作为 content type 的表单:

POST /test.html HTTP/1.1
Host: example.org
Content-Type: multipart/form-data;boundary="boundary"

--boundary
Content-Disposition: form-data; name="field1"

value1
--boundary
Content-Disposition: form-data; name="field2"; filename="example.txt"

value2

POST 传递 json

### Send POST request with json body
POST http://localhost:18443/post-json
Content-Type: application/json

{
  "id": 999,
  "value": "content",
  "level": "LOW"
}

那么 SpringMVC 的控制器接收:

public String index1(@RequestBody Map<String,String> content) {}

因为 json 是在 HTTP 请求的 Body 里面的。


POST 传递 x-www-form-urlencoded

### Send POST request with body as parameters
POST http://localhost:18443/post-x-www-form-urlencoded
Content-Type: application/x-www-form-urlencoded

id=999&value=content

那么 SpringMVC 的控制器接收:

public String index2(@RequestParam String id, @RequestParam String value) {}

总结

如果你要使用 POST 方法向服务器发送二进制数据(比如非字符或数字的,文件,一个很大的有效载荷),那么应该使用 multipart/form-data,其他情况下则使用 application/x-www-form-urlencoded,以键值对的方式传递字符数据。


参考资料:

POST
application/x-www-form-urlencoded or multipart/form-data?
How to POST form data with Spring RestTemplate?

标签: none

评论已关闭