From 01c50992e9eccfad282e16a7bb949557660d2d1a Mon Sep 17 00:00:00 2001 From: JianBo He Date: Mon, 29 Nov 2021 09:47:52 +0800 Subject: [PATCH] refactor: improve gw api --- .../include/emqx_gateway_http.hrl | 28 ++ apps/emqx_gateway/src/emqx_gateway_api.erl | 449 ++++++++---------- .../src/emqx_gateway_api_authn.erl | 106 ++--- .../src/emqx_gateway_api_listeners.erl | 163 ++----- 4 files changed, 301 insertions(+), 445 deletions(-) create mode 100644 apps/emqx_gateway/include/emqx_gateway_http.hrl diff --git a/apps/emqx_gateway/include/emqx_gateway_http.hrl b/apps/emqx_gateway/include/emqx_gateway_http.hrl new file mode 100644 index 000000000..ffcd10fcc --- /dev/null +++ b/apps/emqx_gateway/include/emqx_gateway_http.hrl @@ -0,0 +1,28 @@ +%%-------------------------------------------------------------------- +%% 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. +%%-------------------------------------------------------------------- + +-define(BAD_REQUEST, 'BAD_REQUEST'). +-define(NOT_FOUND, 'NOT_FOUND'). +-define(INTERNAL_ERROR, 'INTERNAL_SERVER_ERROR'). + +-define(STANDARD_RESP(R), + R#{ 400 => emqx_dashboard_swagger:error_codes( + [?BAD_REQUEST], <<"Bad request">>) + , 404 => emqx_dashboard_swagger:error_codes( + [?NOT_FOUND], <<"Not Found">>) + , 500 => emqx_dashboard_swagger:error_codes( + [?INTERNAL_ERROR], <<"Internal Server Error">>) + }). diff --git a/apps/emqx_gateway/src/emqx_gateway_api.erl b/apps/emqx_gateway/src/emqx_gateway_api.erl index 925b7cc0e..b7e96770b 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api.erl @@ -16,22 +16,30 @@ %% -module(emqx_gateway_api). +-include("emqx_gateway_http.hrl"). +-include_lib("typerefl/include/types.hrl"). +-include_lib("hocon/include/hoconsc.hrl"). -include_lib("emqx/include/emqx_placeholder.hrl"). -include_lib("emqx/include/emqx_authentication.hrl"). -behaviour(minirest_api). +-import(hoconsc, [mk/2, ref/1, ref/2]). + -import(emqx_gateway_http, [ 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 --export([api_spec/0]). +%% minirest/dashbaord_swagger behaviour callbacks +-export([ api_spec/0 + , paths/0 + , schema/1 + ]). + +-export([ roots/0 + , fields/1 + ]). %% http handlers -export([ gateway/2 @@ -44,12 +52,12 @@ %%-------------------------------------------------------------------- api_spec() -> - {metadata(apis()), []}. + emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}). -apis() -> - [ {"/gateway", gateway} - , {"/gateway/:name", gateway_insta} - , {"/gateway/:name/stats", gateway_insta_stats} +paths() -> + [ "/gateway" + , "/gateway/:name" + , "/gateway/:name/stats" ]. %%-------------------------------------------------------------------- @@ -137,270 +145,195 @@ gateway_insta_stats(get, _Req) -> %% 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", get) -> - #{ description => <<"Get gateway list">> - , parameters => params_gateway_status_in_qs() - , responses => - #{ <<"200">> => schema_gateway_overview_list() } +schema("/gateway") -> + #{ 'operationId' => gateway, + get => + #{ description => <<"Get gateway list">> + , parameters => params_gateway_status_in_qs() + , responses => + ?STANDARD_RESP(#{200 => ref(gateway_overview)}) + }, + post => + #{ description => <<"Load a gateway">> + , 'requestBody' => schema_gateways_conf() + , responses => + ?STANDARD_RESP(#{201 => schema_gateways_conf()}) + } }; -swagger("/gateway", post) -> - #{ description => <<"Load a gateway">> - , requestBody => schema_gateway_conf() - , responses => - #{ <<"400">> => schema_bad_request() - , <<"404">> => schema_not_found() - , <<"500">> => schema_internal_error() - , <<"204">> => schema_no_content() - } +schema("/gateway/:name") -> + #{ 'operationId' => gateway_insta, + get => + #{ description => <<"Get the gateway configurations">> + , parameters => params_gateway_name_in_path() + , responses => + ?STANDARD_RESP(#{200 => schema_gateways_conf()}) + }, + delete => + #{ description => <<"Delete/Unload the gateway">> + , parameters => params_gateway_name_in_path() + , responses => + ?STANDARD_RESP(#{204 => <<"Deleted">>}) + }, + put => + #{ description => <<"Update the gateway configurations/status">> + , parameters => params_gateway_name_in_path() + , 'requestBody' => schema_gateways_conf() + , responses => + ?STANDARD_RESP(#{200 => schema_gateways_conf()}) + } }; -swagger("/gateway/:name", get) -> - #{ description => <<"Get the gateway configurations">> - , parameters => params_gateway_name_in_path() - , responses => - #{ <<"400">> => schema_bad_request() - , <<"404">> => schema_not_found() - , <<"500">> => schema_internal_error() - , <<"200">> => schema_gateway_conf() - } - }; -swagger("/gateway/:name", delete) -> - #{ description => <<"Delete/Unload the gateway">> - , parameters => params_gateway_name_in_path() - , responses => - #{ <<"400">> => schema_bad_request() - , <<"404">> => schema_not_found() - , <<"500">> => schema_internal_error() - , <<"204">> => schema_no_content() - } - }; -swagger("/gateway/:name", put) -> - #{ description => <<"Update the gateway configurations/status">> - , parameters => params_gateway_name_in_path() - , requestBody => schema_gateway_conf() - , responses => - #{ <<"400">> => schema_bad_request() - , <<"404">> => schema_not_found() - , <<"500">> => schema_internal_error() - , <<"200">> => schema_no_content() - } - }; -swagger("/gateway/:name/stats", get) -> - #{ description => <<"Get gateway Statistic">> - , parameters => params_gateway_name_in_path() - , responses => - #{ <<"400">> => schema_bad_request() - , <<"404">> => schema_not_found() - , <<"500">> => schema_internal_error() - , <<"200">> => schema_gateway_stats() - } +schema("/gateway/:name/stats") -> + #{ 'operationId' => gateway_insta_stats, + get => + #{ description => <<"Get gateway Statistic">> + , parameters => params_gateway_name_in_path() + , responses => + ?STANDARD_RESP( + #{200 => emqx_dashboard_swagger:schema_with_examples( + ref(gateway_stats), + examples_gateway_stats()) + }) + } }. %%-------------------------------------------------------------------- %% params defines params_gateway_name_in_path() -> - [#{ name => name - , in => path - , schema => #{type => string} - , required => true - }]. + [{name, + mk(binary(), + #{ in => path + , desc => <<"Gateway Name">> + })} + ]. params_gateway_status_in_qs() -> - [#{ name => status - , in => query - , schema => #{type => string} - , required => false - }]. + [{status, + mk(binary(), + #{ in => query + , nullable => true + , desc => <<"Gateway Status">> + })} + ]. %%-------------------------------------------------------------------- %% schemas -schema_gateway_overview_list() -> - emqx_mgmt_util:array_schema( - #{ type => object - , properties => properties_gateway_overview() - }, - <<"Gateway list">> +roots() -> + [ gateway_overview + , gateway_stats + ]. + +fields(gateway_overview) -> + [ {name, + mk(string(), + #{ desc => <<"Gateway Name">>})} + , {status, + mk(hoconsc:enum([running, stopped, unloaded]), + #{ desc => <<"The Gateway status">>})} + , {created_at, + mk(string(), + #{desc => <<"The Gateway created datetime">>})} + , {started_at, + mk(string(), + #{ nullable => true + , desc => <<"The Gateway started datetime">>})} + , {stopped_at, + mk(string(), + #{ nullable => true + , desc => <<"The Gateway stopped datetime">>})} + , {max_connections, + mk(integer(), + #{ desc => <<"The Gateway allowed maximum connections/clients">>})} + , {current_connections, + mk(integer(), + #{ desc => <<"The Gateway current connected connections/clients">> + })} + , {listeners, + mk(hoconsc:array(ref(gateway_listener_overview)), + #{ nullable => {true, recursively} + , desc => <<"The Gateway listeners overview">>})} + ]; +fields(gateway_listener_overview) -> + [ {id, + mk(string(), + #{ desc => <<"Listener ID">>})} + , {running, + mk(boolean(), + #{ desc => <<"Listener Running status">>})} + , {type, + mk(hoconsc:enum([tcp, ssl, udp, dtls]), + #{ desc => <<"Listener Type">>})} + ]; + +fields(Gw) when Gw == stomp; Gw == mqttsn; + Gw == coap; Gw == lwm2m; + Gw == exproto -> + convert_listener_struct(emqx_gateway_schema:fields(Gw)); +fields(Listener) when Listener == tcp_listener; + Listener == ssl_listener; + Listener == udp_listener; + Listener == dtls_listener -> + [ {type, + mk(hoconsc:union([tcp, ssl, udp, dtls]), + #{ desc => <<"Listener type">>})} + , {name, + mk(string(), + #{ desc => <<"Listener Name">>})} + , {running, + mk(boolean(), + #{ desc => <<"Listener running status">>})} + ] ++ emqx_gateway_schema:fields(Listener); + +fields(gateway_stats) -> + [{key, mk(string(), #{})}]. + +schema_gateways_conf() -> + %% XXX: We need convert the emqx_gateway_schema's listener map + %% structure to array + emqx_dashboard_swagger:schema_with_examples( + hoconsc:union([ref(stomp), ref(mqttsn), + ref(coap), ref(lwm2m), ref(exproto)]), + examples_gateway_confs() ). -%% XXX: This is whole confs for all type gateways. It is used to fill the -%% default configurations and generate the swagger-schema -%% -%% NOTE: It is a temporary measure to generate swagger-schema --define(COAP_GATEWAY_CONFS, -#{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY => - #{<<"mechanism">> => <<"password-based">>, - <<"name">> => <<"authenticator1">>, - <<"server_type">> => <<"built-in-database">>, - <<"user_id_type">> => <<"clientid">>}, - <<"name">> => <<"coap">>, - <<"enable">> => true, - <<"enable_stats">> => true,<<"heartbeat">> => <<"30s">>, - <<"idle_timeout">> => <<"30s">>, - <<"listeners">> => [ - #{<<"id">> => <<"coap:udp:default">>, - <<"type">> => <<"udp">>, - <<"running">> => true, - <<"acceptors">> => 8,<<"bind">> => 5683, - <<"max_conn_rate">> => 1000, - <<"max_connections">> => 10240}], - <<"mountpoint">> => <<>>,<<"notify_type">> => <<"qos">>, - <<"publish_qos">> => <<"qos1">>, - <<"subscribe_qos">> => <<"qos0">>} -). +convert_listener_struct(Schema) -> + {value, {listeners, + #{type := Type}}, Schema1} = lists:keytake(listeners, 1, Schema), + ListenerSchema = hoconsc:mk(listeners_schema(Type), + #{ nullable => {true, recursively} + , desc => <<"The gateway listeners">> + }), + lists:keystore(listeners, 1, Schema1, {listeners, ListenerSchema}). --define(EXPROTO_GATEWAY_CONFS, -#{<<"enable">> => true, - <<"name">> => <<"exproto">>, - <<"enable_stats">> => true, - <<"handler">> => - #{<<"address">> => <<"http://127.0.0.1:9001">>}, - <<"idle_timeout">> => <<"30s">>, - <<"listeners">> => [ - #{<<"id">> => <<"exproto:tcp:default">>, - <<"type">> => <<"tcp">>, - <<"running">> => true, - <<"acceptors">> => 8,<<"bind">> => 7993, - <<"max_conn_rate">> => 1000, - <<"max_connections">> => 10240}], - <<"mountpoint">> => <<>>, - <<"server">> => #{<<"bind">> => 9100}} -). - --define(LWM2M_GATEWAY_CONFS, -#{<<"auto_observe">> => false, - <<"name">> => <<"lwm2m">>, - <<"enable">> => true, - <<"enable_stats">> => true, - <<"idle_timeout">> => <<"30s">>, - <<"lifetime_max">> => <<"86400s">>, - <<"lifetime_min">> => <<"1s">>, - <<"listeners">> => [ - #{<<"id">> => <<"lwm2m:udp:default">>, - <<"type">> => <<"udp">>, - <<"running">> => true, - <<"bind">> => 5783}], - <<"mountpoint">> => <<"lwm2m/", ?PH_S_ENDPOINT_NAME, "/">>, - <<"qmode_time_windonw">> => 22, - <<"translators">> => - #{<<"command">> => <<"dn/#">>,<<"notify">> => <<"up/notify">>, - <<"register">> => <<"up/resp">>, - <<"response">> => <<"up/resp">>, - <<"update">> => <<"up/resp">>}, - <<"update_msg_publish_condition">> => - <<"contains_object_list">>, - <<"xml_dir">> => <<"etc/lwm2m_xml">>} -). - --define(MQTTSN_GATEWAY_CONFS, -#{<<"broadcast">> => true, - <<"clientinfo_override">> => - #{<<"password">> => <<"abc">>, - <<"username">> => <<"mqtt_sn_user">>}, - <<"enable">> => true, - <<"name">> => <<"mqtt-sn">>, - <<"enable_qos3">> => true,<<"enable_stats">> => true, - <<"gateway_id">> => 1,<<"idle_timeout">> => <<"30s">>, - <<"listeners">> => [ - #{<<"id">> => <<"mqttsn:udp:default">>, - <<"type">> => <<"udp">>, - <<"running">> => true, - <<"bind">> => 1884,<<"max_conn_rate">> => 1000, - <<"max_connections">> => 10240000}], - <<"mountpoint">> => <<>>, - <<"predefined">> => - [#{<<"id">> => 1, - <<"topic">> => <<"/predefined/topic/name/hello">>}, - #{<<"id">> => 2, - <<"topic">> => <<"/predefined/topic/name/nice">>}]} -). - --define(STOMP_GATEWAY_CONFS, -#{?EMQX_AUTHENTICATION_CONFIG_ROOT_NAME_BINARY => - #{<<"mechanism">> => <<"password-based">>, - <<"name">> => <<"authenticator1">>, - <<"server_type">> => <<"built-in-database">>, - <<"user_id_type">> => <<"clientid">>}, - <<"clientinfo_override">> => - #{<<"password">> => <<"${Packet.headers.passcode}">>, - <<"username">> => <<"${Packet.headers.login}">>}, - <<"enable">> => true, - <<"name">> => <<"stomp">>, - <<"enable_stats">> => true, - <<"frame">> => - #{<<"max_body_length">> => 8192,<<"max_headers">> => 10, - <<"max_headers_length">> => 1024}, - <<"idle_timeout">> => <<"30s">>, - <<"listeners">> => [ - #{<<"id">> => <<"stomp:tcp:default">>, - <<"type">> => <<"tcp">>, - <<"running">> => true, - <<"acceptors">> => 16,<<"active_n">> => 100, - <<"bind">> => 61613,<<"max_conn_rate">> => 1000, - <<"max_connections">> => 1024000}], - <<"mountpoint">> => <<>>} -). - -%% --- END - -schema_gateway_conf() -> - emqx_mgmt_util:schema( - #{oneOf => - [ emqx_mgmt_api_configs:gen_schema(?STOMP_GATEWAY_CONFS) - , emqx_mgmt_api_configs:gen_schema(?MQTTSN_GATEWAY_CONFS) - , emqx_mgmt_api_configs:gen_schema(?COAP_GATEWAY_CONFS) - , emqx_mgmt_api_configs:gen_schema(?LWM2M_GATEWAY_CONFS) - , emqx_mgmt_api_configs:gen_schema(?EXPROTO_GATEWAY_CONFS) - ]}). - -schema_gateway_stats() -> - emqx_mgmt_util:schema( - #{ type => object - , properties => - #{ a_key => #{type => string} - }}). +listeners_schema(?R_REF(_Mod, tcp_listeners)) -> + hoconsc:array(hoconsc:union([ref(tcp_listener), ref(ssl_listener)])); +listeners_schema(?R_REF(_Mod, udp_listeners)) -> + hoconsc:array(hoconsc:union([ref(udp_listener), ref(dtls_listener)])); +listeners_schema(?R_REF(_Mod, udp_tcp_listeners)) -> + hoconsc:array(hoconsc:union([ref(tcp_listener), ref(ssl_listener), + ref(udp_listener), ref(dtls_listener)])). %%-------------------------------------------------------------------- -%% properties +%% examples -properties_gateway_overview() -> - ListenerProps = - [ {id, string, - <<"Listener ID">>} - , {running, boolean, - <<"Listener Running status">>} - , {type, string, - <<"Listener Type">>, [<<"tcp">>, <<"ssl">>, <<"udp">>, <<"dtls">>]} - ], - emqx_mgmt_util:properties( - [ {name, string, - <<"Gateway Name">>} - , {status, string, - <<"Gateway Status">>, - [<<"running">>, <<"stopped">>, <<"unloaded">>]} - , {created_at, string, - <<>>} - , {started_at, string, - <<>>} - , {stopped_at, string, - <<>>} - , {max_connections, integer, <<>>} - , {current_connections, integer, <<>>} - , {listeners, {array, object}, ListenerProps} - ]). +examples_gateway_confs() -> + #{ a_stomp_gateway => + #{ enable => true + , enable_stats => true + , idle_timeout => <<"30s">> + , mountpoint => <<"stomp/">> + , frame => + #{ max_header => 10 + , make_header_length => 1024 + , max_body_length => 65535 + } + } + , a_mqttsn_gateway => + #{ enable => true + , enable_stats => true + } + }. + +examples_gateway_stats() -> + #{}. diff --git a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl index 143507b0b..d9bdf4d7c 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_authn.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_authn.erl @@ -13,17 +13,14 @@ %% See the License for the specific language governing permissions and %% limitations under the License. %%-------------------------------------------------------------------- -%% + -module(emqx_gateway_api_authn). -behaviour(minirest_api). +-include("emqx_gateway_http.hrl"). -include_lib("typerefl/include/types.hrl"). --define(BAD_REQUEST, 'BAD_REQUEST'). --define(NOT_FOUND, 'NOT_FOUND'). --define(INTERNAL_ERROR, 'INTERNAL_SERVER_ERROR'). - -import(hoconsc, [mk/2, ref/2]). -import(emqx_dashboard_swagger, [error_codes/2]). @@ -162,48 +159,30 @@ schema("/gateway/:name/authentication") -> #{ description => <<"Get the gateway authentication">> , parameters => params_gateway_name_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => schema_authn() - , 204 => <<"Authentication does not initiated">> - } + ?STANDARD_RESP( + #{ 200 => schema_authn() + , 204 => <<"Authentication does not initiated">> + }) }, put => #{ description => <<"Update authentication for the gateway">> , parameters => params_gateway_name_in_path() , 'requestBody' => schema_authn() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => schema_authn() - } + ?STANDARD_RESP(#{200 => schema_authn()}) }, post => #{ description => <<"Add authentication for the gateway">> , parameters => params_gateway_name_in_path() , 'requestBody' => schema_authn() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 201 => schema_authn() - } + ?STANDARD_RESP(#{201 => schema_authn()}) }, delete => #{ description => <<"Remove the gateway authentication">> , parameters => params_gateway_name_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 204 => <<"Deleted">> - } + ?STANDARD_RESP(#{204 => <<"Deleted">>}) } }; schema("/gateway/:name/authentication/users") -> @@ -213,14 +192,11 @@ schema("/gateway/:name/authentication/users") -> , parameters => params_gateway_name_in_path() ++ params_paging_in_qs() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, post => #{ description => <<"Add user for the authentication">> @@ -229,14 +205,11 @@ schema("/gateway/:name/authentication/users") -> ref(emqx_authn_api, request_user_create), emqx_authn_api:request_user_create_examples()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 201 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 201 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) } }; schema("/gateway/:name/authentication/users/:uid") -> @@ -247,14 +220,11 @@ schema("/gateway/:name/authentication/users/:uid") -> , parameters => params_gateway_name_in_path() ++ params_userid_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, put => #{ description => <<"Update the user info for the gateway " @@ -265,14 +235,11 @@ schema("/gateway/:name/authentication/users/:uid") -> ref(emqx_authn_api, request_user_update), emqx_authn_api:request_user_update_examples()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, delete => #{ description => <<"Delete the user for the gateway " @@ -280,12 +247,7 @@ schema("/gateway/:name/authentication/users/:uid") -> , parameters => params_gateway_name_in_path() ++ params_userid_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 204 => <<"User Deleted">> - } + ?STANDARD_RESP(#{204 => <<"User Deleted">>}) } }; schema("/gateway/:name/authentication/import_users") -> @@ -298,13 +260,7 @@ schema("/gateway/:name/authentication/import_users") -> emqx_authn_api:request_import_users_examples() ) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - %% XXX: Put a hint message into 204 return ? - , 204 => <<"Imported">> - } + ?STANDARD_RESP(#{204 => <<"Imported">>}) } }. diff --git a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl index 2a16907f8..44e3842cc 100644 --- a/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl +++ b/apps/emqx_gateway/src/emqx_gateway_api_listeners.erl @@ -18,14 +18,10 @@ -behaviour(minirest_api). +-include("emqx_gateway_http.hrl"). -include_lib("typerefl/include/types.hrl"). --define(BAD_REQUEST, 'BAD_REQUEST'). --define(NOT_FOUND, 'NOT_FOUND'). --define(INTERNAL_ERROR, 'INTERNAL_SERVER_ERROR'). - -import(hoconsc, [mk/2, ref/1, ref/2]). --import(emqx_dashboard_swagger, [error_codes/2]). -import(emqx_gateway_http, [ return_http_error/2 @@ -228,14 +224,11 @@ schema("/gateway/:name/listeners") -> #{ description => <<"Get the gateway listeners">> , parameters => params_gateway_name_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_examples( - hoconsc:array(ref(listener)), - examples_listener_list()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_examples( + hoconsc:array(ref(listener)), + examples_listener_list()) + }) }, post => #{ description => <<"Create the gateway listener">> @@ -244,14 +237,11 @@ schema("/gateway/:name/listeners") -> ref(listener), examples_listener()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 201 => emqx_dashboard_swagger:schema_with_examples( - ref(listener), - examples_listener_list()) - } + ?STANDARD_RESP( + #{ 201 => emqx_dashboard_swagger:schema_with_examples( + ref(listener), + examples_listener_list()) + }) } }; schema("/gateway/:name/listeners/:id") -> @@ -261,26 +251,18 @@ schema("/gateway/:name/listeners/:id") -> , parameters => params_gateway_name_in_path() ++ params_listener_id_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_examples( - ref(listener), - examples_listener()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_examples( + ref(listener), + examples_listener()) + }) }, delete => #{ description => <<"Delete the gateway listener">> , parameters => params_gateway_name_in_path() ++ params_listener_id_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 204 => <<"Deleted">> - } + ?STANDARD_RESP(#{204 => <<"Deleted">>}) }, put => #{ description => <<"Update the gateway listener">> @@ -290,14 +272,11 @@ schema("/gateway/:name/listeners/:id") -> ref(listener), examples_listener()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_examples( - ref(listener), - examples_listener()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_examples( + ref(listener), + examples_listener()) + }) } }; schema("/gateway/:name/listeners/:id/authentication") -> @@ -307,13 +286,10 @@ schema("/gateway/:name/listeners/:id/authentication") -> , parameters => params_gateway_name_in_path() ++ params_listener_id_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => schema_authn() - , 204 => <<"Authentication does not initiated">> - } + ?STANDARD_RESP( + #{ 200 => schema_authn() + , 204 => <<"Authentication does not initiated">> + }) }, post => #{ description => <<"Add authentication for the listener">> @@ -321,12 +297,7 @@ schema("/gateway/:name/listeners/:id/authentication") -> ++ params_listener_id_in_path() , 'requestBody' => schema_authn() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 201 => schema_authn() - } + ?STANDARD_RESP(#{201 => schema_authn()}) }, put => #{ description => <<"Update authentication for the listener">> @@ -334,24 +305,14 @@ schema("/gateway/:name/listeners/:id/authentication") -> ++ params_listener_id_in_path() , 'requestBody' => schema_authn() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => schema_authn() - } + ?STANDARD_RESP(#{200 => schema_authn()}) }, delete => #{ description => <<"Remove authentication for the listener">> , parameters => params_gateway_name_in_path() ++ params_listener_id_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => <<"Deleted">> - } + ?STANDARD_RESP(#{200 => <<"Deleted">>}) } }; schema("/gateway/:name/listeners/:id/authentication/users") -> @@ -362,14 +323,11 @@ schema("/gateway/:name/listeners/:id/authentication/users") -> params_listener_id_in_path() ++ params_paging_in_qs() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, post => #{ description => <<"Add user for the authentication">> @@ -379,14 +337,11 @@ schema("/gateway/:name/listeners/:id/authentication/users") -> ref(emqx_authn_api, request_user_create), emqx_authn_api:request_user_create_examples()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 201 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 201 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) } }; schema("/gateway/:name/listeners/:id/authentication/users/:uid") -> @@ -398,14 +353,11 @@ schema("/gateway/:name/listeners/:id/authentication/users/:uid") -> params_listener_id_in_path() ++ params_userid_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, put => #{ description => <<"Update the user info for the gateway " @@ -417,14 +369,11 @@ schema("/gateway/:name/listeners/:id/authentication/users/:uid") -> ref(emqx_authn_api, request_user_update), emqx_authn_api:request_user_update_examples()) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 200 => emqx_dashboard_swagger:schema_with_example( - ref(emqx_authn_api, response_user), - emqx_authn_api:response_user_examples()) - } + ?STANDARD_RESP( + #{ 200 => emqx_dashboard_swagger:schema_with_example( + ref(emqx_authn_api, response_user), + emqx_authn_api:response_user_examples()) + }) }, delete => #{ description => <<"Delete the user for the gateway " @@ -433,12 +382,7 @@ schema("/gateway/:name/listeners/:id/authentication/users/:uid") -> params_listener_id_in_path() ++ params_userid_in_path() , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 204 => <<"Deleted">> - } + ?STANDARD_RESP(#{204 => <<"Deleted">>}) } }; schema("/gateway/:name/listeners/:id/authentication/import_users") -> @@ -452,12 +396,7 @@ schema("/gateway/:name/listeners/:id/authentication/import_users") -> emqx_authn_api:request_import_users_examples() ) , responses => - #{ 400 => error_codes([?BAD_REQUEST], <<"Bad Request">>) - , 404 => error_codes([?NOT_FOUND], <<"Not Found">>) - , 500 => error_codes([?INTERNAL_ERROR], - <<"Ineternal Server Error">>) - , 204 => <<"Imported">> - } + ?STANDARD_RESP(#{204 => <<"Imported">>}) } }.