mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
Add support for rich error reporting for API
This commit is contained in:
parent
fb2603d3cd
commit
39640b67c7
@ -380,13 +380,12 @@ register(User, Host, Password) ->
|
|||||||
{atomic, ok} ->
|
{atomic, ok} ->
|
||||||
{ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
|
{ok, io_lib:format("User ~s@~s successfully registered", [User, Host])};
|
||||||
{atomic, exists} ->
|
{atomic, exists} ->
|
||||||
String = io_lib:format("User ~s@~s already registered at node ~p",
|
Msg = io_lib:format("User ~s@~s already registered", [User, Host]),
|
||||||
[User, Host, node()]),
|
{error, conflict, 10090, Msg};
|
||||||
{conflict, String};
|
|
||||||
{error, Reason} ->
|
{error, Reason} ->
|
||||||
String = io_lib:format("Can't register user ~s@~s at node ~p: ~p",
|
String = io_lib:format("Can't register user ~s@~s at node ~p: ~p",
|
||||||
[User, Host, node(), Reason]),
|
[User, Host, node(), Reason]),
|
||||||
{cannot_register, String}
|
{error, cannot_register, 10001, String}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
unregister(User, Host) ->
|
unregister(User, Host) ->
|
||||||
|
@ -212,7 +212,7 @@ process(["help" | Mode], Version) ->
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
process(["--version", Arg | Args], _) ->
|
process(["--version", Arg | Args], _) ->
|
||||||
Version =
|
Version =
|
||||||
try
|
try
|
||||||
list_to_integer(Arg)
|
list_to_integer(Arg)
|
||||||
catch _:_ ->
|
catch _:_ ->
|
||||||
@ -321,7 +321,7 @@ call_command([CmdString | Args], Auth, AccessCommands, Version) ->
|
|||||||
{ArgsFormat, ResultFormat} ->
|
{ArgsFormat, ResultFormat} ->
|
||||||
case (catch format_args(Args, ArgsFormat)) of
|
case (catch format_args(Args, ArgsFormat)) of
|
||||||
ArgsFormatted when is_list(ArgsFormatted) ->
|
ArgsFormatted when is_list(ArgsFormatted) ->
|
||||||
Result = ejabberd_commands:execute_command(AccessCommands,
|
Result = ejabberd_commands:execute_command(AccessCommands,
|
||||||
Auth, Command,
|
Auth, Command,
|
||||||
ArgsFormatted,
|
ArgsFormatted,
|
||||||
Version),
|
Version),
|
||||||
@ -374,6 +374,12 @@ format_arg2(Arg, Parse)->
|
|||||||
format_result({error, ErrorAtom}, _) ->
|
format_result({error, ErrorAtom}, _) ->
|
||||||
{io_lib:format("Error: ~p", [ErrorAtom]), make_status(error)};
|
{io_lib:format("Error: ~p", [ErrorAtom]), make_status(error)};
|
||||||
|
|
||||||
|
%% An error should always be allowed to return extended error to help with API.
|
||||||
|
%% Extended error is of the form:
|
||||||
|
%% {error, type :: atom(), code :: int(), Desc :: string()}
|
||||||
|
format_result({error, ErrorAtom, Code, _Msg}, _) ->
|
||||||
|
{io_lib:format("Error: ~p", [ErrorAtom]), make_status(Code)};
|
||||||
|
|
||||||
format_result(Atom, {_Name, atom}) ->
|
format_result(Atom, {_Name, atom}) ->
|
||||||
io_lib:format("~p", [Atom]);
|
io_lib:format("~p", [Atom]);
|
||||||
|
|
||||||
@ -433,6 +439,7 @@ format_result(404, {_Name, _}) ->
|
|||||||
|
|
||||||
make_status(ok) -> ?STATUS_SUCCESS;
|
make_status(ok) -> ?STATUS_SUCCESS;
|
||||||
make_status(true) -> ?STATUS_SUCCESS;
|
make_status(true) -> ?STATUS_SUCCESS;
|
||||||
|
make_status(Code) when is_integer(Code) -> Code;
|
||||||
make_status(_Error) -> ?STATUS_ERROR.
|
make_status(_Error) -> ?STATUS_ERROR.
|
||||||
|
|
||||||
get_list_commands(Version) ->
|
get_list_commands(Version) ->
|
||||||
|
@ -220,12 +220,8 @@ process([Call], #request{method = 'POST', data = Data, ip = {IP, _} = IPPort} =
|
|||||||
log(Call, Args, IPPort),
|
log(Call, Args, IPPort),
|
||||||
case check_permissions(Req, Call) of
|
case check_permissions(Req, Call) of
|
||||||
{allowed, Cmd, Auth} ->
|
{allowed, Cmd, Auth} ->
|
||||||
case handle(Cmd, Auth, Args, Version, IP) of
|
Result = handle(Cmd, Auth, Args, Version, IP),
|
||||||
{Code, Result} ->
|
json_format(Result);
|
||||||
json_response(Code, jiffy:encode(Result));
|
|
||||||
{HTMLCode, JSONErrorCode, Message} ->
|
|
||||||
json_error(HTMLCode, JSONErrorCode, Message)
|
|
||||||
end;
|
|
||||||
%% Warning: check_permission direcly formats 401 reply if not authorized
|
%% Warning: check_permission direcly formats 401 reply if not authorized
|
||||||
ErrorResponse ->
|
ErrorResponse ->
|
||||||
ErrorResponse
|
ErrorResponse
|
||||||
@ -247,8 +243,8 @@ process([Call], #request{method = 'GET', q = Data, ip = IP} = Req) ->
|
|||||||
log(Call, Args, IP),
|
log(Call, Args, IP),
|
||||||
case check_permissions(Req, Call) of
|
case check_permissions(Req, Call) of
|
||||||
{allowed, Cmd, Auth} ->
|
{allowed, Cmd, Auth} ->
|
||||||
{Code, Result} = handle(Cmd, Auth, Args, Version, IP),
|
Result = handle(Cmd, Auth, Args, Version, IP),
|
||||||
json_response(Code, jiffy:encode(Result));
|
json_format(Result);
|
||||||
%% Warning: check_permission direcly formats 401 reply if not authorized
|
%% Warning: check_permission direcly formats 401 reply if not authorized
|
||||||
ErrorResponse ->
|
ErrorResponse ->
|
||||||
ErrorResponse
|
ErrorResponse
|
||||||
@ -302,7 +298,7 @@ handle(Call, Auth, Args, Version, IP) when is_atom(Call), is_list(Args) ->
|
|||||||
[{Key, undefined}|Acc]
|
[{Key, undefined}|Acc]
|
||||||
end, [], ArgsSpec),
|
end, [], ArgsSpec),
|
||||||
try
|
try
|
||||||
handle2(Call, Auth, match(Args2, Spec), Version, IP)
|
handle2(Call, Auth, match(Args2, Spec), Version, IP)
|
||||||
catch throw:not_found ->
|
catch throw:not_found ->
|
||||||
{404, <<"not_found">>};
|
{404, <<"not_found">>};
|
||||||
throw:{not_found, Why} when is_atom(Why) ->
|
throw:{not_found, Why} when is_atom(Why) ->
|
||||||
@ -448,12 +444,12 @@ format_command_result(Cmd, Auth, Result, Version) ->
|
|||||||
{200, 0};
|
{200, 0};
|
||||||
{{_, rescode}, _} ->
|
{{_, rescode}, _} ->
|
||||||
{200, 1};
|
{200, 1};
|
||||||
|
{_, {error, ErrorAtom, Code, Msg}} ->
|
||||||
|
format_error_result(ErrorAtom, Code, Msg);
|
||||||
{{_, restuple}, {V, Text}} when V == true; V == ok ->
|
{{_, restuple}, {V, Text}} when V == true; V == ok ->
|
||||||
{200, iolist_to_binary(Text)};
|
{200, iolist_to_binary(Text)};
|
||||||
{{_, restuple}, {V, Text}} when V == conflict ->
|
{{_, restuple}, {ErrorAtom, Msg}} ->
|
||||||
{409, iolist_to_binary(Text)};
|
format_error_result(ErrorAtom, 0, Msg);
|
||||||
{{_, restuple}, {_, Text2}} ->
|
|
||||||
{500, iolist_to_binary(Text2)};
|
|
||||||
{{_, {list, _}}, _V} ->
|
{{_, {list, _}}, _V} ->
|
||||||
{_, L} = format_result(Result, ResultFormat),
|
{_, L} = format_result(Result, ResultFormat),
|
||||||
{200, L};
|
{200, L};
|
||||||
@ -499,6 +495,11 @@ format_result(Tuple, {Name, {tuple, Def}}) ->
|
|||||||
format_result(404, {_Name, _}) ->
|
format_result(404, {_Name, _}) ->
|
||||||
"not_found".
|
"not_found".
|
||||||
|
|
||||||
|
format_error_result(conflict, Code, Msg) ->
|
||||||
|
{409, Code, iolist_to_binary(Msg)};
|
||||||
|
format_error_result(_ErrorAtom, Code, Msg) ->
|
||||||
|
{500, Code, iolist_to_binary(Msg)}.
|
||||||
|
|
||||||
unauthorized_response() ->
|
unauthorized_response() ->
|
||||||
json_error(401, 10, <<"Oauth Token is invalid or expired.">>).
|
json_error(401, 10, <<"Oauth Token is invalid or expired.">>).
|
||||||
|
|
||||||
@ -507,6 +508,11 @@ badrequest_response() ->
|
|||||||
badrequest_response(Body) ->
|
badrequest_response(Body) ->
|
||||||
json_response(400, jiffy:encode(Body)).
|
json_response(400, jiffy:encode(Body)).
|
||||||
|
|
||||||
|
json_format({Code, Result}) ->
|
||||||
|
json_response(Code, jiffy:encode(Result));
|
||||||
|
json_format({HTMLCode, JSONErrorCode, Message}) ->
|
||||||
|
json_error(HTMLCode, JSONErrorCode, Message).
|
||||||
|
|
||||||
json_response(Code, Body) when is_integer(Code) ->
|
json_response(Code, Body) when is_integer(Code) ->
|
||||||
{Code, ?HEADER(?CT_JSON), Body}.
|
{Code, ?HEADER(?CT_JSON), Body}.
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user