Просмотр исходного кода

feat(uri): support decoding uri in string

zhouzb 4 лет назад
Родитель
Сommit
bd1051d1e6
1 измененных файлов с 35 добавлено и 9 удалено
  1. 35 9
      src/emqx_http_lib.erl

+ 35 - 9
src/emqx_http_lib.erl

@@ -31,22 +31,40 @@
                      fragment => unicode:chardata(),
                      fragment => unicode:chardata(),
                      userinfo => 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.
 %% @doc Decode percent-encoded URI.
 %% This is copied from http_uri.erl which has been deprecated since OTP-23
 %% This is copied from http_uri.erl which has been deprecated since OTP-23
 %% The recommended replacement uri_string function is not quite equivalent
 %% The recommended replacement uri_string function is not quite equivalent
 %% and not backward compatible.
 %% 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.
 %% @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(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
 %% @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
 %% 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(<<"http">>) -> http;
 atom_scheme(Other) -> throw({unsupported_scheme, Other}).
 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
     case reserved(Char)  of
         true ->
         true ->
             << $%, (integer_to_binary(Char, 16))/binary >>;
             << $%, (integer_to_binary(Char, 16))/binary >>;