From 5a272e4fbe797873f088d46db63ae9dff4c20294 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Hoguin?= Date: Sat, 1 Jul 2017 16:10:27 +0200 Subject: Aggregate validation errors and pass them in exception --- src/cowboy_req.erl | 50 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/src/cowboy_req.erl b/src/cowboy_req.erl index 3eca379..fc82308 100644 --- a/src/cowboy_req.erl +++ b/src/cowboy_req.erl @@ -762,28 +762,46 @@ kvlist_to_map(Keys, [{Key, Value}|Tail], Map) -> kvlist_to_map(Keys, Tail, Map) end. -%% Loop through fields, if value is missing and no default, crash; -%% else if value is missing and has a default, set default; -%% otherwise apply constraints. If constraint fails, crash. -filter([], Map) -> - Map; -filter([{Key, Constraints}|Tail], Map) -> - filter_constraints(Tail, Map, Key, maps:get(Key, Map), Constraints); -filter([{Key, Constraints, Default}|Tail], Map) -> +filter(Fields, Map0) -> + case filter(Fields, Map0, #{}) of + {ok, Map} -> + Map; + {error, Errors} -> + exit({validation_failed, Errors}) + end. + +%% Loop through fields, if value is missing and no default, +%% record the error; else if value is missing and has a +%% default, set default; otherwise apply constraints. If +%% constraint fails, record the error. +%% +%% When there is an error at the end, crash. +filter([], Map, Errors) -> + case maps:size(Errors) of + 0 -> {ok, Map}; + _ -> {error, Errors} + end; +filter([{Key, Constraints}|Tail], Map, Errors) -> + filter_constraints(Tail, Map, Errors, Key, maps:get(Key, Map), Constraints); +filter([{Key, Constraints, Default}|Tail], Map, Errors) -> case maps:find(Key, Map) of {ok, Value} -> - filter_constraints(Tail, Map, Key, Value, Constraints); + filter_constraints(Tail, Map, Errors, Key, Value, Constraints); error -> - filter(Tail, Map#{Key => Default}) + filter(Tail, Map#{Key => Default}, Errors) end; -filter([Key|Tail], Map) -> - true = maps:is_key(Key, Map), - filter(Tail, Map). +filter([Key|Tail], Map, Errors) -> + case maps:is_key(Key, Map) of + true -> + filter(Tail, Map, Errors); + false -> + filter(Tail, Map, Errors#{Key => required}) + end. -filter_constraints(Tail, Map, Key, Value0, Constraints) -> +filter_constraints(Tail, Map, Errors, Key, Value0, Constraints) -> case cowboy_constraints:validate(Value0, Constraints) of {ok, Value} -> - filter(Tail, Map#{Key => Value}); + filter(Tail, Map#{Key => Value}, Errors); {error, Reason} -> - exit(Reason) + filter(Tail, Map, Errors#{Key => Reason}) end. -- cgit v1.2.3