Merge pull request #4283 from zmstone/add-emqx-http-lib

refactor(http-lib): Add emqx_http_lib
This commit is contained in:
Zaiming Shi 2021-03-04 07:14:02 +01:00 committed by GitHub
commit 42098b497f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 117 additions and 14 deletions

View File

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

View File

@ -241,7 +241,7 @@ handle_received_publish(Topic, MaxAge, Format, Payload) ->
handle_received_create(TopicPrefix, MaxAge, Payload) -> handle_received_create(TopicPrefix, MaxAge, Payload) ->
case core_link:decode(Payload) of case core_link:decode(Payload) of
[{rootless, [Topic], [{ct, CT}]}] when is_binary(Topic), Topic =/= <<>> -> [{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]), ?LOG(debug, "decoded link-format payload, the Topic=~p, CT=~p~n", [TrueTopic, CT]),
LocPath = concatenate_location_path([<<"ps">>, TopicPrefix, TrueTopic]), LocPath = concatenate_location_path([<<"ps">>, TopicPrefix, TrueTopic]),
FullTopic = binary:part(LocPath, 4, byte_size(LocPath)-4), FullTopic = binary:part(LocPath, 4, byte_size(LocPath)-4),
@ -259,14 +259,6 @@ handle_received_create(TopicPrefix, MaxAge, Payload) ->
{error, bad_request} {error, bad_request}
end. 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, %% 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!!! %% 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) -> return_resource(Topic, Payload, MaxAge, TimeStamp, Content) ->

69
src/emqx_http_lib.erl Normal file
View File

@ -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.

View File

@ -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.