Ver código fonte

refactor: improve gw api

JianBo He 4 anos atrás
pai
commit
01c50992e9

+ 28 - 0
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">>)
+         }).

+ 188 - 255
apps/emqx_gateway/src/emqx_gateway_api.erl

@@ -16,22 +16,30 @@
 %%
 %%
 -module(emqx_gateway_api).
 -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_placeholder.hrl").
 -include_lib("emqx/include/emqx_authentication.hrl").
 -include_lib("emqx/include/emqx_authentication.hrl").
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-import(hoconsc, [mk/2, ref/1, ref/2]).
+
 -import(emqx_gateway_http,
 -import(emqx_gateway_http,
         [ return_http_error/2
         [ return_http_error/2
         , with_gateway/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
 %% http handlers
 -export([ gateway/2
 -export([ gateway/2
@@ -44,12 +52,12 @@
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
 
 
 api_spec() ->
 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
 %% 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()
-         }
-     };
-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()
-         }
+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/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 defines
 
 
 params_gateway_name_in_path() ->
 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() ->
 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
 %% schemas
 
 
-schema_gateway_overview_list() ->
-    emqx_mgmt_util:array_schema(
-      #{ type => object
-       , properties => properties_gateway_overview()
-       },
-      <<"Gateway list">>
-     ).
-
-%% 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">>}
-).
-
--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}}
-).
+roots() ->
+    [ gateway_overview
+    , gateway_stats
+    ].
 
 
--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">>}
-).
+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">>})}
+    ];
 
 
--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">>}]}
-).
+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);
 
 
--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">> => <<>>}
-).
+fields(gateway_stats) ->
+    [{key, mk(string(), #{})}].
 
 
-%% --- END
+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()
+     ).
 
 
-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)
-        ]}).
+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}).
 
 
-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
+
+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
+         }
+     }.
 
 
-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_stats() ->
+    #{}.

+ 31 - 75
apps/emqx_gateway/src/emqx_gateway_api_authn.erl

@@ -13,17 +13,14 @@
 %% See the License for the specific language governing permissions and
 %% See the License for the specific language governing permissions and
 %% limitations under the License.
 %% limitations under the License.
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------
-%%
+
 -module(emqx_gateway_api_authn).
 -module(emqx_gateway_api_authn).
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-include("emqx_gateway_http.hrl").
 -include_lib("typerefl/include/types.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(hoconsc, [mk/2, ref/2]).
 -import(emqx_dashboard_swagger, [error_codes/2]).
 -import(emqx_dashboard_swagger, [error_codes/2]).
 
 
@@ -162,48 +159,30 @@ schema("/gateway/:name/authentication") ->
          #{ description => <<"Get the gateway authentication">>
          #{ description => <<"Get the gateway authentication">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
           , responses =>
           , 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 =>
        put =>
          #{ description => <<"Update authentication for the gateway">>
          #{ description => <<"Update authentication for the gateway">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
           , 'requestBody' => schema_authn()
           , 'requestBody' => schema_authn()
           , responses =>
           , 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 =>
        post =>
          #{ description => <<"Add authentication for the gateway">>
          #{ description => <<"Add authentication for the gateway">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
           , 'requestBody' => schema_authn()
           , 'requestBody' => schema_authn()
           , responses =>
           , 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 =>
        delete =>
          #{ description => <<"Remove the gateway authentication">>
          #{ description => <<"Remove the gateway authentication">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
           , responses =>
           , 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") ->
 schema("/gateway/:name/authentication/users") ->
@@ -213,14 +192,11 @@ schema("/gateway/:name/authentication/users") ->
           , parameters => params_gateway_name_in_path() ++
           , parameters => params_gateway_name_in_path() ++
                           params_paging_in_qs()
                           params_paging_in_qs()
           , responses =>
           , 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 =>
        post =>
          #{ description => <<"Add user for the authentication">>
          #{ description => <<"Add user for the authentication">>
@@ -229,14 +205,11 @@ schema("/gateway/:name/authentication/users") ->
                                ref(emqx_authn_api, request_user_create),
                                ref(emqx_authn_api, request_user_create),
                                emqx_authn_api:request_user_create_examples())
                                emqx_authn_api:request_user_create_examples())
           , responses =>
           , 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") ->
 schema("/gateway/:name/authentication/users/:uid") ->
@@ -247,14 +220,11 @@ schema("/gateway/:name/authentication/users/:uid") ->
            , parameters => params_gateway_name_in_path() ++
            , parameters => params_gateway_name_in_path() ++
                            params_userid_in_path()
                            params_userid_in_path()
            , responses =>
            , 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 =>
         put =>
           #{ description => <<"Update the user info for the gateway "
           #{ 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),
                                 ref(emqx_authn_api, request_user_update),
                                 emqx_authn_api:request_user_update_examples())
                                 emqx_authn_api:request_user_update_examples())
            , responses =>
            , 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 =>
         delete =>
           #{ description => <<"Delete the user for the gateway "
           #{ description => <<"Delete the user for the gateway "
