emqx_dashboard_api_test_helpers.erl 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. %%--------------------------------------------------------------------
  2. %% Copyright (c) 2022-2023 EMQ Technologies Co., Ltd. All Rights Reserved.
  3. %%
  4. %% Licensed under the Apache License, Version 2.0 (the "License");
  5. %% you may not use this file except in compliance with the License.
  6. %% You may obtain a copy of the License at
  7. %%
  8. %% http://www.apache.org/licenses/LICENSE-2.0
  9. %%
  10. %% Unless required by applicable law or agreed to in writing, software
  11. %% distributed under the License is distributed on an "AS IS" BASIS,
  12. %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. %% See the License for the specific language governing permissions and
  14. %% limitations under the License.
  15. %%--------------------------------------------------------------------
  16. -module(emqx_dashboard_api_test_helpers).
  17. -export([
  18. set_default_config/0,
  19. set_default_config/1,
  20. set_default_config/2,
  21. set_default_config/3,
  22. request/2,
  23. request/3,
  24. request/4,
  25. multipart_formdata_request/3,
  26. multipart_formdata_request/4,
  27. host/0,
  28. uri/0,
  29. uri/1
  30. ]).
  31. -define(HOST, "http://127.0.0.1:18083").
  32. -define(API_VERSION, "v5").
  33. -define(BASE_PATH, "api").
  34. set_default_config() ->
  35. set_default_config(<<"admin">>).
  36. set_default_config(DefaultUsername) ->
  37. set_default_config(DefaultUsername, false).
  38. set_default_config(DefaultUsername, HAProxyEnabled) ->
  39. set_default_config(DefaultUsername, HAProxyEnabled, #{}).
  40. set_default_config(DefaultUsername, HAProxyEnabled, Opts) ->
  41. Config = #{
  42. listeners => #{
  43. http => #{
  44. bind => maps:get(bind, Opts, 18083),
  45. inet6 => false,
  46. ipv6_v6only => false,
  47. max_connections => 512,
  48. num_acceptors => 4,
  49. send_timeout => 5000,
  50. backlog => 512,
  51. proxy_header => HAProxyEnabled
  52. }
  53. },
  54. default_username => DefaultUsername,
  55. default_password => <<"public">>,
  56. i18n_lang => en
  57. },
  58. emqx_config:put([dashboard], Config),
  59. ok.
  60. request(Method, Url) ->
  61. request(Method, Url, []).
  62. request(Method, Url, Body) ->
  63. request(<<"admin">>, Method, Url, Body).
  64. request(Username, Method, Url, Body) ->
  65. Request =
  66. case Body of
  67. [] when
  68. Method =:= get orelse Method =:= put orelse
  69. Method =:= head orelse Method =:= delete orelse
  70. Method =:= trace
  71. ->
  72. {Url, [auth_header(Username)]};
  73. _ ->
  74. {Url, [auth_header(Username)], "application/json", emqx_utils_json:encode(Body)}
  75. end,
  76. ct:pal("Method: ~p, Request: ~p", [Method, Request]),
  77. case httpc:request(Method, Request, [], [{body_format, binary}]) of
  78. {error, socket_closed_remotely} ->
  79. {error, socket_closed_remotely};
  80. {ok, {{"HTTP/1.1", Code, _}, _Headers, Return}} ->
  81. {ok, Code, Return};
  82. {ok, {Reason, _, _}} ->
  83. {error, Reason}
  84. end.
  85. host() ->
  86. ?HOST.
  87. uri() -> uri([]).
  88. uri(Parts) when is_list(Parts) ->
  89. NParts = [E || E <- Parts],
  90. host() ++ "/" ++ to_list(filename:join([?BASE_PATH, ?API_VERSION | NParts])).
  91. auth_header(Username) ->
  92. Password = <<"public">>,
  93. {ok, Token} = emqx_dashboard_admin:sign_token(Username, Password),
  94. {"Authorization", "Bearer " ++ binary_to_list(Token)}.
  95. multipart_formdata_request(Url, Fields, Files) ->
  96. multipart_formdata_request(Url, <<"admin">>, Fields, Files).
  97. multipart_formdata_request(Url, Username, Fields, Files) ->
  98. Boundary =
  99. "------------" ++ integer_to_list(rand:uniform(99999999999999999)) ++
  100. integer_to_list(erlang:system_time(millisecond)),
  101. Body = format_multipart_formdata(Boundary, Fields, Files),
  102. ContentType = lists:concat(["multipart/form-data; boundary=", Boundary]),
  103. Headers =
  104. [
  105. auth_header(Username),
  106. {"Content-Length", integer_to_list(length(Body))}
  107. ],
  108. case httpc:request(post, {Url, Headers, ContentType, Body}, [], []) of
  109. {error, socket_closed_remotely} ->
  110. {error, socket_closed_remotely};
  111. {ok, {{"HTTP/1.1", Code, _}, _Headers, Return}} ->
  112. {ok, Code, Return};
  113. {ok, {Reason, _, _}} ->
  114. {error, Reason}
  115. end.
  116. format_multipart_formdata(Boundary, Fields, Files) ->
  117. FieldParts = lists:map(
  118. fun({FieldName, FieldContent}) ->
  119. [
  120. lists:concat(["--", Boundary]),
  121. lists:concat([
  122. "Content-Disposition: form-data; name=\"", atom_to_list(FieldName), "\""
  123. ]),
  124. "",
  125. to_list(FieldContent)
  126. ]
  127. end,
  128. Fields
  129. ),
  130. FieldParts2 = lists:append(FieldParts),
  131. FileParts = lists:map(
  132. fun({FieldName, FileName, FileContent}) ->
  133. [
  134. lists:concat(["--", Boundary]),
  135. lists:concat([
  136. "Content-Disposition: form-data; name=\"",
  137. atom_to_list(FieldName),
  138. "\"; filename=\"",
  139. FileName,
  140. "\""
  141. ]),
  142. lists:concat(["Content-Type: ", "application/octet-stream"]),
  143. "",
  144. to_list(FileContent)
  145. ]
  146. end,
  147. Files
  148. ),
  149. FileParts2 = lists:append(FileParts),
  150. EndingParts = [lists:concat(["--", Boundary, "--"]), ""],
  151. Parts = lists:append([FieldParts2, FileParts2, EndingParts]),
  152. string:join(Parts, "\r\n").
  153. to_list(Bin) when is_binary(Bin) -> binary_to_list(Bin);
  154. to_list(Str) when is_list(Str) -> Str.