fix: don't allow empty string in server_port schema

This commit is contained in:
Zhongwen Deng 2023-03-13 12:08:19 +08:00
parent 823128dfc7
commit 5be4d97c42
2 changed files with 73 additions and 19 deletions

View File

@ -2608,7 +2608,7 @@ non_empty_string(_) -> {error, invalid_string}.
servers_sc(Meta0, ParseOpts) -> servers_sc(Meta0, ParseOpts) ->
%% if this filed has a default value %% if this filed has a default value
%% then it is not NOT required %% then it is not NOT required
%% NOTE: maps:is_key is not the solution beause #{default => undefined} is legit %% NOTE: maps:is_key is not the solution because #{default => undefined} is legit
HasDefault = (maps:get(default, Meta0, undefined) =/= undefined), HasDefault = (maps:get(default, Meta0, undefined) =/= undefined),
Required = maps:get(required, Meta0, not HasDefault), Required = maps:get(required, Meta0, not HasDefault),
Meta = #{ Meta = #{
@ -2661,17 +2661,18 @@ normalize_host_port_str(Str) ->
%% NOTE: Validator is called after converter. %% NOTE: Validator is called after converter.
servers_validator(Opts, Required) -> servers_validator(Opts, Required) ->
fun(Str0) -> fun(Str0) ->
Str = str(Str0), case str(Str0) of
case Str =:= "" orelse Str =:= "undefined" of "" ->
true when Required -> %% Empty string is not allowed even if the field is not required
%% it's a required field %% remove field from config if it's empty
%% but value is set to an empty string (from environment override) throw("cannot_be_empty");
%% or when the filed is not set in config file "undefined" when Required ->
%% when the filed is not set in config file
%% NOTE: assuming nobody is going to name their server "undefined" %% NOTE: assuming nobody is going to name their server "undefined"
throw("cannot_be_empty"); throw("cannot_be_empty");
true -> "undefined" ->
ok; ok;
_ -> Str ->
%% it's valid as long as it can be parsed %% it's valid as long as it can be parsed
_ = parse_servers(Str, Opts), _ = parse_servers(Str, Opts),
ok ok
@ -2816,20 +2817,17 @@ is_port_number(Port) ->
end. end.
parse_port(Port) -> parse_port(Port) ->
try case string:to_integer(string:strip(Port)) of
P = list_to_integer(string:strip(Port)), {P, ""} when P < 0 -> throw("port_number_too_small");
true = (P > 0), {P, ""} when P > 65535 -> throw("port_number_too_large");
true = (P =< 65535), {P, ""} -> P;
P _ -> throw("bad_port_number")
catch
_:_ ->
throw("bad_port_number")
end. end.
quic_feature_toggle(Desc) -> quic_feature_toggle(Desc) ->
sc( sc(
%% true, false are for user facing %% true, false are for user facing
%% 0, 1 are for internal represtation %% 0, 1 are for internal representation
typerefl:alias("boolean", typerefl:union([true, false, 0, 1])), typerefl:alias("boolean", typerefl:union([true, false, 0, 1])),
#{ #{
desc => Desc, desc => Desc,

View File

@ -33,6 +33,26 @@
"tags {\"t1\" = \"good\", test = 100}\n" "tags {\"t1\" = \"good\", test = 100}\n"
"}\n" "}\n"
>>). >>).
-define(BAD_CONF, <<
"\n"
"statsd {\n"
"enable = true\n"
"flush_time_interval = 4s\n"
"sample_time_interval = 4s\n"
"server = \"\"\n"
"tags {\"t1\" = \"good\", test = 100}\n"
"}\n"
>>).
-define(DEFAULT_CONF, <<
"\n"
"statsd {\n"
"enable = true\n"
"flush_time_interval = 4s\n"
"sample_time_interval = 4s\n"
"tags {\"t1\" = \"good\", test = 100}\n"
"}\n"
>>).
init_per_suite(Config) -> init_per_suite(Config) ->
emqx_common_test_helpers:start_apps( emqx_common_test_helpers:start_apps(
@ -55,6 +75,33 @@ set_special_configs(_) ->
all() -> all() ->
emqx_common_test_helpers:all(?MODULE). emqx_common_test_helpers:all(?MODULE).
t_server_validator(_) ->
Server0 = emqx_conf:get_raw([statsd, server]),
?assertThrow(
#{
kind := validation_error,
path := "statsd.server",
reason := "cannot_be_empty",
value := ""
},
emqx_common_test_helpers:load_config(emqx_statsd_schema, ?BAD_CONF, #{
raw_with_default => true
})
),
%% default
ok = emqx_common_test_helpers:load_config(emqx_statsd_schema, ?DEFAULT_CONF, #{
raw_with_default => true
}),
undefined = emqx_conf:get_raw([statsd, server], undefined),
?assertMatch("127.0.0.1:8125", emqx_conf:get([statsd, server])),
%% recover
ok = emqx_common_test_helpers:load_config(emqx_statsd_schema, ?BASE_CONF, #{
raw_with_default => true
}),
Server2 = emqx_conf:get_raw([statsd, server]),
?assertMatch(Server0, Server2),
ok.
t_statsd(_) -> t_statsd(_) ->
{ok, Socket} = gen_udp:open(8126, [{active, true}]), {ok, Socket} = gen_udp:open(8126, [{active, true}]),
receive receive
@ -137,7 +184,16 @@ t_config_update(_) ->
?assertNotEqual(OldPid, NewPid) ?assertNotEqual(OldPid, NewPid)
after after
{ok, _} = emqx_statsd_config:update(OldRawConf) {ok, _} = emqx_statsd_config:update(OldRawConf)
end. end,
%% bad server url
BadRawConf = OldRawConf#{<<"server">> := <<"">>},
{error, #{
kind := validation_error,
path := "statsd.server",
reason := "cannot_be_empty",
value := ""
}} = emqx_statsd_config:update(BadRawConf),
ok.
request(Method) -> request(Method, []). request(Method) -> request(Method, []).