ngx.req.set_uri_args 的使用陷阱

本文介绍了NginxOpenResty中的ngx.req.set_uri_args函数用于动态修改请求查询字符串的用法,包括传递table、字符串和数组参数,以及需要注意的参数顺序和URL编码问题。

ngx.req.set_uri_args 是一个在Nginx的Lua模块(通常是 OpenResty )中使用的函数,这个函数可以用来动态修改请求的查询字符串(Query String),但某些情况下,原始请求的 Query 参数顺序经过这个函数修改后可能会改变参数顺序。

1. 基础用法

1.1 传递table参数

  • 设置 URI 参数为 “?arg1=value1”
ngx.req.set_uri_args({ arg1 = "value1" })
  • 设置 URI 参数为 “?arg1=value1&arg2=value2”
ngx.req.set_uri_args({ arg1 = "value1", arg2 = "value2" })

1.2 传递字符串

  • 可以直接传递一个编码后的查询字符串,URI 参数会被设置为 “?arg1=value1&arg2=value2”
ngx.req.set_uri_args("arg1=value1&arg2=value2")

1.3 数组参数

  • 设置 URI 参数为 “?arg=value1&arg=value2”
ngx.req.set_uri_args({ arg = {"value1", "value2" } })

2. 需要注意的陷阱

2.1 参数顺序

在Lua中,字典(或哈希表)的遍历顺序是不确定的,因为它们是根据键的哈希值来组织的,而不是按照插入的顺序,当使用 ngx.req.set_uri_args 函数设置参数时,参数若被存储在一个表(Lua中的数组和字典结构)里,在 ngx.req.set_uri_args 函数中参数被转回URI字符串时,它们的顺序可能与原始或预期的顺序不同。例如,

ngx.req.set_uri_args({ arg1 = "value1", arg2 = "value2", arg3 = "value3"})

设置完 URI 参数可能会变为 “arg3=value3&arg2=value2&arg1=value1”。

2.2 URL 编码问题

ngx.req.set_uri_args 函数在设置 URI 参数时,会自动对参数执行URL编码,调用前不需要事先对参数值进行编码。当传递一个 Lua 表或键值对参数到该函数时,它会确保所有的参数值被正确地编码为适合在 URL 中使用的格式。

例如,如果有包含(如空格、&、% 等)的参数值时,ngx.req.set_uri_args 会将这些字符串转换为他们的 URL 编码形式,这是处理 HTTP 请求的标准做法,确保了数据的完整性和传输的安全性。

ngx.req.set_uri_args({ arg = "value with space" })

这个例子中,参数 “arg” 的值 “value with spaces” 中的空格会被转换为 “%20” 。如果直接传递一个已经编码的查询字符串给 “ngx.req.set_uri_args” ,它将不会再次对这个字符串进行编码。所以,在这种情况下,需要确保提供的字符串已经正确编码。

这个例子中,参数 “arg” 的值 “value with spaces” 中的空格会被转换为"%20" 。如果直接传递一个已经编码的查询字符串给 “ngx.req.set_uri_args” ,它将不会再次对这个字符串进行编码。所以,在这种情况下使用函数时,需要确保提供的字符串已经正确编码。

有些 http 请求中一般不编码的符号例如冒号,通过 table 参数传递给 ngx.req.set_uri_args 时,也会被编码,但直接传递字符串不会被 URL 编码,例如以下两种传递字符串的方式设置后的 URI 参数是不同的。

ngx.req.set_uri_args({arg1 = "2001:4860:4801:48::13"})
通过 table 设置后 uri 参数为 arg1=2001%3A4860%3A4801%3A48%3A%3A13

ngx.req.set_uri_args("arg1=2001:4860:4801:48::13")
通过 字符串 设置后 uri 参数为 arg1=2001:4860:4801:48::13

综上所示,ngx.req.set_uri_args 使用时需要注意查询字符串中的参数顺序和编码是否符合预期。

欢迎来公众号交流,共同学习,共同进步,分享总结 C++、Golang、数据结构等面试考点,日常工作经验等等,持续更新!
Coder567

`proxy_set_body` 和 `urlencode` 是 Nginx 中处理请求体和编码的重要指令。 ### 1. `proxy_set_body` `proxy_set_body` 指令用于设置传递给后端服务器的请求主体内容。通常在反向代理场景下使用,可以自定义发送到上游服务器的内容,适用于修改、简化或构建新的请求体数据。 #### 示例: ```nginx location /api { proxy_pass http://backend; proxy_set_body "custom_request_body"; } ``` 在这个例子中,所有发往 `/api` 的请求都将被转发至 `http://backend` ,并且其请求体会被替换为 `"custom_request_body"` 字符串。 ### 2. URL 编码 (`urlencode`) URL 编码是一种将特殊字符转换成可在 URI 中安全传输的形式的技术。例如空格会被替换成 `%20`, 非 ASCII 字符也被相应的百分比序列表示。这主要是为了确保字符串能正确地作为 URL 参数或其他需要转义的地方工作正常。 虽然 Nginx 自身并没有直接提供名为 `urlencode` 的配置项,但在实际应用里我们经常结合其他工具和技术来实现类似功能: - **通过 Lua 脚本**:如果你安装了 ngx_http_lua_module,则可以在 Nginx 内部运行 Lua 代码来进行复杂的逻辑运算包括 urlencode; ```lua lua_package_path "/path/to/lua/socket/?.lua;;"; server { location = /encode_url { content_by_lua_block { local args = ngx.req.get_uri_args() for k, v in pairs(args) do ngx.say("Original: ", v) local encoded = ngx.escape_uri(v) ngx.say("Encoded : ", encoded) end } } } ``` - **外部程序**:也可以利用 FastCGI 或 uWSGI 等机制调用 Python/Ruby 程序完成此任务; - **正则表达式配合 map 模块**:对于简单情况下的字符替换,可以直接运用 rewrite 规则以及内置函数如 `$escape_uri` 来做初步处理。 ### 综合示例 - 使用 `map` 实现简单的 URL 编码 下面的例子展示了如何创建一个新的变量,并对来自客户端的数据自动进行基本形式的 URL 编码后再赋值给 `proxy_set_body`. ```nginx # 定义映射规则,在这里仅做了最基本的字母大小写保护 map $request_body $encoded_request_body { default $request_body; "~[a-zA-Z]+" ${request_body}; } server { listen 80; server_name localhost; location /post_data { # 应用上面定义好的映射 set $safe_request_body $encoded_request_body; proxy_pass https://upstream_server; proxy_method POST; # 如果原始method不是POST记得指定 # 设置经由我们预处理过的body内容传送给后台服务 proxy_set_body "$safe_request_body"; } } ``` 请注意这个案例非常基础,真实的项目环境还需要考虑更多细节比如非英文字符集的支持等。 --- 最后需要注意的是,如果涉及到较为复杂或者高频率变化的业务需求建议尽量避免过多依赖于 Nginx 进行此类操作而是交给应用程序层面去做更为合理高效的选择。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder567

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值