fix(mgmt): avoid 500 error when hocon syntax error

This commit is contained in:
zmstone 2024-04-27 21:02:09 +02:00
parent a3320ab51b
commit 5f4215b333
3 changed files with 36 additions and 18 deletions

View File

@ -32,7 +32,7 @@
-export([format/2]).
%% For CLI HTTP API outputs
-export([best_effort_json/1, best_effort_json/2]).
-export([best_effort_json/1, best_effort_json/2, best_effort_json_obj/1]).
-ifdef(TEST).
-include_lib("proper/include/proper.hrl").
@ -65,10 +65,13 @@
best_effort_json(Input) ->
best_effort_json(Input, [pretty, force_utf8]).
best_effort_json(Input, Opts) ->
Config = #{depth => unlimited, single_line => true, chars_limit => unlimited},
JsonReady = best_effort_json_obj(Input, Config),
JsonReady = best_effort_json_obj(Input),
emqx_utils_json:encode(JsonReady, Opts).
best_effort_json_obj(Input) ->
Config = #{depth => unlimited, single_line => true, chars_limit => unlimited},
best_effort_json_obj(Input, Config).
-spec format(logger:log_event(), config()) -> iodata().
format(#{level := Level, msg := Msg, meta := Meta}, Config0) when is_map(Config0) ->
Config = add_default_config(Config0),

View File

@ -366,11 +366,8 @@ configs(put, #{body := Conf, query_string := #{<<"mode">> := Mode}}, _Req) ->
ok ->
{200};
%% bad hocon format
{error, MsgList = [{_, _} | _]} ->
JsonFun = fun(K, V) -> {K, emqx_utils_maps:binary_string(V)} end,
JsonMap = emqx_utils_maps:jsonable_map(maps:from_list(MsgList), JsonFun),
{400, #{<<"content-type">> => <<"text/plain">>}, JsonMap};
{error, Msg} ->
{error, Errors} ->
Msg = emqx_logger_jsonfmt:best_effort_json_obj(#{errors => Errors}),
{400, #{<<"content-type">> => <<"text/plain">>}, Msg}
end.

View File

@ -336,13 +336,15 @@ t_configs_key(_Config) ->
BadLog = emqx_utils_maps:deep_put([<<"log">>, <<"console">>, <<"level">>], Log, <<"erro1r">>),
{error, Error} = update_configs_with_binary(iolist_to_binary(hocon_pp:do(BadLog, #{}))),
ExpectError = #{
<<"log">> =>
#{
<<"kind">> => <<"validation_error">>,
<<"path">> => <<"log.console.level">>,
<<"reason">> => <<"unable_to_convert_to_enum_symbol">>,
<<"value">> => <<"erro1r">>
}
<<"errors">> => #{
<<"log">> =>
#{
<<"kind">> => <<"validation_error">>,
<<"path">> => <<"log.console.level">>,
<<"reason">> => <<"unable_to_convert_to_enum_symbol">>,
<<"value">> => <<"erro1r">>
}
}
},
?assertEqual(ExpectError, emqx_utils_json:decode(Error, [return_maps])),
ReadOnlyConf = #{
@ -355,7 +357,7 @@ t_configs_key(_Config) ->
},
ReadOnlyBin = iolist_to_binary(hocon_pp:do(ReadOnlyConf, #{})),
{error, ReadOnlyError} = update_configs_with_binary(ReadOnlyBin),
?assertEqual(<<"Cannot update read-only key 'cluster'.">>, ReadOnlyError),
?assertEqual(<<"{\"errors\":\"Cannot update read-only key 'cluster'.\"}">>, ReadOnlyError),
ok.
t_get_configs_in_different_accept(_Config) ->
@ -487,6 +489,22 @@ t_create_webhook_v1_bridges_api(Config) ->
?assertEqual(#{<<"webhook">> => #{}}, emqx_conf:get_raw([<<"bridges">>])),
ok.
t_config_update_parse_error(_Config) ->
?assertMatch(
{error, <<"{\"errors\":\"{parse_error,", _/binary>>},
update_configs_with_binary(<<"not an object">>)
),
?assertMatch(
{error, <<"{\"errors\":\"{parse_error,", _/binary>>},
update_configs_with_binary(<<"a = \"tlsv1\"\"\"3e-01">>)
).
t_config_update_unknown_root(_Config) ->
?assertMatch(
{error, <<"{\"errors\":{\"a\":\"{root_key_not_found,", _/binary>>},
update_configs_with_binary(<<"a = \"tlsv1.3\"">>)
).
%% Helpers
get_config(Name) ->
@ -547,10 +565,10 @@ update_configs_with_binary(Bin) ->
Code >= 200 andalso Code =< 299
->
Body;
{ok, {{"HTTP/1.1", _Code, _}, _Headers, Body}} ->
{ok, {{"HTTP/1.1", 400, _}, _Headers, Body}} ->
{error, Body};
Error ->
Error
error({unexpected, Error})
end.
update_config(Name, Change) ->