From 6ea7153e31a8d36fbb34816b4c87ea3eca1ac8fc Mon Sep 17 00:00:00 2001 From: Mickael Remond Date: Sun, 31 Jul 2016 22:48:24 +0200 Subject: [PATCH] Improve error handling --- src/ejabberd_admin.erl | 1 + src/ejabberd_commands.erl | 2 +- src/mod_http_api.erl | 34 ++++++++++++++++++++++++---------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/ejabberd_admin.erl b/src/ejabberd_admin.erl index 2c4d5ed6d..615459f77 100644 --- a/src/ejabberd_admin.erl +++ b/src/ejabberd_admin.erl @@ -87,6 +87,7 @@ get_commands_spec() -> args = [], result = {res, rescode}}, #ejabberd_commands{name = reopen_log, tags = [logs, server], desc = "Reopen the log files", + policy = admin, module = ?MODULE, function = reopen_log, args = [], result = {res, rescode}}, #ejabberd_commands{name = rotate_log, tags = [logs, server], diff --git a/src/ejabberd_commands.erl b/src/ejabberd_commands.erl index d9497322f..a8b3e25ab 100644 --- a/src/ejabberd_commands.erl +++ b/src/ejabberd_commands.erl @@ -425,7 +425,7 @@ get_command_definition(Name, Version) -> {V, C} end)))) of [{_, Command} | _ ] -> Command; - _E -> throw(unknown_command) + _E -> throw({error, unknown_command}) end. -spec get_commands_definition(integer()) -> [ejabberd_commands()]. diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl index cda4d6059..d33fb7a7f 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -213,11 +213,7 @@ process(_, #request{method = 'POST', data = <<>>}) -> process([Call], #request{method = 'POST', data = Data, ip = {IP, _} = IPPort} = Req) -> Version = get_api_version(Req), try - Args = case jiffy:decode(Data) of - List when is_list(List) -> List; - {List} when is_list(List) -> List; - Other -> [Other] - end, + Args = extract_args(Data), log(Call, Args, IPPort), case check_permissions(Req, Call) of {allowed, Cmd, Auth} -> @@ -227,10 +223,14 @@ process([Call], #request{method = 'POST', data = Data, ip = {IP, _} = IPPort} = ErrorResponse -> ErrorResponse end - catch _:{error,{_,invalid_json}} = _Err -> - ?DEBUG("Bad Request: ~p", [_Err]), - badrequest_response(<<"Invalid JSON input">>); - _:_Error -> + catch + %% TODO We need to refactor to remove redundant error return formatting + throw:{error, unknown_command} -> + {404, 40, <<"Command not found.">>}; + _:{error,{_,invalid_json}} = _Err -> + ?DEBUG("Bad Request: ~p", [_Err]), + badrequest_response(<<"Invalid JSON input">>); + _:_Error -> ?DEBUG("Bad Request: ~p ~p", [_Error, erlang:get_stacktrace()]), badrequest_response() end; @@ -250,7 +250,12 @@ process([Call], #request{method = 'GET', q = Data, ip = IP} = Req) -> ErrorResponse -> ErrorResponse end - catch _:_Error -> + catch + %% TODO We need to refactor to remove redundant error return formatting + throw:{error, unknown_command} -> + {404, 40, <<"Command not found.">>}; + _:_Error -> + ?DEBUG("Bad Request: ~p ~p", [_Error, erlang:get_stacktrace()]), badrequest_response() end; @@ -260,6 +265,15 @@ process(_Path, Request) -> ?DEBUG("Bad Request: no handler ~p", [Request]), badrequest_response(). +%% Be tolerant to make API more easily usable from command-line pipe. +extract_args(<<"\n">>) -> []; +extract_args(Data) -> + case jiffy:decode(Data) of + List when is_list(List) -> List; + {List} when is_list(List) -> List; + Other -> [Other] + end. + % get API version N from last "vN" element in URL path get_api_version(#request{path = Path}) -> get_api_version(lists:reverse(Path));