Просмотр исходного кода

Merge pull request #9958 from HJianBo/refine-clients-http-return

fix(api): fix bad return error message if client id is not found
zhongwencool 3 лет назад
Родитель
Сommit
0753146f65

+ 1 - 1
apps/emqx_management/src/emqx_management.app.src

@@ -2,7 +2,7 @@
 {application, emqx_management, [
 {application, emqx_management, [
     {description, "EMQX Management API and CLI"},
     {description, "EMQX Management API and CLI"},
     % strict semver, bump manually!
     % strict semver, bump manually!
-    {vsn, "5.0.14"},
+    {vsn, "5.0.15"},
     {modules, []},
     {modules, []},
     {registered, [emqx_management_sup]},
     {registered, [emqx_management_sup]},
     {applications, [kernel, stdlib, emqx_plugins, minirest, emqx]},
     {applications, [kernel, stdlib, emqx_plugins, minirest, emqx]},

+ 28 - 26
apps/emqx_management/src/emqx_mgmt_api_clients.erl

@@ -76,9 +76,10 @@
 
 
 -define(FORMAT_FUN, {?MODULE, format_channel_info}).
 -define(FORMAT_FUN, {?MODULE, format_channel_info}).
 
 
--define(CLIENT_ID_NOT_FOUND,
-    <<"{\"code\": \"RESOURCE_NOT_FOUND\", \"reason\": \"Client id not found\"}">>
-).
+-define(CLIENTID_NOT_FOUND, #{
+    code => 'CLIENTID_NOT_FOUND',
+    message => <<"Client ID not found">>
+}).
 
 
 api_spec() ->
 api_spec() ->
     emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}).
     emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true, translate_body => true}).
@@ -219,7 +220,7 @@ schema("/clients/:clientid") ->
             responses => #{
             responses => #{
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}),
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}),
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         },
         },
@@ -232,7 +233,7 @@ schema("/clients/:clientid") ->
             responses => #{
             responses => #{
                 204 => <<"Kick out client successfully">>,
                 204 => <<"Kick out client successfully">>,
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -247,7 +248,7 @@ schema("/clients/:clientid/authorization/cache") ->
             responses => #{
             responses => #{
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, authz_cache), #{}),
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, authz_cache), #{}),
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         },
         },
@@ -256,9 +257,9 @@ schema("/clients/:clientid/authorization/cache") ->
             tags => ?TAGS,
             tags => ?TAGS,
             parameters => [{clientid, hoconsc:mk(binary(), #{in => path})}],
             parameters => [{clientid, hoconsc:mk(binary(), #{in => path})}],
             responses => #{
             responses => #{
-                204 => <<"Kick out client successfully">>,
+                204 => <<"Clean client authz cache successfully">>,
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -273,10 +274,11 @@ schema("/clients/:clientid/subscriptions") ->
             responses => #{
             responses => #{
                 200 => hoconsc:mk(
                 200 => hoconsc:mk(
                     hoconsc:array(hoconsc:ref(emqx_mgmt_api_subscriptions, subscription)), #{}
                     hoconsc:array(hoconsc:ref(emqx_mgmt_api_subscriptions, subscription)), #{}
-                ),
-                404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
                 )
                 )
+                %% returns [] if client not existed in cluster
+                %404 => emqx_dashboard_swagger:error_codes(
+                %    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
+                %)
             }
             }
         }
         }
     };
     };
@@ -291,7 +293,7 @@ schema("/clients/:clientid/subscribe") ->
             responses => #{
             responses => #{
                 200 => hoconsc:ref(emqx_mgmt_api_subscriptions, subscription),
                 200 => hoconsc:ref(emqx_mgmt_api_subscriptions, subscription),
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -307,7 +309,7 @@ schema("/clients/:clientid/subscribe/bulk") ->
             responses => #{
             responses => #{
                 200 => hoconsc:array(hoconsc:ref(emqx_mgmt_api_subscriptions, subscription)),
                 200 => hoconsc:array(hoconsc:ref(emqx_mgmt_api_subscriptions, subscription)),
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -323,7 +325,7 @@ schema("/clients/:clientid/unsubscribe") ->
             responses => #{
             responses => #{
                 204 => <<"Unsubscribe OK">>,
                 204 => <<"Unsubscribe OK">>,
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -339,7 +341,7 @@ schema("/clients/:clientid/unsubscribe/bulk") ->
             responses => #{
             responses => #{
                 204 => <<"Unsubscribe OK">>,
                 204 => <<"Unsubscribe OK">>,
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -355,7 +357,7 @@ schema("/clients/:clientid/keepalive") ->
             responses => #{
             responses => #{
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}),
                 200 => hoconsc:mk(hoconsc:ref(?MODULE, client), #{}),
                 404 => emqx_dashboard_swagger:error_codes(
                 404 => emqx_dashboard_swagger:error_codes(
-                    ['CLIENTID_NOT_FOUND'], <<"Client id not found">>
+                    ['CLIENTID_NOT_FOUND'], <<"Client ID not found">>
                 )
                 )
             }
             }
         }
         }
