aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2017-07-23 15:30:32 +0200
committerLoïc Hoguin <[email protected]>2017-07-23 15:30:32 +0200
commitd4fb6571b38226bd9903ff9db0bce28abcad80d6 (patch)
tree9828f3989dac32ba5dc7acf8aa778a18ebc0510c
parent0556fb027c44cf80d3f77fb9c3fac4c504d6720c (diff)
downloadcowboy-d4fb6571b38226bd9903ff9db0bce28abcad80d6.tar.gz
cowboy-d4fb6571b38226bd9903ff9db0bce28abcad80d6.tar.bz2
cowboy-d4fb6571b38226bd9903ff9db0bce28abcad80d6.zip
Update the constraints chapter
-rw-r--r--doc/src/guide/constraints.asciidoc74
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.