chore(swagger): support check_schema option, default is false.

This commit is contained in:
zhongwencool 2021-09-22 09:55:12 +08:00
parent 39423665e9
commit 96fad3d225
3 changed files with 30 additions and 6 deletions

View File

@ -41,7 +41,7 @@
namespace() -> "dashboard". namespace() -> "dashboard".
api_spec() -> api_spec() ->
emqx_dashboard_swagger:spec(?MODULE). emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
paths() -> ["/login", "/logout", "/users", paths() -> ["/login", "/logout", "/users",
"/users/:username", "/users/:username/change_pwd"]. "/users/:username", "/users/:username/change_pwd"].

View File

@ -4,7 +4,7 @@
-include_lib("hocon/include/hoconsc.hrl"). -include_lib("hocon/include/hoconsc.hrl").
%% API %% API
-export([spec/1]). -export([spec/1, spec/2]).
-export([translate_req/2]). -export([translate_req/2]).
-ifdef(TEST). -ifdef(TEST).
@ -24,23 +24,37 @@
-define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])). -define(TO_REF(_N_, _F_), iolist_to_binary([to_bin(_N_), ".", to_bin(_F_)])).
-define(TO_COMPONENTS(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>, ?TO_REF(namespace(_M_), _F_)])). -define(TO_COMPONENTS(_M_, _F_), iolist_to_binary([<<"#/components/schemas/">>, ?TO_REF(namespace(_M_), _F_)])).
-spec(spec(module()) -> {list({Path, Specs, OperationId, Options}), list(Component)} when %% @equiv spec(Module, #{check_schema => false})
-spec(spec(module()) ->
{list({Path, Specs, OperationId, Options}), list(Component)} when
Path :: string()|binary(), Path :: string()|binary(),
Specs :: map(), Specs :: map(),
OperationId :: atom(), OperationId :: atom(),
Options :: #{filter => fun((map(), Options :: #{filter => fun((map(),
#{module => module(), path => string(), method => atom()}) -> map())}, #{module => module(), path => string(), method => atom()}) -> map())},
Component :: map()). Component :: map()).
spec(Module) -> spec(Module) -> spec(Module, #{check_schema => false}).
-spec(spec(module(), #{check_schema => boolean()}) ->
{list({Path, Specs, OperationId, Options}), list(Component)} when
Path :: string()|binary(),
Specs :: map(),
OperationId :: atom(),
Options :: #{filter => fun((map(),
#{module => module(), path => string(), method => atom()}) -> map())},
Component :: map()).
spec(Module, Options) ->
Paths = apply(Module, paths, []), Paths = apply(Module, paths, []),
{ApiSpec, AllRefs} = {ApiSpec, AllRefs} =
lists:foldl(fun(Path, {AllAcc, AllRefsAcc}) -> lists:foldl(fun(Path, {AllAcc, AllRefsAcc}) ->
{OperationId, Specs, Refs} = parse_spec_ref(Module, Path), {OperationId, Specs, Refs} = parse_spec_ref(Module, Path),
{[{Path, Specs, OperationId, ?DEFAULT_FILTER} | AllAcc], CheckSchema = support_check_schema(Options),
{[{Path, Specs, OperationId, CheckSchema} | AllAcc],
Refs ++ AllRefsAcc} Refs ++ AllRefsAcc}
end, {[], []}, Paths), end, {[], []}, Paths),
{ApiSpec, components(lists:usort(AllRefs))}. {ApiSpec, components(lists:usort(AllRefs))}.
-spec(translate_req(#{binding => list(), query_string => list(), body => map()}, -spec(translate_req(#{binding => list(), query_string => list(), body => map()},
#{module => module(), path => string(), method => atom()}) -> #{module => module(), path => string(), method => atom()}) ->
{ok, #{binding => list(), query_string => list(), body => map()}}| {ok, #{binding => list(), query_string => list(), body => map()}}|
@ -59,6 +73,10 @@ translate_req(Request, #{module := Module, path := Path, method := Method}) ->
{400, 'BAD_REQUEST', iolist_to_binary(io_lib:format("~s : ~p", [Key, Reason]))} {400, 'BAD_REQUEST', iolist_to_binary(io_lib:format("~s : ~p", [Key, Reason]))}
end. end.
support_check_schema(#{check_schema := true}) -> ?DEFAULT_FILTER;
support_check_schema(#{check_schema := Func})when is_function(Func, 2) -> #{filter => Func};
support_check_schema(_) -> #{filter => undefined}.
parse_spec_ref(Module, Path) -> parse_spec_ref(Module, Path) ->
Schema = Schema =
try try

View File

@ -162,7 +162,13 @@ t_in_mix_trans_error(_Config) ->
ok. ok.
t_api_spec(_Config) -> t_api_spec(_Config) ->
emqx_dashboard_swagger:spec(?MODULE), {Spec, _Components} = emqx_dashboard_swagger:spec(?MODULE),
Filter = fun(V, S) -> lists:all(fun({_, _, _, #{filter := Filter}}) -> Filter =:= V end, S) end,
?assertEqual(true, Filter(undefined, Spec)),
{Spec1, _Components1} = emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}),
?assertEqual(true, Filter(fun emqx_dashboard_swagger:translate_req/2, Spec1)),
{Spec2, _Components2} = emqx_dashboard_swagger:spec(?MODULE, #{check_schema => fun emqx_dashboard_swagger:translate_req/2}),
?assertEqual(true, Filter(fun emqx_dashboard_swagger:translate_req/2, Spec2)),
ok. ok.
validate(Path, ExpectParams) -> validate(Path, ExpectParams) ->