Search code examples
nginxluaopenresty

Is there a lua equivalent of the javascript encodeURI() function?


I am currently using openresty nginx to proxy requests to an origin. I want to escape any unsafe characters in the uri of the request. Basically, I am looking for a lua equivalent for the encodeURI() javascript function.

Is there a method in Lua, similar to encodeURI() in JS?

I have looked at ngx.escape_uri, but this function only escapes a URI component.

I want the uri /test/[hello] to become /test/%5Bhello%5D after encoding the URI. If I do encodeURI("/test/[hello]/"); in JS, I get the desired output which is /test/%5Bhello%5D.

But, in Lua, if I do ngx.escape_uri("/test/[hello]/"), I get the output as '%2Ftest%2F%5Bhello%5D'.


Solution

  • ngx.escape_uri has an option to escape a full URI:

    syntax: newstr = ngx.escape_uri(str, type?)

    Since v0.10.16, this function accepts an optional type argument. It accepts the following values (defaults to 2):

    0: escapes str as a full URI. [...]

    2: escape str as a URI component. [...]

    Nonetheless, ngx.escape_uri(str, 0) is still not the same as encodeURI.

    Fortunately, it's easy to write your own function that produce exactly the same output as encodeURI:

    local function _encode_uri_char(char)
        return string.format('%%%0X', string.byte(char))
    end
    
    local function encode_uri(uri)
        return (string.gsub(uri, "[^%a%d%-_%.!~%*'%(%);/%?:@&=%+%$,#]", _encode_uri_char))
    end
    
    -- prints /test/%5Bhello%5D/
    ngx.say(encode_uri('/test/[hello]/')) 
    

    The encode_uri function escapes all characters except:

    A–Z a–z 0–9 - _ . ! ~ * ' ( )
    
    ; / ? : @ & = + $ , #
    

    as it described here.