diff --git a/src/emqx_http_lib.erl b/src/emqx_http_lib.erl index 195656622..7813c605e 100644 --- a/src/emqx_http_lib.erl +++ b/src/emqx_http_lib.erl @@ -31,22 +31,40 @@ fragment => unicode:chardata(), userinfo => unicode:chardata()}. +-type hex_uri() :: string() | binary(). +-type maybe_hex_uri() :: string() | binary(). %% A possibly hexadecimal encoded URI. +-type uri() :: string() | binary(). + %% @doc Decode percent-encoded URI. %% This is copied from http_uri.erl which has been deprecated since OTP-23 %% The recommended replacement uri_string function is not quite equivalent %% and not backward compatible. --spec uri_decode(binary()) -> binary(). -uri_decode(<<$%, Hex:2/binary, Rest/bits>>) -> - <<(binary_to_integer(Hex, 16)), (uri_decode(Rest))/binary>>; -uri_decode(<>) -> - <>; -uri_decode(<<>>) -> +-spec uri_decode(maybe_hex_uri()) -> uri(). +uri_decode(String) when is_list(String) -> + do_uri_decode(String); +uri_decode(String) when is_binary(String) -> + do_uri_decode_binary(String). + +do_uri_decode([$%,Hex1,Hex2|Rest]) -> + [hex2dec(Hex1)*16+hex2dec(Hex2)|do_uri_decode(Rest)]; +do_uri_decode([First|Rest]) -> + [First|do_uri_decode(Rest)]; +do_uri_decode([]) -> + []. + +do_uri_decode_binary(<<$%, Hex:2/binary, Rest/bits>>) -> + <<(binary_to_integer(Hex, 16)), (do_uri_decode_binary(Rest))/binary>>; +do_uri_decode_binary(<>) -> + <>; +do_uri_decode_binary(<<>>) -> <<>>. %% @doc Encode URI. --spec uri_encode(binary()) -> binary(). +-spec uri_encode(uri()) -> hex_uri(). +uri_encode(URI) when is_list(URI) -> + lists:append([do_uri_encode(Char) || Char <- URI]); uri_encode(URI) when is_binary(URI) -> - << <<(uri_encode_binary(Char))/binary>> || <> <= URI >>. + << <<(do_uri_encode_binary(Char))/binary>> || <> <= URI >>. %% @doc Parse URI into a map as uri_string:uri_map(), but with two fields %% normalised: (1): port number is never 'undefined', default ports are used @@ -93,7 +111,15 @@ atom_scheme(<<"https">>) -> https; atom_scheme(<<"http">>) -> http; atom_scheme(Other) -> throw({unsupported_scheme, Other}). -uri_encode_binary(Char) -> +do_uri_encode(Char) -> + case reserved(Char) of + true -> + [ $% | http_util:integer_to_hexlist(Char)]; + false -> + [Char] + end. + +do_uri_encode_binary(Char) -> case reserved(Char) of true -> << $%, (integer_to_binary(Char, 16))/binary >>;