@@ -621,7 +623,7 @@ set_keepalive(put, #{bindings := #{clientid := ClientID}, body := Body}) ->
         {ok, Interval} ->
         {ok, Interval} ->
             case emqx_mgmt:set_keepalive(emqx_mgmt_util:urldecode(ClientID), Interval) of
             case emqx_mgmt:set_keepalive(emqx_mgmt_util:urldecode(ClientID), Interval) of
                 ok -> lookup(#{clientid => ClientID});
                 ok -> lookup(#{clientid => ClientID});
-                {error, not_found} -> {404, ?CLIENT_ID_NOT_FOUND};
+                {error, not_found} -> {404, ?CLIENTID_NOT_FOUND};
                 {error, Reason} -> {400, #{code => 'PARAMS_ERROR', message => Reason}}
                 {error, Reason} -> {400, #{code => 'PARAMS_ERROR', message => Reason}}
             end
             end
     end.
     end.
@@ -669,7 +671,7 @@ list_clients(QString) ->
 lookup(#{clientid := ClientID}) ->
 lookup(#{clientid := ClientID}) ->
     case emqx_mgmt:lookup_client({clientid, ClientID}, ?FORMAT_FUN) of
     case emqx_mgmt:lookup_client({clientid, ClientID}, ?FORMAT_FUN) of
         [] ->
         [] ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         ClientInfo ->
         ClientInfo ->
             {200, hd(ClientInfo)}
             {200, hd(ClientInfo)}
     end.
     end.
@@ -677,7 +679,7 @@ lookup(#{clientid := ClientID}) ->
 kickout(#{clientid := ClientID}) ->
 kickout(#{clientid := ClientID}) ->
     case emqx_mgmt:kickout_client({ClientID, ?FORMAT_FUN}) of
     case emqx_mgmt:kickout_client({ClientID, ?FORMAT_FUN}) of
         {error, not_found} ->
         {error, not_found} ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         _ ->
         _ ->
             {204}
             {204}
     end.
     end.
@@ -685,7 +687,7 @@ kickout(#{clientid := ClientID}) ->
 get_authz_cache(#{clientid := ClientID}) ->
 get_authz_cache(#{clientid := ClientID}) ->
     case emqx_mgmt:list_authz_cache(ClientID) of
     case emqx_mgmt:list_authz_cache(ClientID) of
         {error, not_found} ->
         {error, not_found} ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         {error, Reason} ->
         {error, Reason} ->
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}};
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}};
@@ -699,7 +701,7 @@ clean_authz_cache(#{clientid := ClientID}) ->
         ok ->
         ok ->
             {204};
             {204};
         {error, not_found} ->
         {error, not_found} ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         {error, Reason} ->
         {error, Reason} ->
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}}
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}}
@@ -709,7 +711,7 @@ subscribe(#{clientid := ClientID, topic := Topic} = Sub) ->
     Opts = maps:with([qos, nl, rap, rh], Sub),
     Opts = maps:with([qos, nl, rap, rh], Sub),
     case do_subscribe(ClientID, Topic, Opts) of
     case do_subscribe(ClientID, Topic, Opts) of
         {error, channel_not_found} ->
         {error, channel_not_found} ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         {error, Reason} ->
         {error, Reason} ->
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             Message = list_to_binary(io_lib:format("~p", [Reason])),
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}};
             {500, #{code => <<"UNKNOW_ERROR">>, message => Message}};
@@ -723,7 +725,7 @@ subscribe_batch(#{clientid := ClientID, topics := Topics}) ->
     %% has returned. So if one want to subscribe topics in this hook, it will fail.
     %% has returned. So if one want to subscribe topics in this hook, it will fail.
     case ets:lookup(emqx_channel, ClientID) of
     case ets:lookup(emqx_channel, ClientID) of
         [] ->
         [] ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         _ ->
         _ ->
             ArgList = [
             ArgList = [
                 [ClientID, Topic, maps:with([qos, nl, rap, rh], Sub)]
                 [ClientID, Topic, maps:with([qos, nl, rap, rh], Sub)]
@@ -735,7 +737,7 @@ subscribe_batch(#{clientid := ClientID, topics := Topics}) ->
 unsubscribe(#{clientid := ClientID, topic := Topic}) ->
 unsubscribe(#{clientid := ClientID, topic := Topic}) ->
     case do_unsubscribe(ClientID, Topic) of
     case do_unsubscribe(ClientID, Topic) of
         {error, channel_not_found} ->
         {error, channel_not_found} ->
-            {404, ?CLIENT_ID_NOT_FOUND};
+            {404, ?CLIENTID_NOT_FOUND};
         {unsubscribe, [{Topic, #{}}]} ->
         {unsubscribe, [{Topic, #{}}]} ->
             {204}
             {204}
     end.
     end.
@@ -745,8 +747,8 @@ unsubscribe_batch(#{clientid := ClientID, topics := Topics}) ->
         {200, _} ->
         {200, _} ->
             _ = emqx_mgmt:unsubscribe_batch(ClientID, Topics),
             _ = emqx_mgmt:unsubscribe_batch(ClientID, Topics),
             {204};
             {204};
-        {404, ?CLIENT_ID_NOT_FOUND} ->
-            {404, ?CLIENT_ID_NOT_FOUND}
+        {404, NotFound} ->
+            {404, NotFound}
     end.
     end.
 
 
 %%--------------------------------------------------------------------
 %%--------------------------------------------------------------------

+ 43 - 0
apps/emqx_management/test/emqx_mgmt_api_clients_SUITE.erl

@@ -247,6 +247,49 @@ t_keepalive(_Config) ->
     emqtt:disconnect(C1),
     emqtt:disconnect(C1),
     ok.
     ok.
 
 
+t_client_id_not_found(_Config) ->
+    AuthHeader = emqx_mgmt_api_test_util:auth_header_(),
+    Http = {"HTTP/1.1", 404, "Not Found"},
+    Body = "{\"code\":\"CLIENTID_NOT_FOUND\",\"message\":\"Client ID not found\"}",
+
+    PathFun = fun(Suffix) ->
+        emqx_mgmt_api_test_util:api_path(["clients", "no_existed_clientid"] ++ Suffix)
+    end,
+    ReqFun = fun(Method, Path) ->
+        emqx_mgmt_api_test_util:request_api(
+            Method, Path, "", AuthHeader, [], #{return_all => true}
+        )
+    end,
+
+    PostFun = fun(Method, Path, Data) ->
+        emqx_mgmt_api_test_util:request_api(
+            Method, Path, "", AuthHeader, Data, #{return_all => true}
+        )
+    end,
+
+    %% Client lookup
+    ?assertMatch({error, {Http, _, Body}}, ReqFun(get, PathFun([]))),
+    %% Client kickout
+    ?assertMatch({error, {Http, _, Body}}, ReqFun(delete, PathFun([]))),
+    %% Client Subscription list
+    ?assertMatch({ok, {{"HTTP/1.1", 200, "OK"}, _, "[]"}}, ReqFun(get, PathFun(["subscriptions"]))),
+    %% AuthZ Cache lookup
+    ?assertMatch({error, {Http, _, Body}}, ReqFun(get, PathFun(["authorization", "cache"]))),
+    %% AuthZ Cache clean
+    ?assertMatch({error, {Http, _, Body}}, ReqFun(delete, PathFun(["authorization", "cache"]))),
+    %% Client Subscribe
+    SubBody = #{topic => <<"testtopic">>, qos => 1, nl => 1, rh => 1},
+    ?assertMatch({error, {Http, _, Body}}, PostFun(post, PathFun(["subscribe"]), SubBody)),
+    ?assertMatch(
+        {error, {Http, _, Body}}, PostFun(post, PathFun(["subscribe", "bulk"]), [SubBody])
+    ),
+    %% Client Unsubscribe
+    UnsubBody = #{topic => <<"testtopic">>},
+    ?assertMatch({error, {Http, _, Body}}, PostFun(post, PathFun(["unsubscribe"]), UnsubBody)),
+    ?assertMatch(
+        {error, {Http, _, Body}}, PostFun(post, PathFun(["unsubscribe", "bulk"]), [UnsubBody])
+    ).
+
 time_string_to_epoch_millisecond(DateTime) ->
 time_string_to_epoch_millisecond(DateTime) ->
     time_string_to_epoch(DateTime, millisecond).
     time_string_to_epoch(DateTime, millisecond).
 
 

+ 1 - 0
changes/v5.0.18/fix-9958.en.md

@@ -0,0 +1 @@
+Fix bad http response format when client ID is not found in `clients` APIs

+ 1 - 0
changes/v5.0.18/fix-9958.zh.md

@@ -0,0 +1 @@
+修复 `clients` API 在 Client ID 不存在时返回的错误的 HTTP 应答格式。