chore(gw): add listeners apis
This commit is contained in:
parent
9fd9e09721
commit
18ed1c9794
|
@ -20,6 +20,11 @@
|
||||||
|
|
||||||
-import(emqx_gateway_http,
|
-import(emqx_gateway_http,
|
||||||
[ return_http_error/2
|
[ return_http_error/2
|
||||||
|
, with_gateway/2
|
||||||
|
, schema_bad_request/0
|
||||||
|
, schema_not_found/0
|
||||||
|
, schema_internal_error/0
|
||||||
|
, schema_no_content/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%% minirest behaviour callbacks
|
%% minirest behaviour callbacks
|
||||||
|
@ -55,44 +60,34 @@ gateway(get, Request) ->
|
||||||
{200, emqx_gateway_http:gateways(Status)}.
|
{200, emqx_gateway_http:gateways(Status)}.
|
||||||
|
|
||||||
gateway_insta(delete, #{bindings := #{name := Name0}}) ->
|
gateway_insta(delete, #{bindings := #{name := Name0}}) ->
|
||||||
Name = binary_to_existing_atom(Name0),
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
case emqx_gateway:unload(Name) of
|
_ = emqx_gateway:unload(GwName),
|
||||||
ok ->
|
{204}
|
||||||
{204};
|
end);
|
||||||
{error, not_found} ->
|
|
||||||
return_http_error(404, <<"Gateway not found">>)
|
|
||||||
end;
|
|
||||||
gateway_insta(get, #{bindings := #{name := Name0}}) ->
|
gateway_insta(get, #{bindings := #{name := Name0}}) ->
|
||||||
Name = binary_to_existing_atom(Name0),
|
with_gateway(Name0, fun(_, _) ->
|
||||||
case emqx_gateway:lookup(Name) of
|
GwConf = filled_raw_confs([<<"gateway">>, Name0]),
|
||||||
#{config := _Config} ->
|
LisConf = maps:get(<<"listeners">>, GwConf, #{}),
|
||||||
GwCfs = filled_raw_confs([<<"gateway">>, Name0]),
|
NLisConf = emqx_gateway_http:mapping_listener_m2l(Name0, LisConf),
|
||||||
NGwCfs = GwCfs#{<<"listeners">> =>
|
{200, GwConf#{<<"listeners">> => NLisConf}}
|
||||||
emqx_gateway_http:mapping_listener_m2l(
|
end);
|
||||||
Name0, maps:get(<<"listeners">>, GwCfs, #{})
|
gateway_insta(put, #{body := GwConf0,
|
||||||
)
|
bindings := #{name := Name0}
|
||||||
},
|
|
||||||
{200, NGwCfs};
|
|
||||||
undefined ->
|
|
||||||
return_http_error(404, <<"Gateway not found">>)
|
|
||||||
end;
|
|
||||||
gateway_insta(put, #{body := RawConfsIn0,
|
|
||||||
bindings := #{name := Name}
|
|
||||||
}) ->
|
}) ->
|
||||||
RawConfsIn = maps:without([<<"authentication">>,
|
with_gateway(Name0, fun(_, _) ->
|
||||||
<<"listeners">>], RawConfsIn0),
|
GwConf = maps:without([<<"authentication">>, <<"listeners">>], GwConf0),
|
||||||
%% FIXME: Cluster Consistence ??
|
case emqx_gateway:update_rawconf(Name0, GwConf) of
|
||||||
case emqx_gateway:update_rawconf(Name, RawConfsIn) of
|
|
||||||
ok ->
|
ok ->
|
||||||
{200};
|
{200};
|
||||||
{error, not_found} ->
|
{error, not_found} ->
|
||||||
return_http_error(404, <<"Gateway not found">>);
|
return_http_error(404, "Gateway not found");
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
return_http_error(500, Reason)
|
return_http_error(500, Reason)
|
||||||
end.
|
end
|
||||||
|
end).
|
||||||
|
|
||||||
gateway_insta_stats(get, _Req) ->
|
gateway_insta_stats(get, _Req) ->
|
||||||
return_http_error(401, <<"Implement it later (maybe 5.1)">>).
|
return_http_error(401, "Implement it later (maybe 5.1)").
|
||||||
|
|
||||||
filled_raw_confs(Path) ->
|
filled_raw_confs(Path) ->
|
||||||
RawConf = emqx_config:fill_defaults(
|
RawConf = emqx_config:fill_defaults(
|
||||||
|
@ -131,7 +126,9 @@ swagger("/gateway/:name", get) ->
|
||||||
#{ description => <<"Get the gateway configurations">>
|
#{ description => <<"Get the gateway configurations">>
|
||||||
, parameters => params_gateway_name_in_path()
|
, parameters => params_gateway_name_in_path()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_gateway_conf()
|
, <<"200">> => schema_gateway_conf()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -139,7 +136,9 @@ swagger("/gateway/:name", delete) ->
|
||||||
#{ description => <<"Delete/Unload the gateway">>
|
#{ description => <<"Delete/Unload the gateway">>
|
||||||
, parameters => params_gateway_name_in_path()
|
, parameters => params_gateway_name_in_path()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"204">> => schema_no_content()
|
, <<"204">> => schema_no_content()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -148,7 +147,9 @@ swagger("/gateway/:name", put) ->
|
||||||
, parameters => params_gateway_name_in_path()
|
, parameters => params_gateway_name_in_path()
|
||||||
, requestBody => schema_gateway_conf()
|
, requestBody => schema_gateway_conf()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_no_content()
|
, <<"200">> => schema_no_content()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -156,7 +157,9 @@ swagger("/gateway/:name/stats", get) ->
|
||||||
#{ description => <<"Get gateway Statistic">>
|
#{ description => <<"Get gateway Statistic">>
|
||||||
, parameters => params_gateway_name_in_path()
|
, parameters => params_gateway_name_in_path()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_gateway_stats()
|
, <<"200">> => schema_gateway_stats()
|
||||||
}
|
}
|
||||||
}.
|
}.
|
||||||
|
@ -181,12 +184,6 @@ params_gateway_status_in_qs() ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% schemas
|
%% schemas
|
||||||
|
|
||||||
schema_not_found() ->
|
|
||||||
emqx_mgmt_util:error_schema(<<"Gateway not found or unloaded">>).
|
|
||||||
|
|
||||||
schema_no_content() ->
|
|
||||||
#{description => <<"No Content">>}.
|
|
||||||
|
|
||||||
schema_gateway_overview_list() ->
|
schema_gateway_overview_list() ->
|
||||||
emqx_mgmt_util:array_schema(
|
emqx_mgmt_util:array_schema(
|
||||||
#{ type => object
|
#{ type => object
|
||||||
|
|
|
@ -36,6 +36,11 @@
|
||||||
|
|
||||||
-import(emqx_gateway_http,
|
-import(emqx_gateway_http,
|
||||||
[ return_http_error/2
|
[ return_http_error/2
|
||||||
|
, with_gateway/2
|
||||||
|
, schema_bad_request/0
|
||||||
|
, schema_not_found/0
|
||||||
|
, schema_internal_error/0
|
||||||
|
, schema_no_content/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -71,10 +76,10 @@ apis() ->
|
||||||
-define(query_fun, {?MODULE, query}).
|
-define(query_fun, {?MODULE, query}).
|
||||||
-define(format_fun, {?MODULE, format_channel_info}).
|
-define(format_fun, {?MODULE, format_channel_info}).
|
||||||
|
|
||||||
clients(get, #{ bindings := #{name := GwName0}
|
clients(get, #{ bindings := #{name := Name0}
|
||||||
, query_string := Qs
|
, query_string := Qs
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
TabName = emqx_gateway_cm:tabname(info, GwName),
|
TabName = emqx_gateway_cm:tabname(info, GwName),
|
||||||
case maps:get(<<"node">>, Qs, undefined) of
|
case maps:get(<<"node">>, Qs, undefined) of
|
||||||
undefined ->
|
undefined ->
|
||||||
|
@ -91,14 +96,14 @@ clients(get, #{ bindings := #{name := GwName0}
|
||||||
TabName, ?CLIENT_QS_SCHEMA, ?query_fun
|
TabName, ?CLIENT_QS_SCHEMA, ?query_fun
|
||||||
),
|
),
|
||||||
{200, Response}
|
{200, Response}
|
||||||
end.
|
end
|
||||||
|
end).
|
||||||
|
|
||||||
clients_insta(get, #{ bindings := #{name := GwName0,
|
clients_insta(get, #{ bindings := #{name := Name0,
|
||||||
clientid := ClientId0}
|
clientid := ClientId0}
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
|
||||||
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
case emqx_gateway_http:lookup_client(GwName, ClientId,
|
case emqx_gateway_http:lookup_client(GwName, ClientId,
|
||||||
{?MODULE, format_channel_info}) of
|
{?MODULE, format_channel_info}) of
|
||||||
[ClientInfo] ->
|
[ClientInfo] ->
|
||||||
|
@ -108,45 +113,44 @@ clients_insta(get, #{ bindings := #{name := GwName0,
|
||||||
[ClientId]),
|
[ClientId]),
|
||||||
{200, ClientInfo};
|
{200, ClientInfo};
|
||||||
[] ->
|
[] ->
|
||||||
return_http_error(404, <<"Gateway or ClientId not found">>)
|
return_http_error(404, "Client not found")
|
||||||
|
end
|
||||||
end;
|
end);
|
||||||
|
clients_insta(delete, #{ bindings := #{name := Name0,
|
||||||
clients_insta(delete, #{ bindings := #{name := GwName0,
|
|
||||||
clientid := ClientId0}
|
clientid := ClientId0}
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
|
||||||
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
_ = emqx_gateway_http:kickout_client(GwName, ClientId),
|
_ = emqx_gateway_http:kickout_client(GwName, ClientId),
|
||||||
{200}.
|
{200}
|
||||||
|
end).
|
||||||
|
|
||||||
%% FIXME:
|
%% FIXME:
|
||||||
%% List the subscription without mountpoint, but has SubOpts,
|
%% List the subscription without mountpoint, but has SubOpts,
|
||||||
%% for example, share group ...
|
%% for example, share group ...
|
||||||
subscriptions(get, #{ bindings := #{name := GwName0,
|
subscriptions(get, #{ bindings := #{name := Name0,
|
||||||
clientid := ClientId0}
|
clientid := ClientId0}
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
|
||||||
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
case emqx_gateway_http:list_client_subscriptions(GwName, ClientId) of
|
case emqx_gateway_http:list_client_subscriptions(GwName, ClientId) of
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
return_http_error(404, Reason);
|
return_http_error(500, Reason);
|
||||||
{ok, Subs} ->
|
{ok, Subs} ->
|
||||||
{200, Subs}
|
{200, Subs}
|
||||||
end;
|
end
|
||||||
|
end);
|
||||||
|
|
||||||
%% Create the subscription without mountpoint
|
%% Create the subscription without mountpoint
|
||||||
subscriptions(post, #{ bindings := #{name := GwName0,
|
subscriptions(post, #{ bindings := #{name := Name0,
|
||||||
clientid := ClientId0},
|
clientid := ClientId0},
|
||||||
body := Body
|
body := Body
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
|
||||||
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
case {maps:get(<<"topic">>, Body, undefined), subopts(Body)} of
|
case {maps:get(<<"topic">>, Body, undefined), subopts(Body)} of
|
||||||
{undefined, _} ->
|
{undefined, _} ->
|
||||||
%% FIXME: more reasonable error code??
|
return_http_error(400, "Miss topic property");
|
||||||
return_http_error(404, <<"Request paramter missed: topic">>);
|
|
||||||
{Topic, QoS} ->
|
{Topic, QoS} ->
|
||||||
case emqx_gateway_http:client_subscribe(GwName, ClientId, Topic, QoS) of
|
case emqx_gateway_http:client_subscribe(GwName, ClientId, Topic, QoS) of
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
|
@ -154,19 +158,21 @@ subscriptions(post, #{ bindings := #{name := GwName0,
|
||||||
ok ->
|
ok ->
|
||||||
{200}
|
{200}
|
||||||
end
|
end
|
||||||
end;
|
end
|
||||||
|
end);
|
||||||
|
|
||||||
%% Remove the subscription without mountpoint
|
%% Remove the subscription without mountpoint
|
||||||
subscriptions(delete, #{ bindings := #{name := GwName0,
|
subscriptions(delete, #{ bindings := #{name := Name0,
|
||||||
clientid := ClientId0,
|
clientid := ClientId0,
|
||||||
topic := Topic0
|
topic := Topic0
|
||||||
}
|
}
|
||||||
}) ->
|
}) ->
|
||||||
GwName = binary_to_existing_atom(GwName0),
|
|
||||||
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
ClientId = emqx_mgmt_util:urldecode(ClientId0),
|
||||||
Topic = emqx_mgmt_util:urldecode(Topic0),
|
Topic = emqx_mgmt_util:urldecode(Topic0),
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
_ = emqx_gateway_http:client_unsubscribe(GwName, ClientId, Topic),
|
_ = emqx_gateway_http:client_unsubscribe(GwName, ClientId, Topic),
|
||||||
{200}.
|
{200}
|
||||||
|
end).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Utils
|
%% Utils
|
||||||
|
@ -379,7 +385,9 @@ swagger("/gateway/:name/clients", get) ->
|
||||||
#{ description => <<"Get the gateway clients">>
|
#{ description => <<"Get the gateway clients">>
|
||||||
, parameters => params_client_query()
|
, parameters => params_client_query()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_clients_list()
|
, <<"200">> => schema_clients_list()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -387,7 +395,9 @@ swagger("/gateway/:name/clients/:clientid", get) ->
|
||||||
#{ description => <<"Get the gateway client infomation">>
|
#{ description => <<"Get the gateway client infomation">>
|
||||||
, parameters => params_client_insta()
|
, parameters => params_client_insta()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_client()
|
, <<"200">> => schema_client()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -395,7 +405,9 @@ swagger("/gateway/:name/clients/:clientid", delete) ->
|
||||||
#{ description => <<"Kick out the gateway client">>
|
#{ description => <<"Kick out the gateway client">>
|
||||||
, parameters => params_client_insta()
|
, parameters => params_client_insta()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"204">> => schema_no_content()
|
, <<"204">> => schema_no_content()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -403,7 +415,9 @@ swagger("/gateway/:name/clients/:clientid/subscriptions", get) ->
|
||||||
#{ description => <<"Get the gateway client subscriptions">>
|
#{ description => <<"Get the gateway client subscriptions">>
|
||||||
, parameters => params_client_insta()
|
, parameters => params_client_insta()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_subscription_list()
|
, <<"200">> => schema_subscription_list()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -412,7 +426,9 @@ swagger("/gateway/:name/clients/:clientid/subscriptions", post) ->
|
||||||
, parameters => params_client_insta()
|
, parameters => params_client_insta()
|
||||||
, requestBody => schema_subscription()
|
, requestBody => schema_subscription()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"200">> => schema_no_content()
|
, <<"200">> => schema_no_content()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -420,7 +436,9 @@ swagger("/gateway/:name/clients/:clientid/subscriptions/:topic", delete) ->
|
||||||
#{ description => <<"Unsubscribe the topic for client">>
|
#{ description => <<"Unsubscribe the topic for client">>
|
||||||
, parameters => params_topic_name_in_path() ++ params_client_insta()
|
, parameters => params_topic_name_in_path() ++ params_client_insta()
|
||||||
, responses =>
|
, responses =>
|
||||||
#{ <<"404">> => schema_not_found()
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
, <<"204">> => schema_no_content()
|
, <<"204">> => schema_no_content()
|
||||||
}
|
}
|
||||||
}.
|
}.
|
||||||
|
@ -483,12 +501,6 @@ queries(Ls) ->
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% schemas
|
%% schemas
|
||||||
|
|
||||||
schema_not_found() ->
|
|
||||||
emqx_mgmt_util:error_schema(<<"Gateway not found or unloaded">>).
|
|
||||||
|
|
||||||
schema_no_content() ->
|
|
||||||
#{description => <<"No Content">>}.
|
|
||||||
|
|
||||||
schema_clients_list() ->
|
schema_clients_list() ->
|
||||||
emqx_mgmt_util:page_schema(
|
emqx_mgmt_util:page_schema(
|
||||||
#{ type => object
|
#{ type => object
|
||||||
|
|
|
@ -0,0 +1,316 @@
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% 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_gateway_api_listeners).
|
||||||
|
|
||||||
|
-behaviour(minirest_api).
|
||||||
|
|
||||||
|
-import(emqx_gateway_http,
|
||||||
|
[ return_http_error/2
|
||||||
|
, with_gateway/2
|
||||||
|
, checks/2
|
||||||
|
, schema_bad_request/0
|
||||||
|
, schema_not_found/0
|
||||||
|
, schema_internal_error/0
|
||||||
|
, schema_no_content/0
|
||||||
|
]).
|
||||||
|
|
||||||
|
%% minirest behaviour callbacks
|
||||||
|
-export([api_spec/0]).
|
||||||
|
|
||||||
|
%% http handlers
|
||||||
|
-export([ listeners/2
|
||||||
|
, listeners_insta/2
|
||||||
|
]).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% minirest behaviour callbacks
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
api_spec() ->
|
||||||
|
{metadata(apis()), []}.
|
||||||
|
|
||||||
|
apis() ->
|
||||||
|
[ {"/gateway/:name/listeners", listeners}
|
||||||
|
, {"/gateway/:name/listeners/:id", listeners_insta}
|
||||||
|
].
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% http handlers
|
||||||
|
|
||||||
|
listeners(get, #{bindings := #{name := Name0}}) ->
|
||||||
|
with_gateway(Name0, fun(GwName, _) ->
|
||||||
|
{200, emqx_gateway_http:listeners(GwName)}
|
||||||
|
end);
|
||||||
|
|
||||||
|
listeners(post, #{bindings := #{name := Name0}, body := LConf}) ->
|
||||||
|
with_gateway(Name0, fun(GwName, Gateway) ->
|
||||||
|
RunningConf = maps:get(config, Gateway),
|
||||||
|
%% XXX: check params miss? check badly data tpye??
|
||||||
|
_ = checks([<<"type">>, <<"name">>, <<"bind">>], LConf),
|
||||||
|
|
||||||
|
Type = binary_to_existing_atom(maps:get(<<"type">>, LConf)),
|
||||||
|
LName = binary_to_atom(maps:get(<<"name">>, LConf)),
|
||||||
|
|
||||||
|
Path = [listeners, Type, LName],
|
||||||
|
case emqx_map_lib:deep_get(Path, RunningConf, undefined) of
|
||||||
|
undefined ->
|
||||||
|
ListenerId = emqx_gateway_utils:listener_id(
|
||||||
|
GwName, Type, LName),
|
||||||
|
case emqx_gateway_http:update_listener(
|
||||||
|
ListenerId, LConf) of
|
||||||
|
ok ->
|
||||||
|
{204};
|
||||||
|
{error, Reason} ->
|
||||||
|
return_http_error(500, Reason)
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
return_http_error(400, "Listener name has occupied")
|
||||||
|
end
|
||||||
|
end).
|
||||||
|
|
||||||
|
listeners_insta(delete, #{bindings := #{name := Name0, id := ListenerId0}}) ->
|
||||||
|
ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
|
||||||
|
with_gateway(Name0, fun(_GwName, _) ->
|
||||||
|
case emqx_gateway_http:remove_listener(ListenerId) of
|
||||||
|
ok -> {204};
|
||||||
|
{error, not_found} -> {204};
|
||||||
|
{error, Reason} ->
|
||||||
|
return_http_error(500, Reason)
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
listeners_insta(get, #{bindings := #{name := Name0, id := ListenerId0}}) ->
|
||||||
|
ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
|
||||||
|
with_gateway(Name0, fun(_GwName, _) ->
|
||||||
|
case emqx_gateway_http:listener(ListenerId) of
|
||||||
|
{ok, Listener} ->
|
||||||
|
{200, Listener};
|
||||||
|
{error, not_found} ->
|
||||||
|
return_http_error(404, "Listener not found");
|
||||||
|
{error, Reason} ->
|
||||||
|
return_http_error(500, Reason)
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
listeners_insta(put, #{body := LConf,
|
||||||
|
bindings := #{name := Name0, id := ListenerId0}
|
||||||
|
}) ->
|
||||||
|
ListenerId = emqx_mgmt_util:urldecode(ListenerId0),
|
||||||
|
with_gateway(Name0, fun(_GwName, _) ->
|
||||||
|
case emqx_gateway_http:update_listener(ListenerId, LConf) of
|
||||||
|
ok ->
|
||||||
|
{204};
|
||||||
|
{error, Reason} ->
|
||||||
|
return_http_error(500, Reason)
|
||||||
|
end
|
||||||
|
end).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% Swagger defines
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
metadata(APIs) ->
|
||||||
|
metadata(APIs, []).
|
||||||
|
metadata([], APIAcc) ->
|
||||||
|
lists:reverse(APIAcc);
|
||||||
|
metadata([{Path, Fun}|More], APIAcc) ->
|
||||||
|
Methods = [get, post, put, delete, patch],
|
||||||
|
Mds = lists:foldl(fun(M, Acc) ->
|
||||||
|
try
|
||||||
|
Acc#{M => swagger(Path, M)}
|
||||||
|
catch
|
||||||
|
error : function_clause ->
|
||||||
|
Acc
|
||||||
|
end
|
||||||
|
end, #{}, Methods),
|
||||||
|
metadata(More, [{Path, Mds, Fun} | APIAcc]).
|
||||||
|
|
||||||
|
swagger("/gateway/:name/listeners", get) ->
|
||||||
|
#{ description => <<"Get the gateway listeners">>
|
||||||
|
, parameters => params_gateway_name_in_path()
|
||||||
|
, responses =>
|
||||||
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
|
, <<"200">> => schema_listener_list()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
swagger("/gateway/:name/listeners", post) ->
|
||||||
|
#{ description => <<"Create the gateway listener">>
|
||||||
|
, parameters => params_gateway_name_in_path()
|
||||||
|
, requestBody => schema_listener()
|
||||||
|
, responses =>
|
||||||
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
|
, <<"200">> => schema_listener_list()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
swagger("/gateway/:name/listeners/:id", get) ->
|
||||||
|
#{ description => <<"Get the gateway listener configurations">>
|
||||||
|
, parameters => params_gateway_name_in_path()
|
||||||
|
++ params_listener_id_in_path()
|
||||||
|
, responses =>
|
||||||
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
|
, <<"200">> => schema_listener()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
swagger("/gateway/:name/listeners/:id", delete) ->
|
||||||
|
#{ description => <<"Delete the gateway listener">>
|
||||||
|
, parameters => params_gateway_name_in_path()
|
||||||
|
++ params_listener_id_in_path()
|
||||||
|
, responses =>
|
||||||
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
|
, <<"204">> => schema_no_content()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
swagger("/gateway/:name/listeners/:id", put) ->
|
||||||
|
#{ description => <<"Update the gateway listener">>
|
||||||
|
, parameters => params_gateway_name_in_path()
|
||||||
|
++ params_listener_id_in_path()
|
||||||
|
, requestBody => schema_listener()
|
||||||
|
, responses =>
|
||||||
|
#{ <<"400">> => schema_bad_request()
|
||||||
|
, <<"404">> => schema_not_found()
|
||||||
|
, <<"500">> => schema_internal_error()
|
||||||
|
, <<"200">> => schema_no_content()
|
||||||
|
}
|
||||||
|
}.
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% params defines
|
||||||
|
|
||||||
|
params_gateway_name_in_path() ->
|
||||||
|
[#{ name => name
|
||||||
|
, in => path
|
||||||
|
, schema => #{type => string}
|
||||||
|
, required => true
|
||||||
|
}].
|
||||||
|
|
||||||
|
params_listener_id_in_path() ->
|
||||||
|
[#{ name => id
|
||||||
|
, in => path
|
||||||
|
, schema => #{type => string}
|
||||||
|
, required => true
|
||||||
|
}].
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% schemas
|
||||||
|
|
||||||
|
schema_listener_list() ->
|
||||||
|
emqx_mgmt_util:array_schema(
|
||||||
|
#{ type => object
|
||||||
|
, properties => properties_listener()
|
||||||
|
},
|
||||||
|
<<"Listener list">>
|
||||||
|
).
|
||||||
|
|
||||||
|
schema_listener() ->
|
||||||
|
emqx_mgmt_util:schema(
|
||||||
|
#{ type => object
|
||||||
|
, properties => properties_listener()
|
||||||
|
}
|
||||||
|
).
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% properties
|
||||||
|
|
||||||
|
properties_listener() ->
|
||||||
|
emqx_mgmt_util:properties(
|
||||||
|
raw_properties_common_listener() ++
|
||||||
|
[ {tcp, object, raw_properties_tcp_opts()}
|
||||||
|
, {ssl, object, raw_properties_ssl_opts()}
|
||||||
|
, {udp, object, raw_properties_udp_opts()}
|
||||||
|
, {dtls, object, raw_properties_dtls_opts()}
|
||||||
|
]).
|
||||||
|
|
||||||
|
raw_properties_tcp_opts() ->
|
||||||
|
[ {active_n, integer, <<>>}
|
||||||
|
, {backlog, integer, <<>>}
|
||||||
|
, {buffer, string, <<>>}
|
||||||
|
, {recbuf, string, <<>>}
|
||||||
|
, {sndbuf, string, <<>>}
|
||||||
|
, {high_watermark, string, <<>>}
|
||||||
|
, {nodelay, boolean, <<>>}
|
||||||
|
, {reuseaddr, boolean, <<>>}
|
||||||
|
, {send_timeout, string, <<>>}
|
||||||
|
, {send_timeout_close, boolean, <<>>}
|
||||||
|
].
|
||||||
|
|
||||||
|
raw_properties_ssl_opts() ->
|
||||||
|
[ {cacertfile, string, <<>>}
|
||||||
|
, {certfile, string, <<>>}
|
||||||
|
, {keyfile, string, <<>>}
|
||||||
|
, {verify, string, <<>>}
|
||||||
|
, {fail_if_no_peer_cert, boolean, <<>>}
|
||||||
|
, {server_name_indication, boolean, <<>>}
|
||||||
|
, {depth, integer, <<>>}
|
||||||
|
, {password, string, <<>>}
|
||||||
|
, {handshake_timeout, string, <<>>}
|
||||||
|
, {versions, {array, string}, <<>>}
|
||||||
|
, {ciphers, {array, string}, <<>>}
|
||||||
|
, {user_lookup_fun, string, <<>>}
|
||||||
|
, {reuse_sessions, boolean, <<>>}
|
||||||
|
, {secure_renegotiate, boolean, <<>>}
|
||||||
|
, {honor_cipher_order, boolean, <<>>}
|
||||||
|
, {dhfile, string, <<>>}
|
||||||
|
].
|
||||||
|
|
||||||
|
raw_properties_udp_opts() ->
|
||||||
|
[ {active_n, integer, <<>>}
|
||||||
|
, {buffer, string, <<>>}
|
||||||
|
, {recbuf, string, <<>>}
|
||||||
|
, {sndbuf, string, <<>>}
|
||||||
|
, {reuseaddr, boolean, <<>>}
|
||||||
|
].
|
||||||
|
|
||||||
|
raw_properties_dtls_opts() ->
|
||||||
|
Ls = lists_key_without(
|
||||||
|
[versions,ciphers,handshake_timeout], 1,
|
||||||
|
raw_properties_ssl_opts()
|
||||||
|
),
|
||||||
|
[ {versions, {array, string}, <<>>}
|
||||||
|
, {ciphers, {array, string}, <<>>}
|
||||||
|
| Ls].
|
||||||
|
|
||||||
|
lists_key_without([], _N, L) ->
|
||||||
|
L;
|
||||||
|
lists_key_without([K|Ks], N, L) ->
|
||||||
|
lists_key_without(Ks, N, lists:keydelete(K, N, L)).
|
||||||
|
|
||||||
|
raw_properties_common_listener() ->
|
||||||
|
[ {enable, boolean, <<"Whether to enable this listener">>}
|
||||||
|
, {id, string, <<"Listener Id">>}
|
||||||
|
, {name, string, <<"Listener name">>}
|
||||||
|
, {type, string,
|
||||||
|
<<"Listener type. Enum: tcp, udp, ssl, dtls">>,
|
||||||
|
[<<"tcp">>, <<"ssl">>, <<"udp">>, <<"dtls">>]}
|
||||||
|
, {running, boolean, <<"Listener running status">>}
|
||||||
|
%% FIXME:
|
||||||
|
, {bind, string, <<"Listener bind address or port">>}
|
||||||
|
, {acceptors, integer, <<"Listener acceptors number">>}
|
||||||
|
, {access_rules, {array, string}, <<"Listener Access rules for client">>}
|
||||||
|
, {max_conn_rate, integer, <<"Max connection rate for the listener">>}
|
||||||
|
, {max_connections, integer, <<"Max connections for the listener">>}
|
||||||
|
, {mountpoint, string,
|
||||||
|
<<"The Mounpoint for clients of the listener. "
|
||||||
|
"The gateway-level mountpoint configuration can be overloaded "
|
||||||
|
"when it is not null or empty string">>}
|
||||||
|
%% FIXME:
|
||||||
|
, {authentication, string, <<"NOT-SUPPORTED-NOW">>}
|
||||||
|
].
|
|
@ -26,7 +26,9 @@
|
||||||
|
|
||||||
%% Mgmt APIs - listeners
|
%% Mgmt APIs - listeners
|
||||||
-export([ listeners/1
|
-export([ listeners/1
|
||||||
, listener/2
|
, listener/1
|
||||||
|
, remove_listener/1
|
||||||
|
, update_listener/2
|
||||||
, mapping_listener_m2l/2
|
, mapping_listener_m2l/2
|
||||||
]).
|
]).
|
||||||
|
|
||||||
|
@ -42,6 +44,12 @@
|
||||||
|
|
||||||
%% Utils for http, swagger, etc.
|
%% Utils for http, swagger, etc.
|
||||||
-export([ return_http_error/2
|
-export([ return_http_error/2
|
||||||
|
, with_gateway/2
|
||||||
|
, checks/2
|
||||||
|
, schema_bad_request/0
|
||||||
|
, schema_not_found/0
|
||||||
|
, schema_internal_error/0
|
||||||
|
, schema_no_content/0
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-type gateway_summary() ::
|
-type gateway_summary() ::
|
||||||
|
@ -108,7 +116,7 @@ get_listeners_status(GwName, Config) ->
|
||||||
lists:map(fun({Type, LisName, ListenOn, _, _}) ->
|
lists:map(fun({Type, LisName, ListenOn, _, _}) ->
|
||||||
Name0 = emqx_gateway_utils:listener_id(GwName, Type, LisName),
|
Name0 = emqx_gateway_utils:listener_id(GwName, Type, LisName),
|
||||||
Name = {Name0, ListenOn},
|
Name = {Name0, ListenOn},
|
||||||
LisO = #{id => Name0, type => Type},
|
LisO = #{id => Name0, type => Type, name => LisName},
|
||||||
case catch esockd:listener(Name) of
|
case catch esockd:listener(Name) of
|
||||||
_Pid when is_pid(_Pid) ->
|
_Pid when is_pid(_Pid) ->
|
||||||
LisO#{running => true};
|
LisO#{running => true};
|
||||||
|
@ -121,6 +129,7 @@ get_listeners_status(GwName, Config) ->
|
||||||
%% Mgmt APIs - listeners
|
%% Mgmt APIs - listeners
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
|
||||||
|
-spec listeners(atom() | binary()) -> list().
|
||||||
listeners(GwName) when is_atom(GwName) ->
|
listeners(GwName) when is_atom(GwName) ->
|
||||||
listeners(atom_to_binary(GwName));
|
listeners(atom_to_binary(GwName));
|
||||||
listeners(GwName) ->
|
listeners(GwName) ->
|
||||||
|
@ -131,8 +140,27 @@ listeners(GwName) ->
|
||||||
[<<"gateway">>, GwName, <<"listeners">>], RawConf)),
|
[<<"gateway">>, GwName, <<"listeners">>], RawConf)),
|
||||||
mapping_listener_m2l(GwName, Listeners).
|
mapping_listener_m2l(GwName, Listeners).
|
||||||
|
|
||||||
listener(_GwName, _ListenerId) ->
|
-spec listener(binary()) -> {ok, map()} | {error, not_found} | {error, any()}.
|
||||||
ok.
|
listener(ListenerId) ->
|
||||||
|
{GwName, Type, LName} = emqx_gateway_utils:parse_listener_id(ListenerId),
|
||||||
|
RootConf = emqx_config:fill_defaults(
|
||||||
|
emqx_config:get_root_raw([<<"gateway">>])),
|
||||||
|
try
|
||||||
|
Path = [<<"gateway">>, GwName, <<"listeners">>, Type, LName],
|
||||||
|
LConf = emqx_map_lib:deep_get(Path, RootConf),
|
||||||
|
Running = is_running(binary_to_existing_atom(ListenerId), LConf),
|
||||||
|
{ok, emqx_map_lib:jsonable_map(
|
||||||
|
LConf#{
|
||||||
|
id => ListenerId,
|
||||||
|
type => Type,
|
||||||
|
name => LName,
|
||||||
|
running => Running})}
|
||||||
|
catch
|
||||||
|
error : {config_not_found, _} ->
|
||||||
|
{error, not_found};
|
||||||
|
_Class : Reason ->
|
||||||
|
{error, Reason}
|
||||||
|
end.
|
||||||
|
|
||||||
mapping_listener_m2l(GwName, Listeners0) ->
|
mapping_listener_m2l(GwName, Listeners0) ->
|
||||||
Listeners = maps:to_list(Listeners0),
|
Listeners = maps:to_list(Listeners0),
|
||||||
|
@ -146,6 +174,7 @@ listener(GwName, Type, Conf) ->
|
||||||
LConf#{
|
LConf#{
|
||||||
id => ListenerId,
|
id => ListenerId,
|
||||||
type => Type,
|
type => Type,
|
||||||
|
name => LName,
|
||||||
running => Running
|
running => Running
|
||||||
}
|
}
|
||||||
end || {LName, LConf} <- Conf, is_map(LConf)].
|
end || {LName, LConf} <- Conf, is_map(LConf)].
|
||||||
|
@ -159,6 +188,28 @@ is_running(ListenerId, #{<<"bind">> := ListenOn0}) ->
|
||||||
false
|
false
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
-spec remove_listener(binary()) -> ok | {error, not_found} | {error, any()}.
|
||||||
|
remove_listener(ListenerId) ->
|
||||||
|
{GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
|
||||||
|
LConf = emqx:get_raw_config(
|
||||||
|
[<<"gateway">>, GwName, <<"listeners">>, Type]
|
||||||
|
),
|
||||||
|
NLConf = maps:remove(Name, LConf),
|
||||||
|
emqx_gateway:update_rawconf(
|
||||||
|
GwName,
|
||||||
|
#{<<"listeners">> => #{Type => NLConf}}
|
||||||
|
).
|
||||||
|
|
||||||
|
-spec update_listener(binary(), map()) -> ok | {error, any()}.
|
||||||
|
update_listener(ListenerId, NewConf0) ->
|
||||||
|
{GwName, Type, Name} = emqx_gateway_utils:parse_listener_id(ListenerId),
|
||||||
|
NewConf = maps:without([<<"id">>, <<"name">>,
|
||||||
|
<<"type">>, <<"running">>], NewConf0),
|
||||||
|
emqx_gateway:update_rawconf(
|
||||||
|
GwName,
|
||||||
|
#{<<"listeners">> => #{Type => #{Name => NewConf}}
|
||||||
|
}).
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Mgmt APIs - clients
|
%% Mgmt APIs - clients
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
|
@ -256,10 +307,61 @@ return_http_error(Code, Msg) ->
|
||||||
})
|
})
|
||||||
}.
|
}.
|
||||||
|
|
||||||
codestr(404) -> 'RESOURCE_NOT_FOUND';
|
codestr(400) -> 'BAD_REQUEST';
|
||||||
codestr(401) -> 'NOT_SUPPORTED_NOW';
|
codestr(401) -> 'NOT_SUPPORTED_NOW';
|
||||||
|
codestr(404) -> 'RESOURCE_NOT_FOUND';
|
||||||
codestr(500) -> 'UNKNOW_ERROR'.
|
codestr(500) -> 'UNKNOW_ERROR'.
|
||||||
|
|
||||||
|
-spec with_gateway(binary(), function()) -> any().
|
||||||
|
with_gateway(GwName0, Fun) ->
|
||||||
|
try
|
||||||
|
GwName = try
|
||||||
|
binary_to_existing_atom(GwName0)
|
||||||
|
catch _ : _ -> error(badname)
|
||||||
|
end,
|
||||||
|
case emqx_gateway:lookup(GwName) of
|
||||||
|
undefined ->
|
||||||
|
return_http_error(404, "Gateway not load");
|
||||||
|
Gateway ->
|
||||||
|
Fun(GwName, Gateway)
|
||||||
|
end
|
||||||
|
catch
|
||||||
|
error : badname ->
|
||||||
|
return_http_error(404, "Bad gateway name");
|
||||||
|
error : {miss_param, K} ->
|
||||||
|
return_http_error(400, [K, " is required"]);
|
||||||
|
error : {invalid_listener_id, Id} ->
|
||||||
|
return_http_error(400, ["invalid listener id: ", Id]);
|
||||||
|
Class : Reason : Stk ->
|
||||||
|
?LOG(error, "Uncatched error: {~p, ~p}, stacktrace: ~0p",
|
||||||
|
[Class, Reason, Stk]),
|
||||||
|
return_http_error(500, {Class, Reason, Stk})
|
||||||
|
end.
|
||||||
|
|
||||||
|
-spec checks(list(), map()) -> ok.
|
||||||
|
checks([], _) ->
|
||||||
|
ok;
|
||||||
|
checks([K|Ks], Map) ->
|
||||||
|
case maps:is_key(K, Map) of
|
||||||
|
true -> checks(Ks, Map);
|
||||||
|
false ->
|
||||||
|
error({miss_param, K})
|
||||||
|
end.
|
||||||
|
|
||||||
|
%%--------------------------------------------------------------------
|
||||||
|
%% common schemas
|
||||||
|
|
||||||
|
schema_bad_request() ->
|
||||||
|
emqx_mgmt_util:error_schema(
|
||||||
|
<<"Some Params missed">>, ['PARAMETER_MISSED']).
|
||||||
|
schema_internal_error() ->
|
||||||
|
emqx_mgmt_util:error_schema(
|
||||||
|
<<"Ineternal Server Error">>, ['INTERNAL_SERVER_ERROR']).
|
||||||
|
schema_not_found() ->
|
||||||
|
emqx_mgmt_util:error_schema(<<"Resource Not Found">>).
|
||||||
|
schema_no_content() ->
|
||||||
|
#{description => <<"No Content">>}.
|
||||||
|
|
||||||
%%--------------------------------------------------------------------
|
%%--------------------------------------------------------------------
|
||||||
%% Internal funcs
|
%% Internal funcs
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
, unix_ts_to_rfc3339/2
|
, unix_ts_to_rfc3339/2
|
||||||
, listener_id/3
|
, listener_id/3
|
||||||
, parse_listener_id/1
|
, parse_listener_id/1
|
||||||
|
, parse_listener_id2/1
|
||||||
]).
|
]).
|
||||||
|
|
||||||
-export([ stringfy/1
|
-export([ stringfy/1
|
||||||
|
@ -136,12 +137,17 @@ listener_id(GwName, Type, LisName) ->
|
||||||
parse_listener_id(Id) ->
|
parse_listener_id(Id) ->
|
||||||
try
|
try
|
||||||
[GwName, Type, Name] = binary:split(bin(Id), <<":">>, [global]),
|
[GwName, Type, Name] = binary:split(bin(Id), <<":">>, [global]),
|
||||||
{binary_to_existing_atom(GwName), binary_to_existing_atom(Type),
|
{GwName, Type, Name}
|
||||||
binary_to_atom(Name)}
|
|
||||||
catch
|
catch
|
||||||
_ : _ -> error({invalid_listener_id, Id})
|
_ : _ -> error({invalid_listener_id, Id})
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
parse_listener_id2(Id) ->
|
||||||
|
{GwName, Type, Name} = parse_listener_id(Id),
|
||||||
|
{binary_to_existing_atom(GwName),
|
||||||
|
binary_to_existing_atom(Type),
|
||||||
|
binary_to_atom(Name)}.
|
||||||
|
|
||||||
bin(A) when is_atom(A) ->
|
bin(A) when is_atom(A) ->
|
||||||
atom_to_binary(A);
|
atom_to_binary(A);
|
||||||
bin(L) when is_list(L); is_binary(L) ->
|
bin(L) when is_list(L); is_binary(L) ->
|
||||||
|
@ -161,6 +167,8 @@ unix_ts_to_rfc3339(Ts) ->
|
||||||
emqx_rule_funcs:unix_ts_to_rfc3339(Ts, <<"millisecond">>).
|
emqx_rule_funcs:unix_ts_to_rfc3339(Ts, <<"millisecond">>).
|
||||||
|
|
||||||
-spec stringfy(term()) -> binary().
|
-spec stringfy(term()) -> binary().
|
||||||
|
stringfy(T) when is_list(T); is_binary(T) ->
|
||||||
|
iolist_to_binary(T);
|
||||||
stringfy(T) ->
|
stringfy(T) ->
|
||||||
iolist_to_binary(io_lib:format("~0p", [T])).
|
iolist_to_binary(io_lib:format("~0p", [T])).
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue