mirror of
https://github.com/mailscope/kumomta.git
synced 2026-09-09 03:52:13 +00:00
typing: refine error handling for _dynamic fields
Better distinguish between unknown and mismatched types for dynamic fields, and show a better error message for them. refs: #211
This commit is contained in:
@@ -14,9 +14,11 @@ local function is_listener_domain_option(name, value)
|
||||
local p = { [name] = value }
|
||||
local status, err = pcall(kumo.make_listener_domain, p)
|
||||
if not status then
|
||||
local err = typing.extract_deserialize_error(err)
|
||||
if tostring(err):find 'invalid type' then
|
||||
error(err, 3)
|
||||
return false, err
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
return status
|
||||
end
|
||||
@@ -332,6 +334,20 @@ log_oob = false
|
||||
),
|
||||
{ relay_from = { '10.0.0.0/24' }, relay_to = false }
|
||||
)
|
||||
|
||||
local status, err = pcall(
|
||||
parse_toml_data,
|
||||
[[
|
||||
# Define a per-listener configuration
|
||||
[listener."127.0.0.1:25"."*.example.com"]
|
||||
log_arf = "yes"
|
||||
]]
|
||||
)
|
||||
assert(not status)
|
||||
utils.assert_matches(
|
||||
err,
|
||||
'ListenerConfig: invalid value for field \'log_arf\'\n.*invalid type: string "yes", expected a boolean'
|
||||
)
|
||||
end
|
||||
|
||||
return mod
|
||||
|
||||
@@ -75,9 +75,11 @@ local function is_queue_config_option(name, value)
|
||||
local p = { [name] = value }
|
||||
local status, err = pcall(kumo.make_queue_config, p)
|
||||
if not status then
|
||||
local err = typing.extract_deserialize_error(err)
|
||||
if tostring(err):find 'invalid type' then
|
||||
error(err, 3)
|
||||
return false, err
|
||||
end
|
||||
return false, nil
|
||||
end
|
||||
return status
|
||||
end
|
||||
|
||||
@@ -176,7 +176,10 @@ end
|
||||
-- rust code in the embedding application. The value in that
|
||||
-- case must be a function that accepts the key and value
|
||||
-- and returns a boolean to indicate whether that combination
|
||||
-- is acceptable.
|
||||
-- is acceptable. If the function returns `false, nil` then
|
||||
-- that signals that the field is unknown. Otherwise it should
|
||||
-- return `false, err` with the second element of the tuple
|
||||
-- containing the error about the mismatched type.
|
||||
--
|
||||
-- { _dynamic = function(key, value) return true end }
|
||||
function mod.record(name, fields)
|
||||
@@ -204,9 +207,20 @@ function mod.record(name, fields)
|
||||
local field_def = ty.fields[k]
|
||||
if not field_def then
|
||||
local dyn_validate = ty.fields._dynamic
|
||||
if dyn_validate and dyn_validate(k, v) then
|
||||
rawset(t, k, v)
|
||||
return
|
||||
if dyn_validate then
|
||||
local status, err = dyn_validate(k, v)
|
||||
if status then
|
||||
rawset(t, k, v)
|
||||
return
|
||||
end
|
||||
if err then
|
||||
TypeError
|
||||
:new(
|
||||
string.format("%s: invalid value for field '%s'", ty.name, k),
|
||||
err
|
||||
)
|
||||
:raise()
|
||||
end
|
||||
end
|
||||
|
||||
TypeError:new(string.format("%s: unknown field '%s'", ty.name, k))
|
||||
@@ -499,6 +513,16 @@ function mod.option(target_type)
|
||||
return make_simple_ctor(ty)
|
||||
end
|
||||
|
||||
function mod.extract_deserialize_error(err)
|
||||
local err = tostring(err)
|
||||
local re = kumo.regex.compile 'deserialize error: (.*), while processing'
|
||||
local cap = re:captures(err)
|
||||
if cap then
|
||||
return cap[1]
|
||||
end
|
||||
return err
|
||||
end
|
||||
|
||||
function mod:test()
|
||||
local utils = require 'policy-extras.policy_utils'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user