Przeglądaj źródła

refactor(http-lib): Add emqx_http_lib

So far only uri_encode and uri_decode APIs
Zaiming Shi 5 lat temu
rodzic
commit
63c001a7aa

+ 1 - 5
apps/emqx_auth_mnesia/test/emqx_acl_mnesia_SUITE.erl

@@ -250,8 +250,4 @@ uri(Parts) when is_list(Parts) ->
     NParts = [b2l(E) || E <- Parts],
     ?HOST ++ filename:join([?BASE_PATH, ?API_VERSION, "acl"| NParts]).
 
-%% @private
-b2l(B) when is_binary(B) ->
-    http_uri:encode(binary_to_list(B));
-b2l(L) when is_list(L) ->
-    http_uri:encode(L).
+b2l(B) -> binary_to_list(emqx_http_lib:uri_encode(iolist_to_binary(B))).

+ 1 - 9
apps/emqx_coap/src/emqx_coap_ps_resource.erl

@@ -241,7 +241,7 @@ handle_received_publish(Topic, MaxAge, Format, Payload) ->
 handle_received_create(TopicPrefix, MaxAge, Payload) ->
     case core_link:decode(Payload) of
         [{rootless, [Topic], [{ct, CT}]}] when is_binary(Topic), Topic =/= <<>> ->
-            TrueTopic = percent_decode(Topic),
+            TrueTopic = emqx_http_lib:uri_decode(Topic),
             ?LOG(debug, "decoded link-format payload, the Topic=~p, CT=~p~n", [TrueTopic, CT]),
             LocPath = concatenate_location_path([<<"ps">>, TopicPrefix, TrueTopic]),
             FullTopic = binary:part(LocPath, 4, byte_size(LocPath)-4),
@@ -259,14 +259,6 @@ handle_received_create(TopicPrefix, MaxAge, Payload) ->
             {error, bad_request}
     end.
 
-%% @private Copy from http_uri.erl which has been deprecated since OTP-23
-percent_decode(<<$%, Hex:2/binary, Rest/bits>>) ->
-    <<(binary_to_integer(Hex, 16)), (percent_decode(Rest))/binary>>;
-percent_decode(<<First:1/binary, Rest/bits>>) ->
-    <<First/binary, (percent_decode(Rest))/binary>>;
-percent_decode(<<>>) ->
-    <<>>.
-
 %% When topic is timeout, server should return nocontent here,
 %% but gen_coap only receive return value of #coap_content from coap_get, so temporarily we can't give the Code 2.07 {ok, nocontent} out.TBC!!!
 return_resource(Topic, Payload, MaxAge, TimeStamp, Content) ->

+ 69 - 0
src/emqx_http_lib.erl

@@ -0,0 +1,69 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%%     http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_http_lib).
+
+-export([uri_encode/1, uri_decode/1]).
+
+%% @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(<<>>) ->
+    <<>>.
+
+%% @doc Encode URI.
+-spec uri_encode(binary()) -> binary().
+uri_encode(URI) when is_binary(URI) ->
+    << <<(uri_encode_binary(Char))/binary>> || <<Char>> <= URI >>.
+
+uri_encode_binary(Char) ->
+    case reserved(Char)  of
+        true ->
+            << $%, (integer_to_binary(Char, 16))/binary >>;
+        false ->
+            <<Char>>
+    end.
+
+reserved($;) -> true;
+reserved($:) -> true;
+reserved($@) -> true;
+reserved($&) -> true;
+reserved($=) -> true;
+reserved($+) -> true;
+reserved($,) -> true;
+reserved($/) -> true;
+reserved($?) -> true;
+reserved($#) -> true;
+reserved($[) -> true;
+reserved($]) -> true;
+reserved($<) -> true;
+reserved($>) -> true;
+reserved($\") -> true;
+reserved(${) -> true;
+reserved($}) -> true;
+reserved($|) -> true;
+reserved($\\) -> true;
+reserved($') -> true;
+reserved($^) -> true;
+reserved($%) -> true;
+reserved($\s) -> true;
+reserved(_) -> false.

+ 46 - 0
test/emqx_http_lib_tests.erl

@@ -0,0 +1,46 @@
+%%--------------------------------------------------------------------
+%% Copyright (c) 2021 EMQ Technologies Co., Ltd. All Rights Reserved.
+%%
+%% Licensed under the Apache License, Version 2.0 (the "License");
+%% you may not use this file except in compliance with the License.
+%% You may obtain a copy of the License at
+%%
+%%     http://www.apache.org/licenses/LICENSE-2.0
+%%
+%% Unless required by applicable law or agreed to in writing, software
+%% distributed under the License is distributed on an "AS IS" BASIS,
+%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+%% See the License for the specific language governing permissions and
+%% limitations under the License.
+%%--------------------------------------------------------------------
+
+-module(emqx_http_lib_tests).
+
+-include_lib("proper/include/proper.hrl").
+-include_lib("eunit/include/eunit.hrl").
+
+uri_encode_decode_test_() ->
+    Opts = [{numtests, 1000}, {to_file, user}],
+    {timeout, 10,
+     fun() -> ?assert(proper:quickcheck(prop_run(), Opts)) end}.
+
+prop_run() ->
+    ?FORALL(Generated, prop_uri(), test_prop_uri(iolist_to_binary(Generated))).
+
+prop_uri() ->
+    proper_types:non_empty(proper_types:list(proper_types:union([prop_char(), prop_reserved()]))).
+
+prop_char() -> proper_types:integer(32, 126).
+
+prop_reserved() ->
+    proper_types:oneof([$;, $:, $@, $&, $=, $+, $,, $/, $?,
+        $#, $[, $], $<, $>, $\", ${, $}, $|,
+        $\\, $', $^, $%, $ ]).
+
+test_prop_uri(URI) ->
+    Encoded = emqx_http_lib:uri_encode(URI),
+    Decoded1 = emqx_http_lib:uri_decode(Encoded),
+    ?assertEqual(URI, Decoded1),
+    Decoded2 =  uri_string:percent_decode(Encoded),
+    ?assertEqual(URI, Decoded2),
+    true.