refactor: routes api

This commit is contained in:
DDDHuang 2021-07-19 10:17:37 +08:00
parent 4427ec8155
commit 14d9b876e7
2 changed files with 162 additions and 19 deletions

View File

@ -18,30 +18,108 @@
-include_lib("emqx/include/emqx.hrl"). -include_lib("emqx/include/emqx.hrl").
-rest_api(#{name => list_routes, %% API
method => 'GET', -behavior(minirest_api).
path => "/routes/",
func => list,
descr => "List routes"}).
-rest_api(#{name => lookup_routes, -export([api_spec/0]).
method => 'GET',
path => "/routes/:bin:topic",
func => lookup,
descr => "Lookup routes to a topic"}).
-export([ list/2 -export([ routes/2
, lookup/2 , route/2]).
]).
list(Bindings, Params) when map_size(Bindings) == 0 -> -define(TOPIC_NOT_FOUND, 'TOPIC_NOT_FOUND').
emqx_mgmt:return({ok, emqx_mgmt_api:paginate(emqx_route, Params, fun format/1)}).
lookup(#{topic := Topic}, _Params) -> api_spec() ->
Topic1 = emqx_mgmt_util:urldecode(Topic), {
emqx_mgmt:return({ok, [format(R) || R <- emqx_mgmt:lookup_routes(Topic1)]}). [routes_api(), route_api()],
[route_schema()]
}.
route_schema() ->
#{
route => #{
type => object,
properties => #{
topic => #{
type => string},
node => #{
type => string,
example => node()}}}}.
routes_api() ->
Metadata = #{
get => #{
description => "EMQ X routes",
parameters => [
#{
name => page,
in => query,
description => <<"Page">>,
schema => #{type => integer},
default => 1
},
#{
name => limit,
in => query,
description => <<"Page size">>,
schema => #{type => integer},
default => emqx_mgmt:max_row_limit()
}],
responses => #{
<<"200">> =>
emqx_mgmt_util:response_array_schema("List route info", <<"route">>)}}},
{"/routes", Metadata, routes}.
route_api() ->
Metadata = #{
get => #{
description => "EMQ X routes",
parameters => [#{
name => topic,
in => path,
required => true,
description => <<"topic">>,
schema => #{type => string}
}],
responses => #{
<<"200">> =>
emqx_mgmt_util:response_schema(<<"Route info">>, <<"route">>),
<<"404">> =>
emqx_mgmt_util:not_found_schema(<<"Topic not found">>, [?TOPIC_NOT_FOUND])
}}},
{"/routes/:topic", Metadata, route}.
%%%==============================================================================================
%% parameters trans
routes(get, Request) ->
Params = cowboy_req:parse_qs(Request),
list(Params).
route(get, Request) ->
Topic = cowboy_req:binding(topic, Request),
lookup(#{topic => Topic}).
%%%==============================================================================================
%% api apply
list(Params) ->
Data = emqx_mgmt_api:paginate(emqx_route, Params, fun format/1),
Response = emqx_json:encode(Data),
{200, Response}.
lookup(#{topic := Topic}) ->
case emqx_mgmt:lookup_routes(Topic) of
[] ->
NotFound = #{code => ?TOPIC_NOT_FOUND, reason => <<"Topic not found">>},
Response = emqx_json:encode(NotFound),
{404, Response};
[Route] ->
Data = format(Route),
Response = emqx_json:encode(Data),
{200, Response}
end.
%%%==============================================================================================
%% internal
format(#route{topic = Topic, dest = {_, Node}}) -> format(#route{topic = Topic, dest = {_, Node}}) ->
#{topic => Topic, node => Node}; #{topic => Topic, node => Node};
format(#route{topic = Topic, dest = Node}) -> format(#route{topic = Topic, dest = Node}) ->
#{topic => Topic, node => Node}. #{topic => Topic, node => Node}.

View File

@ -0,0 +1,65 @@
%%--------------------------------------------------------------------
%% Copyright (c) 2020-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_mgmt_routes_api_SUITE).
-compile(export_all).
-compile(nowarn_export_all).
-include_lib("eunit/include/eunit.hrl").
all() ->
emqx_ct:all(?MODULE).
init_per_suite(Config) ->
ekka_mnesia:start(),
emqx_mgmt_auth:mnesia(boot),
emqx_ct_helpers:start_apps([emqx_management], fun set_special_configs/1),
Config.
end_per_suite(_) ->
emqx_ct_helpers:stop_apps([emqx_management]).
set_special_configs(emqx_management) ->
emqx_config:put([emqx_management], #{listeners => [#{protocol => http, port => 8081}],
applications =>[#{id => "admin", secret => "public"}]}),
ok;
set_special_configs(_App) ->
ok.
t_nodes_api(_) ->
Topic = <<"test_topic">>,
{ok, Client} = emqtt:start_link(#{username => <<"routes_username">>, clientid => <<"routes_cid">>}),
{ok, _} = emqtt:connect(Client),
{ok, _, _} = emqtt:subscribe(Client, Topic),
Path = emqx_mgmt_api_test_util:api_path(["routes"]),
{ok, Response} = emqx_mgmt_api_test_util:request_api(get, Path),
RoutesData = emqx_json:decode(Response, [return_maps]),
Meta = maps:get(<<"meta">>, RoutesData),
?assertEqual(1, maps:get(<<"page">>, Meta)),
?assertEqual(emqx_mgmt:max_row_limit(), maps:get(<<"limit">>, Meta)),
?assertEqual(1, maps:get(<<"count">>, Meta)),
Data = maps:get(<<"data">>, RoutesData),
Route = erlang:hd(Data),
?assertEqual(Topic, maps:get(<<"topic">>, Route)),
?assertEqual(atom_to_binary(node(), utf8), maps:get(<<"node">>, Route)),
%% get routes/:topic
RoutePath = emqx_mgmt_api_test_util:api_path(["routes", Topic]),
{ok, RouteResponse} = emqx_mgmt_api_test_util:request_api(get, RoutePath),
RouteData = emqx_json:decode(RouteResponse, [return_maps]),
?assertEqual(Topic, maps:get(<<"topic">>, RouteData)),
?assertEqual(atom_to_binary(node(), utf8), maps:get(<<"node">>, RouteData)).