OpenResty中是否有等价于JavaScript encodeURI()的Lua函数?
实现OpenResty中与JavaScript encodeURI()等价的Lua方法
问题背景
ngx.escape_uri是OpenResty提供的URI组件转义函数,它会把所有非组件安全的字符(包括/)都转义,比如ngx.escape_uri("/test/[hello]/")会得到%2Ftest%2F%5Bhello%5D,但我们需要和JavaScript的encodeURI()行为一致——保留URI结构中的合法分隔符(如/),仅转义[]这类不安全字符,得到/test/%5Bhello%5D/。
解决方案:自定义Lua函数模拟encodeURI逻辑
JavaScript的encodeURI()规则是:保留字母、数字、通用安全字符(- _ . ! ~ * ' ( ))以及URI保留字符(; / ? : @ & = + $ , #),仅转义其他字符。我们可以基于这个规则实现等价的Lua函数:
function encode_uri(str) -- URI保留字符,encodeURI不转义这些 local reserved = { [';'] = true, ['/'] = true, ['?'] = true, [':'] = true, ['@'] = true, ['&'] = true, ['='] = true, ['+'] = true, ['$'] = true, [','] = true, ['#'] = true } -- 通用安全字符,encodeURI不转义这些 local safe = {} -- 0-9 for i = 48, 57 do safe[string.char(i)] = true end -- A-Z for i = 65, 90 do safe[string.char(i)] = true end -- a-z for i = 97, 122 do safe[string.char(i)] = true end -- 额外安全符号 safe['-'] = true safe['_'] = true safe['.'] = true safe['!'] = true safe['~'] = true safe['*'] = true safe["'"] = true safe['('] = true safe[')'] = true local parts = {} for i = 1, #str do local char = str:sub(i, i) if safe[char] or reserved[char] then table.insert(parts, char) else -- 转义为%XX格式,大写十六进制 table.insert(parts, string.format('%%%02X', string.byte(char))) end end return table.concat(parts) end
使用示例
调用上述函数:
local encoded = encode_uri("/test/[hello]/") -- 输出结果:/test/%5Bhello%5D/
该结果与JavaScriptencodeURI("/test/[hello]/")的输出完全一致。
额外说明
这个函数同样支持UTF-8字符的转义(比如中文),会将每个UTF-8字节转义为对应的%XX序列,和encodeURI()的处理逻辑保持一致。
内容的提问来源于stack exchange,提问作者dhruvparekh12
相关产品推荐
相关产品推荐

