openresty获取HTTP请求内容与其他语言的差异

注:请求方式分为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
它的特点

  • 它会将表单的数据处理为一条消息,以标签元素为单元,用分隔符分开
  • 它既可以提交键值对,也可以上传文件

其预览内容如下:

  1. ------WebKitFormBoundarycWa0J33ty7eIQlMX
  2. Content-Disposition: form-data; name="name"
  3. shixinke
  4. ------WebKitFormBoundarycWa0J33ty7eIQlMX
  5. Content-Disposition: form-data; name="email"
  6. ishixinke@qq.com
2、x-www-form-urlencoded

它将请求数据被编码为名称/值对,是标准的请求体(一般ajax请求都是用这种格式),其格式如下:

  1. name=shixinke&email=ishixinke@qq.com
3、text(raw)

它的请求数据是纯文本,可以是json,text,xml或者html等

  • 纯文本
  1. name
  • json
  1. {"name":"shixinke", "email":"ishixinke@qq.com"}

二、openresty获取请求内容

示例代码:

  1. ngx.req.read_body()
  2. -- 通过get_post_args()来获取请求内容
  3. local args, err = ngx.req.get_post_args()
  4. if not args then
  5. ngx.say("cannot get post args")
  6. else
  7. ngx.say("post args:<br>")
  8. for k, v in pairs(args) do
  9. ngx.say("key:")
  10. ngx.say(k)
  11. ngx.say('<br>')
  12. ngx.say("value:")
  13. ngx.say(v)
  14. ngx.say('<br>##########################################<br>')
  15. end
  16. if args["name"] then
  17. ngx.say("name="..args["name"])
  18. end
  19. if args["email"] then
  20. ngx.say("email="..args['email'])
  21. end
  22. ngx.say("<br>####################################################<br>")
  23. end
  24. -- 通过get_body_data来获取内容
  25. local data, err = ngx.req.get_body_data()
  26. if not data then
  27. ngx.say("cannot get body data")
  28. else
  29. ngx.say("body data:<br>")
  30. ngx.say(data)
  31. end
1、form-data格式
(1)请求表单

(2)响应内容:
  • 通过ngx.req.get_post_args()来获取请求内容:
  1. key: ------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name
  2. value: "name" shixinke ------WebKitFormBoundaryiAAQVKRKgYqR8kAw Content-Disposition: form-data; name="email" ishixinke@qq.com ------WebKitFormBoundaryiAAQVKRKgYqR8kAw--
  • 通过ngx.req.get_body_data()来获取请求内容
  1. ------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)响应内容:
  1. post args:
  2. key: email
  3. value: ishixinke@qq.com
  4. ##########################################
  5. key: name
  6. value: shixinke
  7. ##########################################
  8. name=shixinke email=ishixinke@qq.com
  9. ####################################################
  10. body data:
  11. 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)响应内容:
  1. post args:
  2. key: email
  3. value: ishixinke@qq.com
  4. ##########################################
  5. key: name
  6. value: shixinke
  7. ##########################################
  8. name=shixinke email=ishixinke@qq.com
  9. ####################################################
  10. body data:
  11. name=shixinke&email=ishixinke@qq.com
(3)结论

对于以URL参数形式组成的纯文本,ngx.req.get_post_args()可以成功解析成表单键值对的形式,ngx.req.get_body_data()获取的还是原始的请求体内容

JSON格式的文本

(1)请求表单

(2)响应内容:
  1. post args:
  2. key: {"name":"shixinke", "email":"ishixinke@qq.com"}
  3. value: true
  4. ##########################################
  5. ####################################################
  6. body data:
  7. {"name":"shixinke", "email":"ishixinke@qq.com"}
(3)结论

当请求体内容为JSON格式的纯文本时,通过ngx.req.get_body_data()可以获取json内容,而通过ngx.req.get_post_args()来获取,解析较为复杂

三、PHP获取请求内容

示例代码:

  1. <?php
  2. echo "POST:<br>";
  3. var_dump($_POST);
  4. echo "<br>";
  5. $data = file_get_contents("php://input");
  6. echo "php://input<br>";
  7. var_dump($data);
  • 1、通过$_POST可以获取form-data和x-www-form-urlencoded的内容,以及可以获取URL参数形式的文本内容
  • 2、通过file_get_contents(“php://input”)可以获取纯文本提交的内容,也可以获取除了form-data之外的请求格式的内容

四、JAVA获取请求内容

示例代码:(这里以spring框架为例)

  1. @PostMapping("/request")
  2. @ResponseBody
  3. public String getContent(HttpServletRequest request) {
  4. String content = "";
  5. String name = request.getParameter("name");
  6. String email = request.getParameter("email");
  7. if (name != null) {
  8. content += "name = "+ name;
  9. }
  10. if (email != null) {
  11. content += ";email" + email;
  12. }
  13. return content;
  14. }
  • 通过request.getParameter()可以获取form-data、x-www-form-urlencoded以及以URL参数形式的文本内容
  • 通过@ResponseBody注解可以获取普通文本的内容