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".
api_spec() ->
emqx_dashboard_swagger:spec(?MODULE).
emqx_dashboard_swagger:spec(?MODULE, #{check_schema => true}).
paths() -> ["/login", "/logout", "/users",
"/users/:username", "/users/:username/change_pwd"].

View File

@ -4,7 +4,7 @@
-include_lib("hocon/include/hoconsc.hrl").
%% API
-export([spec/1]).
-export([spec/1, spec/2]).
-export([translate_req/2]).
-ifdef(TEST).
@ -24,23 +24,37 @@
-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_)])).
-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(),
Specs :: map(),
OperationId :: atom(),
Options :: #{filter => fun((map(),
#{module => module(), path => string(), method => atom()}) -> 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, []),
{ApiSpec, AllRefs} =
lists:foldl(fun(Path, {AllAcc, AllRefsAcc}) ->
{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}
end, {[], []}, Paths),
{ApiSpec, components(lists:usort(AllRefs))}.
-spec(translate_req(#{binding => list(), query_string => list(), body => map()},
#{module => module(), path => string(), method => atom()}) ->
{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]))}
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) ->
Schema =
try

View File

@ -162,7 +162,13 @@ t_in_mix_trans_error(_Config) ->
ok.
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.
validate(Path, ExpectParams) ->