约束是用来验证和转换用户输入的函数。
它们被用于Cowboy中的各个地方,包括路由器和cowboy_req匹配函数。
约束以字段列表的形式提供。对于列表中的每个字段,可以应用特定的约束,如果字段缺失,还可以应用默认值。
字段可以是一个atom的字段、一个带约束的{field, constraints}元组或一个带约束(默认值为{field, constraints, default})的元组。字段形式表示该字段为必选字段。
注意,当与路由器一起使用时,只有第二种形式才有意义,因为它不使用默认值,而且字段总是定义的。
每个字段的约束以原子或应用程序的有序列表的形式提供。内置约束是作为原子提供的,而自定义约束是作为函数提供的。
当提供了多个约束时,它们将按照给定的顺序应用。如果该值已被约束修改,那么下一个将接收新值。
例如,以下约束将首先验证并将字段my_value转换为整数,然后检查整数是否为正:
PositiveFun = fun (_, V) when V > 0 -> {ok, V}; (_, _) -> {error, not_positive} end, {my_value, [int, PositiveFun]}.
在这个代码片段中,我们忽略第一个函数参数。我们不应该。我们将在本章后面简单地学习它。
当只有一个约束时,可以直接提供,而不用将其包装到列表中:
{my_value, int}
内置约束被指定为一个atom:
约束 | 描述 |
---|---|
int | 将二进制值转换为整数 |
nonempty | 确保二进制值不为空。 |
自定义约束被指定为一个函数。这个函数有两个参数。第一个参数指示要执行的操作,第二个参数是值。该值是什么以及必须返回什么取决于操作。
Cowboy目前定义了三个操作。用于验证和转换用户输入的操作是forward操作。
int(forward, Value) -> try {ok, binary_to_integer(Value)} catch _:_ -> {error, not_an_integer} end;
即使该值没有被约束转换,也必须返回。
reverse
操作则相反:它接受一个转换后的值,并将其更改为用户输入的值。
int(reverse, Value) -> try {ok, integer_to_binary(Value)} catch _:_ -> {error, not_an_integer} end;
最后,format_error操作接受任何其他操作返回的错误,并返回格式化后的人类可读的错误消息。
int(format_error, {not_an_integer, Value}) -> io_lib:format("The value ~p is not an integer.", [Value]).
注意,在这种情况下,您得到了error和给出给产生这个error的约束的值。
Cowboy不会捕获来自约束函数的异常。它们应该被写入不产生任何异常。