emqx/apps/emqx_dashboard/test/emqx_dashboard_api_test_hel...

185 lines
5.9 KiB
Erlang

%%--------------------------------------------------------------------
%% Copyright (c) 2022-2023 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_dashboard_api_test_helpers).
-export([
set_default_config/0,
set_default_config/1,
set_default_config/2,
set_default_config/3,
request/2,
request/3,
request/4,
request/5,
multipart_formdata_request/3,
multipart_formdata_request/4,
host/0,
uri/0,
uri/1,
uri/2
]).
-define(HOST, "http://127.0.0.1:18083").
-define(API_VERSION, "v5").
-define(BASE_PATH, "api").
set_default_config() ->
set_default_config(<<"admin">>).
set_default_config(DefaultUsername) ->
set_default_config(DefaultUsername, false).
set_default_config(DefaultUsername, HAProxyEnabled) ->
set_default_config(DefaultUsername, HAProxyEnabled, #{}).
set_default_config(DefaultUsername, HAProxyEnabled, Opts) ->
Config = #{
listeners => #{
http => #{
bind => maps:get(bind, Opts, 18083),
inet6 => false,
ipv6_v6only => false,
max_connections => 512,
num_acceptors => 4,
send_timeout => 5000,
backlog => 512,
proxy_header => HAProxyEnabled
}
},
default_username => DefaultUsername,
default_password => <<"public">>,
i18n_lang => en
},
emqx_config:put([dashboard], Config),
ok.
request(Method, Url) ->
request(Method, Url, []).
request(Method, Url, Body) ->
request(<<"admin">>, Method, Url, Body).
request(Username, Method, Url, Body) ->
request(Username, <<"public">>, Method, Url, Body).
request(Username, Password, Method, Url, Body) ->
Request =
case Body of
[] when
Method =:= get orelse Method =:= put orelse
Method =:= head orelse Method =:= delete orelse
Method =:= trace
->
{Url, [auth_header(Username, Password)]};
_ ->
{Url, [auth_header(Username, Password)], "application/json",
emqx_utils_json:encode(Body)}
end,
ct:pal("Method: ~p, Request: ~p", [Method, Request]),
case httpc:request(Method, Request, [], [{body_format, binary}]) of
{error, socket_closed_remotely} ->
{error, socket_closed_remotely};
{ok, {{"HTTP/1.1", Code, _}, _Headers, Return}} ->
{ok, Code, Return};
{ok, {Reason, _, _}} ->
{error, Reason}
end.
host() ->
?HOST.
uri() ->
uri([]).
uri(Parts) when is_list(Parts) ->
uri(host(), Parts).
uri(Host, Parts) when is_list(Host), is_list(Parts) ->
NParts = [E || E <- Parts],
Host ++ "/" ++ to_list(filename:join([?BASE_PATH, ?API_VERSION | NParts])).
auth_header(Username) ->
auth_header(Username, <<"public">>).
auth_header(Username, Password) ->
{ok, _Role, Token} = emqx_dashboard_admin:sign_token(Username, Password),
{"Authorization", "Bearer " ++ binary_to_list(Token)}.
multipart_formdata_request(Url, Fields, Files) ->
multipart_formdata_request(Url, <<"admin">>, Fields, Files).
multipart_formdata_request(Url, Username, Fields, Files) ->
Boundary =
"------------" ++ integer_to_list(rand:uniform(99999999999999999)) ++
integer_to_list(erlang:system_time(millisecond)),
Body = format_multipart_formdata(Boundary, Fields, Files),
ContentType = lists:concat(["multipart/form-data; boundary=", Boundary]),
Headers =
[
auth_header(Username),
{"Content-Length", integer_to_list(length(Body))}
],
case httpc:request(post, {Url, Headers, ContentType, Body}, [], []) of
{error, socket_closed_remotely} ->
{error, socket_closed_remotely};
{ok, {{"HTTP/1.1", Code, _}, _Headers, Return}} ->
{ok, Code, Return};
{ok, {Reason, _, _}} ->
{error, Reason}
end.
format_multipart_formdata(Boundary, Fields, Files) ->
FieldParts = lists:map(
fun({FieldName, FieldContent}) ->
[
lists:concat(["--", Boundary]),
lists:concat([
"Content-Disposition: form-data; name=\"", atom_to_list(FieldName), "\""
]),
"",
to_list(FieldContent)
]
end,
Fields
),
FieldParts2 = lists:append(FieldParts),
FileParts = lists:map(
fun({FieldName, FileName, FileContent}) ->
[
lists:concat(["--", Boundary]),
lists:concat([
"Content-Disposition: form-data; name=\"",
atom_to_list(FieldName),
"\"; filename=\"",
FileName,
"\""
]),
lists:concat(["Content-Type: ", "application/octet-stream"]),
"",
to_list(FileContent)
]
end,
Files
),
FileParts2 = lists:append(FileParts),
EndingParts = [lists:concat(["--", Boundary, "--"]), ""],
Parts = lists:append([FieldParts2, FileParts2, EndingParts]),
string:join(Parts, "\r\n").
to_list(Bin) when is_binary(Bin) -> binary_to_list(Bin);
to_list(Str) when is_list(Str) -> Str.