diff options
Diffstat (limited to 'src/mod_http_api.erl')
-rw-r--r-- | src/mod_http_api.erl | 62 |
1 files changed, 30 insertions, 32 deletions
diff --git a/src/mod_http_api.erl b/src/mod_http_api.erl index 84866d4d0..e6e618bd0 100644 --- a/src/mod_http_api.erl +++ b/src/mod_http_api.erl @@ -80,6 +80,7 @@ -include("xmpp.hrl"). -include("logger.hrl"). -include("ejabberd_http.hrl"). +-include("ejabberd_stacktrace.hrl"). -define(DEFAULT_API_VERSION, 0). @@ -192,9 +193,8 @@ process([Call], #request{method = 'POST', data = Data, ip = IPPort} = Req) -> _:{error,{_,invalid_json}} = _Err -> ?DEBUG("Bad Request: ~p", [_Err]), badrequest_response(<<"Invalid JSON input">>); - _:_Error -> - St = erlang:get_stacktrace(), - ?DEBUG("Bad Request: ~p ~p", [_Error, St]), + ?EX_RULE(_Class, _Error, Stack) -> + ?DEBUG("Bad Request: ~p ~p", [_Error, ?EX_STACK(Stack)]), badrequest_response() end; process([Call], #request{method = 'GET', q = Data, ip = {IP, _}} = Req) -> @@ -210,9 +210,8 @@ process([Call], #request{method = 'GET', q = Data, ip = {IP, _}} = Req) -> %% TODO We need to refactor to remove redundant error return formatting throw:{error, unknown_command} -> json_format({404, 44, <<"Command not found.">>}); - _:_Error -> - St = erlang:get_stacktrace(), - ?DEBUG("Bad Request: ~p ~p", [_Error, St]), + ?EX_RULE(_, _Error, Stack) -> + ?DEBUG("Bad Request: ~p ~p", [_Error, ?EX_STACK(Stack)]), badrequest_response() end; process([_Call], #request{method = 'OPTIONS', data = <<>>}) -> @@ -274,20 +273,8 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) -> case ejabberd_commands:get_command_format(Call, Auth, Version) of {ArgsSpec, _} when is_list(ArgsSpec) -> Args2 = [{misc:binary_to_atom(Key), Value} || {Key, Value} <- Args], - Spec = lists:foldr( - fun ({Key, binary}, Acc) -> - [{Key, <<>>}|Acc]; - ({Key, string}, Acc) -> - [{Key, ""}|Acc]; - ({Key, integer}, Acc) -> - [{Key, 0}|Acc]; - ({Key, {list, _}}, Acc) -> - [{Key, []}|Acc]; - ({Key, atom}, Acc) -> - [{Key, undefined}|Acc] - end, [], ArgsSpec), try - handle2(Call, Auth, match(Args2, Spec), Version) + handle2(Call, Auth, Args2, Version) catch throw:not_found -> {404, <<"not_found">>}; throw:{not_found, Why} when is_atom(Why) -> @@ -301,9 +288,9 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) -> throw:{not_allowed, Msg} -> {401, iolist_to_binary(Msg)}; throw:{error, account_unprivileged} -> - {403, 31, <<"Command need to be run with admin privilege.">>}; - throw:{error, access_rules_unauthorized} -> - {403, 32, <<"AccessRules: Account does not have the right to perform the operation.">>}; + {403, 31, <<"Command need to be run with admin privilege.">>}; + throw:{error, access_rules_unauthorized} -> + {403, 32, <<"AccessRules: Account does not have the right to perform the operation.">>}; throw:{invalid_parameter, Msg} -> {400, iolist_to_binary(Msg)}; throw:{error, Why} when is_atom(Why) -> @@ -314,9 +301,8 @@ handle(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) -> {400, misc:atom_to_binary(Error)}; throw:Msg when is_list(Msg); is_binary(Msg) -> {400, iolist_to_binary(Msg)}; - _Error -> - St = erlang:get_stacktrace(), - ?ERROR_MSG("REST API Error: ~p ~p", [_Error, St]), + ?EX_RULE(Class, Error, Stack) -> + ?ERROR_MSG("REST API Error: ~p:~p ~p", [Class, Error, ?EX_STACK(Stack)]), {500, <<"internal_error">>} end; {error, Msg} -> @@ -337,15 +323,20 @@ handle2(Call, Auth, Args, Version) when is_atom(Call), is_list(Args) -> format_command_result(Call, Auth, Res, Version) end. -get_elem_delete(A, L) -> +get_elem_delete(A, L, F) -> case proplists:get_all_values(A, L) of [Value] -> {Value, proplists:delete(A, L)}; [_, _ | _] -> %% Crash reporting the error exit({duplicated_attribute, A, L}); [] -> - %% Report the error and then force a crash - exit({attribute_not_found, A, L}) + case F of + {list, _} -> + {[], L}; + _ -> + %% Report the error and then force a crash + exit({attribute_not_found, A, L}) + end end. format_args(Args, ArgsFormat) -> @@ -354,7 +345,7 @@ format_args(Args, ArgsFormat) -> {Args1, Res}) -> {ArgValue, Args2} = get_elem_delete(ArgName, - Args1), + Args1, ArgFormat), Formatted = format_arg(ArgValue, ArgFormat), {Args2, Res ++ [Formatted]} @@ -431,9 +422,6 @@ process_unicode_codepoints(Str) -> %% internal helpers %% ---------------- -match(Args, Spec) -> - [{Key, proplists:get_value(Key, Args, Default)} || {Key, Default} <- Spec]. - format_command_result(Cmd, Auth, Result, Version) -> {_, ResultFormat} = ejabberd_commands:get_command_format(Cmd, Auth, Version), case {ResultFormat, Result} of @@ -486,6 +474,9 @@ format_result(Code, {Name, restuple}) -> format_result(Els, {Name, {list, {_, {tuple, [{_, atom}, _]}} = Fmt}}) -> {misc:atom_to_binary(Name), {[format_result(El, Fmt) || El <- Els]}}; +format_result(Els, {Name, {list, {_, {tuple, [{name, string}, {value, _}]}} = Fmt}}) -> + {misc:atom_to_binary(Name), {[format_result(El, Fmt) || El <- Els]}}; + format_result(Els, {Name, {list, Def}}) -> {misc:atom_to_binary(Name), [element(2, format_result(El, Def)) || El <- Els]}; @@ -494,6 +485,11 @@ format_result(Tuple, {_Name, {tuple, [{_, atom}, ValFmt]}}) -> {_, Val2} = format_result(Val, ValFmt), {misc:atom_to_binary(Name2), Val2}; +format_result(Tuple, {_Name, {tuple, [{name, string}, {value, _} = ValFmt]}}) -> + {Name2, Val} = Tuple, + {_, Val2} = format_result(Val, ValFmt), + {iolist_to_binary(Name2), Val2}; + format_result(Tuple, {Name, {tuple, Def}}) -> Els = lists:zip(tuple_to_list(Tuple), Def), {misc:atom_to_binary(Name), {[format_result(El, ElDef) || {El, ElDef} <- Els]}}; @@ -504,6 +500,8 @@ format_result(404, {_Name, _}) -> format_error_result(conflict, Code, Msg) -> {409, Code, iolist_to_binary(Msg)}; +format_error_result(not_exists, Code, Msg) -> + {404, Code, iolist_to_binary(Msg)}; format_error_result(_ErrorAtom, Code, Msg) -> {500, Code, iolist_to_binary(Msg)}. |