@@ -280,12 +247,7 @@ schema("/gateway/:name/authentication/users/:uid") ->
            , parameters => params_gateway_name_in_path() ++
            , parameters => params_gateway_name_in_path() ++
                            params_userid_in_path()
                            params_userid_in_path()
            , responses =>
            , 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") ->
 schema("/gateway/:name/authentication/import_users") ->
@@ -298,13 +260,7 @@ schema("/gateway/:name/authentication/import_users") ->
                              emqx_authn_api:request_import_users_examples()
                              emqx_authn_api:request_import_users_examples()
                             )
                             )
           , responses =>
           , 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">>})
           }
           }
      }.
      }.
 
 

+ 51 - 112
apps/emqx_gateway/src/emqx_gateway_api_listeners.erl

@@ -18,14 +18,10 @@
 
 
 -behaviour(minirest_api).
 -behaviour(minirest_api).
 
 
+-include("emqx_gateway_http.hrl").
 -include_lib("typerefl/include/types.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(hoconsc, [mk/2, ref/1, ref/2]).
--import(emqx_dashboard_swagger, [error_codes/2]).
 
 
 -import(emqx_gateway_http,
 -import(emqx_gateway_http,
         [ return_http_error/2
         [ return_http_error/2
@@ -228,14 +224,11 @@ schema("/gateway/:name/listeners") ->
          #{ description => <<"Get the gateway listeners">>
          #{ description => <<"Get the gateway listeners">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
           , responses =>
           , 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 =>
        post =>
          #{ description => <<"Create the gateway listener">>
          #{ description => <<"Create the gateway listener">>
@@ -244,14 +237,11 @@ schema("/gateway/:name/listeners") ->
                              ref(listener),
                              ref(listener),
                              examples_listener())
                              examples_listener())
           , responses =>
           , 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") ->
 schema("/gateway/:name/listeners/:id") ->
@@ -261,26 +251,18 @@ schema("/gateway/:name/listeners/:id") ->
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , responses =>
           , 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 =>
        delete =>
          #{ description => <<"Delete the gateway listener">>
          #{ description => <<"Delete the gateway listener">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , responses =>
           , 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 =>
        put =>
          #{ description => <<"Update the gateway listener">>
          #{ description => <<"Update the gateway listener">>
@@ -290,14 +272,11 @@ schema("/gateway/:name/listeners/:id") ->
                              ref(listener),
                              ref(listener),
                              examples_listener())
                              examples_listener())
           , responses =>
           , 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") ->
 schema("/gateway/:name/listeners/:id/authentication") ->
@@ -307,13 +286,10 @@ schema("/gateway/:name/listeners/:id/authentication") ->
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , responses =>
           , 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 =>
        post =>
          #{ description => <<"Add authentication for the listener">>
          #{ description => <<"Add authentication for the listener">>
@@ -321,12 +297,7 @@ schema("/gateway/:name/listeners/:id/authentication") ->
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , 'requestBody' => schema_authn()
           , 'requestBody' => schema_authn()
           , responses =>
           , 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 =>
        put =>
          #{ description => <<"Update authentication for the listener">>
          #{ description => <<"Update authentication for the listener">>
@@ -334,24 +305,14 @@ schema("/gateway/:name/listeners/:id/authentication") ->
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , 'requestBody' => schema_authn()
           , 'requestBody' => schema_authn()
           , responses =>
           , 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 =>
        delete =>
          #{ description => <<"Remove authentication for the listener">>
          #{ description => <<"Remove authentication for the listener">>
           , parameters => params_gateway_name_in_path()
           , parameters => params_gateway_name_in_path()
                           ++ params_listener_id_in_path()
                           ++ params_listener_id_in_path()
           , responses =>
           , 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") ->
 schema("/gateway/:name/listeners/:id/authentication/users") ->
@@ -362,14 +323,11 @@ schema("/gateway/:name/listeners/:id/authentication/users") ->
                           params_listener_id_in_path() ++
                           params_listener_id_in_path() ++
                           params_paging_in_qs()
                           params_paging_in_qs()
           , responses =>
           , 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 =>
        post =>
          #{ description => <<"Add user for the authentication">>
          #{ description => <<"Add user for the authentication">>
@@ -379,14 +337,11 @@ schema("/gateway/:name/listeners/:id/authentication/users") ->
                                ref(emqx_authn_api, request_user_create),
                                ref(emqx_authn_api, request_user_create),
                                emqx_authn_api:request_user_create_examples())
                                emqx_authn_api:request_user_create_examples())
           , responses =>
           , 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") ->
 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_listener_id_in_path() ++
                            params_userid_in_path()
                            params_userid_in_path()
            , responses =>
            , 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 =>
         put =>
           #{ description => <<"Update the user info for the gateway "
           #{ 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),
                                ref(emqx_authn_api, request_user_update),
                                emqx_authn_api:request_user_update_examples())
                                emqx_authn_api:request_user_update_examples())
            , responses =>
            , 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 =>
         delete =>
           #{ description => <<"Delete the user for the gateway "
           #{ 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_listener_id_in_path() ++
                            params_userid_in_path()
                            params_userid_in_path()
            , responses =>
            , 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") ->
 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()
                              emqx_authn_api:request_import_users_examples()
                             )
                             )
           , responses =>
           , 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">>})
           }
           }
      }.
      }.