mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 20:30:23 +00:00
Update the constraints chapter
This commit is contained in:
parent
0556fb027c
commit
d4fb6571b3
1 changed files with 53 additions and 21 deletions
|
@ -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;
|
||||
----
|
||||
|
||||
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.
|
||||
The value must be returned even if it is not converted
|
||||
by the constraint.
|
||||
|
||||
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.
|
||||
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]).
|
||||
----
|
||||
|
||||
Notice that for this case you get both the error and
|
||||
the value that was given to the constraint that produced
|
||||
this error.
|
||||
|
||||
Cowboy will not catch exceptions coming from constraint
|
||||
functions. They should be written to not emit any exceptions.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue