diff options
Diffstat (limited to 'doc/src/guide/constraints.asciidoc')
| -rw-r--r-- | doc/src/guide/constraints.asciidoc | 74 | 
1 files changed, 53 insertions, 21 deletions
| diff --git a/doc/src/guide/constraints.asciidoc b/doc/src/guide/constraints.asciidoc index 7721831..6cc1075 100644 --- a/doc/src/guide/constraints.asciidoc +++ b/doc/src/guide/constraints.asciidoc @@ -5,7 +5,7 @@ Constraints are validation and conversion functions applied  to user input.  They are used in various places in Cowboy, including the -router and the request match functions. +router and the `cowboy_req` match functions.  === Syntax @@ -36,10 +36,18 @@ check that the integer is positive:  [source,erlang]  ---- -PositiveFun = fun(V) when V > 0 -> true; (_) -> false end, +PositiveFun = fun +    (_, V) when V > 0 -> +        {ok, V}; +    (_, _) -> +        {error, not_positive} +end,  {my_value, [int, PositiveFun]}.  ---- +We ignore the first fun argument in this snippet. We shouldn't. +We will simply learn what it is later in this chapter. +  When there's only one constraint, it can be provided directly  without wrapping it into a list: @@ -62,30 +70,54 @@ Built-in constraints are specified as an atom:  === Custom constraints  Custom constraints are specified as a fun. This fun takes -a single argument and must return one of `true`, `{true, NewValue}` -or `false`. +two arguments. The first argument indicates the operation +to be performed, and the second is the value. What the +value is and what must be returned depends on the operation. -`true` indicates the input is valid, `false` otherwise. -The `{true, NewValue}` tuple is returned when the input -is valid and the value has been converted. For example, -the following constraint will convert the binary input -to an integer: +Cowboy currently defines three operations. The operation +used for validating and converting user input is the `forward` +operation.  [source,erlang]  ---- -fun (Value0) when is_binary(Value0) -> -    try binary_to_integer(Value0) of -        Value -> {true, Value} +int(forward, Value) -> +    try +        {ok, binary_to_integer(Value)}      catch _:_ -> -        false -    end. +        {error, not_an_integer} +    end; +---- + +The value must be returned even if it is not converted +by the constraint. + +The `reverse` operation does the opposite: it +takes a converted value and changes it back to what the +user input would have been. + +[source,erlang] +---- +int(reverse, Value) -> +	try +		{ok, integer_to_binary(Value)} +	catch _:_ -> +		{error, not_an_integer} +	end; +---- + +Finally, the `format_error` operation takes an error +returned by any other operation and returns a formatted +human-readable error message. + +[source,erlang] +---- +int(format_error, {not_an_integer, Value}) -> +	io_lib:format("The value ~p is not an integer.", [Value]).  ---- -Constraint functions should only crash because the programmer -made an error when chaining constraints incorrectly (for example -if the constraints were `[int, int]`, and not because of input. -If the input is invalid then `false` must be returned. +Notice that for this case you get both the error and +the value that was given to the constraint that produced +this error. -In our snippet, the `is_binary/1` guard will crash only -because of a programmer error, and the try block is there -to ensure that we do not crash when the input is invalid. +Cowboy will not catch exceptions coming from constraint +functions. They should be written to not emit any exceptions. | 
