From 08d88ea814257e19497fb4f0f7033e60f3861d84 Mon Sep 17 00:00:00 2001 From: Andrew Mayorov Date: Mon, 27 May 2024 17:14:37 +0200 Subject: [PATCH] feat(bridge-api): improve error messages for Update Source API --- apps/emqx_bridge/src/emqx_bridge_v2_api.erl | 25 ++++++++++++++++--- .../src/schema/emqx_bridge_v2_schema.erl | 22 +++++++++++++--- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/apps/emqx_bridge/src/emqx_bridge_v2_api.erl b/apps/emqx_bridge/src/emqx_bridge_v2_api.erl index b06424ea2..8ba2ef487 100644 --- a/apps/emqx_bridge/src/emqx_bridge_v2_api.erl +++ b/apps/emqx_bridge/src/emqx_bridge_v2_api.erl @@ -658,21 +658,38 @@ schema("/source_types") -> %%------------------------------------------------------------------------------ -check_api_schema(Request, ReqMeta = #{path := Path = "/actions/:id", method := put}) -> - Spec = maps:get(put, schema(Path)), +check_api_schema(Request, ReqMeta = #{path := "/actions/:id", method := put}) -> BridgeId = emqx_utils_maps:deep_get([bindings, id], Request), try emqx_bridge_resource:parse_bridge_id(BridgeId, #{atom_name => false}) of + %% NOTE + %% Bridge type is known, refine the API schema to get more specific error messages. {BridgeType, _Name} -> Schema = emqx_bridge_v2_schema:action_api_schema("put", BridgeType), - SpecRefined = Spec#{'requestBody' => Schema}, - emqx_dashboard_swagger:filter_check_request(Request, ReqMeta#{apispec => SpecRefined}) + emqx_dashboard_swagger:filter_check_request(Request, refine_api_schema(Schema, ReqMeta)) catch throw:#{reason := Reason} -> ?NOT_FOUND(<<"Invalid bridge ID, ", Reason/binary>>) end; +check_api_schema(Request, ReqMeta = #{path := "/sources/:id", method := put}) -> + SourceId = emqx_utils_maps:deep_get([bindings, id], Request), + try emqx_bridge_resource:parse_bridge_id(SourceId, #{atom_name => false}) of + %% NOTE + %% Source type is known, refine the API schema to get more specific error messages. + {BridgeType, _Name} -> + Schema = emqx_bridge_v2_schema:source_api_schema("put", BridgeType), + emqx_dashboard_swagger:filter_check_request(Request, refine_api_schema(Schema, ReqMeta)) + catch + throw:#{reason := Reason} -> + ?NOT_FOUND(<<"Invalid source ID, ", Reason/binary>>) + end; check_api_schema(Request, ReqMeta) -> emqx_dashboard_swagger:filter_check_request(Request, ReqMeta). +refine_api_schema(Schema, ReqMeta = #{path := Path, method := Method}) -> + Spec = maps:get(Method, schema(Path)), + SpecRefined = Spec#{'requestBody' => Schema}, + ReqMeta#{apispec => SpecRefined}. + %%------------------------------------------------------------------------------ %% Thin Handlers %%------------------------------------------------------------------------------ diff --git a/apps/emqx_bridge/src/schema/emqx_bridge_v2_schema.erl b/apps/emqx_bridge/src/schema/emqx_bridge_v2_schema.erl index d0b053467..d7270d206 100644 --- a/apps/emqx_bridge/src/schema/emqx_bridge_v2_schema.erl +++ b/apps/emqx_bridge/src/schema/emqx_bridge_v2_schema.erl @@ -40,6 +40,7 @@ sources_get_response/0, sources_put_request/0, sources_post_request/0, + source_api_schema/2, sources_examples/1, source_values/4 ]). @@ -169,6 +170,15 @@ sources_api_schema(Method) -> APISchemas = ?MODULE:registered_sources_api_schemas(Method), hoconsc:union(bridge_api_union(APISchemas)). +source_api_schema(Method, SourceType) -> + APISchemas = ?MODULE:registered_sources_api_schemas(Method), + case lists:keyfind(atom_to_binary(SourceType), 1, APISchemas) of + {_, SchemaRef} -> + hoconsc:mk(SchemaRef); + false -> + unknown_source_schema(SourceType) + end. + registered_sources_api_schemas(Method) -> RegisteredSchemas = emqx_action_info:registered_schema_modules_sources(), [ @@ -241,13 +251,19 @@ bridge_api_union(Refs) -> end end. --dialyzer({nowarn_function, [unknown_bridge_schema/1]}). unknown_bridge_schema(BridgeV2Type) -> + erroneous_value_schema(BridgeV2Type, <<"unknown bridge type">>). + +unknown_source_schema(SourceType) -> + erroneous_value_schema(SourceType, <<"unknown source type">>). + +-dialyzer({nowarn_function, [erroneous_value_schema/2]}). +erroneous_value_schema(Value, Reason) -> hoconsc:mk(typerefl:any(), #{ validator => fun(_) -> throw(#{ - value => BridgeV2Type, - reason => <<"unknown bridge type">> + value => Value, + reason => Reason }) end }).