refactor: routes api
This commit is contained in:
parent
4427ec8155
commit
14d9b876e7
|
@ -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}.
|
||||||
|
|
||||||
|
|
|
@ -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)).
|
Loading…
Reference in New Issue