You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:42:50