当前位置: 首页 > 工具软件 > Mobile Lua > 使用案例 >

Nginx+Lua重写POST的Body数据

谭敏学
2023-12-01

需求描述

Nginx在反向代理请求之前,对Post请求体的内容进行修改,添加额外的字段内容。这里POST请求的Content-Type的值为application/x-www-form-urlencoded。

实现

安装OpenResty,使用Lua扩展功能实现,具体代码如下,

location /serviceA {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' '*';
            rewrite_by_lua_block {
                local cjson = require "cjson"
                ngx.req.read_body()
                local args = ngx.req.get_post_args()
                ngx.log(ngx.DEBUG, cjson.encode(args))
                args['secret'] = "7W0XLF"
                ngx.log(ngx.DEBUG, cjson.encode(args))
                local data = {}
                for i, v in pairs(args) do
                    table.insert(data, i .."=" ..v)
                end
                ngx.req.set_body_data(table.concat(data, "&"))
            }
            proxy_pass https://your_domain/serviceA;
        }

其中,ngx.log为调试代码输出,为了使ngx.DEBUG的日志输出到error.log日志中,需要在nginx.conf中配置error_log的日志级别,即error_log logs/error.log debug;
主要涉及到的技术点,

  • 读取post的body的数据,
    ngx.req.read_body()
    local args = ngx.req.get_post_args()
    
    其中的args为key-value形式的table数据。
  • 把修改后的数据写入body体,ngx.req.set_body_data(data)其中的data是字符串类型的数据。
  • Content-Typeapplication/x-www-form-urlencoded的类型时,实际的post传递的是字符串格式的数据,其形式为a=20&name=张山。还需要注意的是,需要时经过urlencoded编码过的。

示例说明

Vue使用axios发起post请求

// 字符串化application/x-www-form-urlencoded的post请求数据
var qs = require("qs");
this.axios.post(
        "http://localhost:8082/serviceA",
        qs.stringify({
          name: "LiSi",
          age: "20"
        }),
        {
          headers: {
            "Content-Type": "application/x-www-form-urlencoded"
          }
        }
      ).then(response => {
        console.log(response)
      });
    }

技术点说明,

  • 指定Content-Type为application/x-www-form-urlencoded
  • 引入qs,调用stringify方法把json对象转换为x-www-form-urlencoded的形式

Nginx配置

Nginx的配置按照上述实现配置即可。

结果

在vue端发起对8082/serviceA的调用之后,经过Nginx的代理,最终到达your_domain/serviceA的时候,可以取到name、age、secret三个字段。并且第三个字段secret是在nginx代理到后端之前,重写post的body加上的,对用户来说是不可见的。

 类似资料: