feat(uri): support decoding uri in string

This commit is contained in:
zhouzb 2021-04-16 19:24:10 +08:00 committed by Rory Z
parent 5009ec0c34
commit bd1051d1e6
1 changed files with 35 additions and 9 deletions

View File

@ -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(<<First:1/binary, Rest/bits>>) ->
<<First/binary, (uri_decode(Rest))/binary>>;
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(<<First:1/binary, Rest/bits>>) ->
<<First/binary, (do_uri_decode_binary(Rest))/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>> || <<Char>> <= URI >>.
<< <<(do_uri_encode_binary(Char))/binary>> || <<Char>> <= 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 >>;