注:请求方式分为GET/POST/HEAD/PUT/OPTIONS等,这里主要讲POST请求
熟悉openresty开发的同学都知道我们通过ngx.req.get_post_args()和ngx.req.get_body_data()就可以获取请求体的内容,这二者有什么区别呢?他们和PHP的$_POST,以及JAVA的HttpServletRequest.getParameter有啥区别呢?跟我一起来一场测试之旅。
一、常用请求体编码格式
所谓请求体编码格式(也叫请求体编码类型),就是提交数据的格式,在html元素form中可以通过enctype来设置。
1、form-data
完整的叫法是multipart/form-data
。
它的特点
- 它会将表单的数据处理为一条消息,以标签元素为单元,用分隔符分开
- 它既可以提交键值对,也可以上传文件
其预览内容如下:
------WebKitFormBoundarycWa0J33ty7eIQlMX
Content-Disposition: form-data; name="name"
shixinke
------WebKitFormBoundarycWa0J33ty7eIQlMX
Content-Disposition: form-data; name="email"
ishixinke@qq.com
2、x-www-form-urlencoded
它将请求数据被编码为名称/值对,是标准的请求体(一般ajax请求都是用这种格式),其格式如下:
name=shixinke&email=ishixinke@qq.com
3、text(raw)
它的请求数据是纯文本,可以是json,text,xml或者html等
- 纯文本
name
- json
{"name":"shixinke", "email":"ishixinke@qq.com"}
二、openresty获取请求内容
示例代码:
ngx.req.read_body()
-- 通过get_post_args()来获取请求内容
local args, err = ngx.req.get_post_args()
if not args then
ngx.say("cannot get post args")
else
ngx.say("post args:<br>")
for k, v in pairs(args) do
ngx.say("key:")
ngx.say(k)
ngx.say('<br>')
ngx.say("value:")
ngx.say(v)
ngx.say('<br>##########################################<br>')
end
if args["name"] then
ngx.say("name="..args["name"])
end
if args["email"] then
ngx.say("email="..args['email'])
end
ngx.say("<br>####################################################<br>")
end
-- 通过get_body_data来获取内容
local data, err = ngx.req.get_body_data()
if not data then
ngx.say("cannot get body data")
else
ngx.say("body data:<br>")
ngx.say(data)
end
1、form-data格式
(1)请求表单
(2)响应内容:
- 通过ngx.req.get_post_args()来获取请求内容:
key: ------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name
value: "name" shixinke ------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name="email" ishixinke@qq.com ------WebKitFormBoundaryiAAQVKRKgYqR8kAw--
- 通过ngx.req.get_body_data()来获取请求内容
------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name="name" shixinke ------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name="email" ishixinke@qq.com ------WebKitFormBoundaryiAAQVKRKgYqR8kAw--
(3)结论:
当请求格式为form-data时,可以获取到请求体的内容,但是请求体内容需要自己去解析,并不是如表单一样的键值对。所以,当请求头中的content-type为multipart/form-data时,通过类似于ngx.req.get_post_args[‘name’]这·种形式并不能得到预想的结果。在这种格式下,ngx.req.get_body_data()和ngx.req.get_post_args()获取的结果是一样的。
2、x-www-form-urlencoded
(1)请求表单
(2)响应内容:
post args:
key: email
value: ishixinke@qq.com
##########################################
key: name
value: shixinke
##########################################
name=shixinke email=ishixinke@qq.com
####################################################
body data:
name=shixinke&email=ishixinke%40qq.com
(3)结论
当请求格式为x-www-form-urlencoded时,ngx.req.get_post_args()可以获取格式化(解析)后的请求内容,是与表单一样的键值对,ngx.req.get_body_data()还是一样获取最原始的请求内容,需要自己去解析
3、text
对于普通text,一般分为普通url参数格式的纯文本、按一定格式组成的文本(如JSON,XML,HTML)和没有特定格式的纯文本(一般没实际意义)
普通url参数格式的纯文本
(1)请求表单
(2)响应内容:
post args:
key: email
value: ishixinke@qq.com
##########################################
key: name
value: shixinke
##########################################
name=shixinke email=ishixinke@qq.com
####################################################
body data:
name=shixinke&email=ishixinke@qq.com
(3)结论
对于以URL参数形式组成的纯文本,ngx.req.get_post_args()可以成功解析成表单键值对的形式,ngx.req.get_body_data()获取的还是原始的请求体内容
JSON格式的文本
(1)请求表单
(2)响应内容:
post args:
key: {"name":"shixinke", "email":"ishixinke@qq.com"}
value: true
##########################################
####################################################
body data:
{"name":"shixinke", "email":"ishixinke@qq.com"}
(3)结论
当请求体内容为JSON格式的纯文本时,通过ngx.req.get_body_data()可以获取json内容,而通过ngx.req.get_post_args()来获取,解析较为复杂
三、PHP获取请求内容
示例代码:
<?php
echo "POST:<br>";
var_dump($_POST);
echo "<br>";
$data = file_get_contents("php://input");
echo "php://input<br>";
var_dump($data);
- 1、通过$_POST可以获取form-data和x-www-form-urlencoded的内容,以及可以获取URL参数形式的文本内容
- 2、通过file_get_contents(“php://input”)可以获取纯文本提交的内容,也可以获取除了form-data之外的请求格式的内容
四、JAVA获取请求内容
示例代码:(这里以spring框架为例)
@PostMapping("/request")
@ResponseBody
public String getContent(HttpServletRequest request) {
String content = "";
String name = request.getParameter("name");
String email = request.getParameter("email");
if (name != null) {
content += "name = "+ name;
}
if (email != null) {
content += ";email" + email;
}
return content;
}
- 通过request.getParameter()可以获取form-data、x-www-form-urlencoded以及以URL参数形式的文本内容
- 通过
@ResponseBody
注解可以获取普通文本的内容