在使用postman发送post请求时,可以看到body的数据格式有如下几种:
postman.png
其中form-data和x-www-form-urlencoded有什么区别呢?点击右侧的code,可以看到实际发出的HTTP请求的样子:
code.png
x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样:
POST /auth/realms/foodie/protocol/openid-connect/token HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
User-Agent: PostmanRuntime/7.20.1
Accept: */*
Cache-Control: no-cache
Postman-Token: 43e5b9f1-8c43-4c76-9789-2fa50025cbec,ebd1348c-0534-4c7a-9fa7-160690f79c9f
Host: localhost:8080
Accept-Encoding: gzip, deflate
Content-Length: 67
Connection: keep-alive
cache-control: no-cache
grant_type=password&client_id=foodie&username=user1&password=123456
最后一行就是实际发出的body数据,它将key,value的字段进行了拼接,并使用url endcoding对key和value进行了编码。
form-data
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data。直接来看一个请求示例:
POST /auth/realms/foodie/protocol/openid-connect/token HTTP/1.1
Host: localhost:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
User-Agent: PostmanRuntime/7.20.1
Accept: */*
Cache-Control: no-cache
Postman-Token: 43e5b9f1-8c43-4c76-9789-2fa50025cbec,2ae8928a-3ffb-4a8f-9cfa-10c7fc6ee965
Host: localhost:8080
Accept-Encoding: gzip, deflate
Content-Length: 67
Connection: keep-alive
cache-control: no-cache
Content-Disposition: form-data; name="grant_type"
password
------WebKitFormBoundary7MA4YWxkTrZu0gW--,
Content-Disposition: form-data; name="grant_type"
password
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="client_id"
foodie
------WebKitFormBoundary7MA4YWxkTrZu0gW--,
Content-Disposition: form-data; name="grant_type"
password
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="client_id"
foodie
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="username"
user1
------WebKitFormBoundary7MA4YWxkTrZu0gW--,
Content-Disposition: form-data; name="grant_type"
password
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="client_id"
foodie
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="username"
user1
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="password"
123456
------WebKitFormBoundary7MA4YWxkTrZu0gW--
首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary是一个自定义的随机字符串,然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,以及 boundary 是什么内容。
消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary 开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。例如:
------WebKitFormBoundary7MA4YWxkTrZu0gW--
Content-Disposition: form-data; name="image"; filename="code.png"
Content-Type: image/png
PNG ... content of code.png ...
消息主体最后以 --boundary-- 标示结束。
上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 <form> 表单也只支持这两种方式(通过 <form> 元素的 enctype
属性指定,默认为 application/x-www-form-urlencoded
。其实 enctype
还支持 text/plain
,不过用得非常少)。
网友评论