Loïc Hoguin 12 лет назад
Родитель
Сommit
c2c333de8a
2 измененных файлов с 15 добавлено и 3 удалено
  1. 2 1
      guide/routing.md
  2. 13 2
      src/cowboy_router.erl

+ 2 - 1
guide/routing.md

@@ -207,7 +207,7 @@ name, and the optional third element is the constraint's arguments.
 The following constraints are currently defined:
 
  *  {Name, int}
- *  {Name, function, (fun(Value) -> true | {true, NewValue} | false)}
+ *  {Name, function, fun ((Value) -> true | {true, NewValue} | false)}
 
 The `int` constraint will check if the binding is a binary string
 representing an integer, and if it is, will convert the value to integer.
@@ -215,6 +215,7 @@ representing an integer, and if it is, will convert the value to integer.
 The `function` constraint will pass the binding value to a user specified
 function that receives the binary value as its only argument and must
 return whether it fulfills the constraint, optionally modifying the value.
+The value thus returned can be of any type.
 
 Note that constraint functions SHOULD be pure and MUST NOT crash.
 

+ 13 - 2
src/cowboy_router.erl

@@ -33,7 +33,8 @@
 -export_type([bindings/0]).
 -export_type([tokens/0]).
 
--type constraints() :: [{atom(), int}].
+-type constraints() :: [{atom(), int}
+	| {atom(), function, fun ((binary()) -> true | {true, any()} | false)}].
 -export_type([constraints/0]).
 
 -type route_match() :: binary() | string().
@@ -297,7 +298,9 @@ check_constraints([Constraint|Tail], Bindings) ->
 check_constraint({_, int}, Value) ->
 	try {true, list_to_integer(binary_to_list(Value))}
 	catch _:_ -> false
-	end.
+	end;
+check_constraint({_, function, Fun}, Value) ->
+	Fun(Value).
 
 %% @doc Split a hostname into a list of tokens.
 -spec split_host(binary()) -> tokens().
@@ -524,6 +527,14 @@ match_constraints_test() ->
 		<<"ninenines.eu">>, <<"/path/123/">>),
 	{error, notfound, path} = match(Dispatch,
 		<<"ninenines.eu">>, <<"/path/NaN/">>),
+	Dispatch2 = [{'_', [],
+		[{[<<"path">>, username], [{username, function,
+		fun(Value) -> Value =:= cowboy_bstr:to_lower(Value) end}],
+		match, []}]}],
+	{ok, _, [], [{username, <<"essen">>}], _, _} = match(Dispatch2,
+		<<"ninenines.eu">>, <<"/path/essen">>),
+	{error, notfound, path} = match(Dispatch2,
+		<<"ninenines.eu">>, <<"/path/ESSEN">>),
 	ok.
 
 -endif.