aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_router.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/cowboy_router.erl')
-rw-r--r--src/cowboy_router.erl43
1 files changed, 34 insertions, 9 deletions
diff --git a/src/cowboy_router.erl b/src/cowboy_router.erl
index f2d1127..a4597ed 100644
--- a/src/cowboy_router.erl
+++ b/src/cowboy_router.erl
@@ -258,14 +258,13 @@ match_path([{<<"*">>, _Constraints, Handler, Opts}|_Tail], HostInfo, <<"*">>, Bi
{ok, Handler, Opts, Bindings, HostInfo, undefined};
match_path([{PathMatch, Constraints, Handler, Opts}|Tail], HostInfo, Tokens,
Bindings) when is_list(Tokens) ->
- case list_match(Tokens, PathMatch, []) of
+ case list_match(Tokens, PathMatch, Bindings) of
false ->
match_path(Tail, HostInfo, Tokens, Bindings);
{true, PathBinds, PathInfo} ->
case check_constraints(Constraints, PathBinds) of
{ok, PathBinds2} ->
- {ok, Handler, Opts, Bindings ++ PathBinds2,
- HostInfo, PathInfo};
+ {ok, Handler, Opts, PathBinds2, HostInfo, PathInfo};
nomatch ->
match_path(Tail, HostInfo, Tokens, Bindings)
end
@@ -357,9 +356,17 @@ list_match([_E|Tail], ['_'|TailMatch], Binds) ->
%% Both values match, continue.
list_match([E|Tail], [E|TailMatch], Binds) ->
list_match(Tail, TailMatch, Binds);
-%% Bind E to the variable name V and continue.
+%% Bind E to the variable name V and continue,
+%% unless V was already defined and E isn't identical to the previous value.
list_match([E|Tail], [V|TailMatch], Binds) when is_atom(V) ->
- list_match(Tail, TailMatch, [{V, E}|Binds]);
+ case lists:keyfind(V, 1, Binds) of
+ {_, E} ->
+ list_match(Tail, TailMatch, Binds);
+ {_, _} ->
+ false;
+ false ->
+ list_match(Tail, TailMatch, [{V, E}|Binds])
+ end;
%% Match complete.
list_match([], [], Binds) ->
{true, Binds, undefined};
@@ -481,10 +488,7 @@ match_test_() ->
{<<"erlang.fr">>, '_',
{ok, match_erlang_ext, [], [{ext, <<"fr">>}]}},
{<<"any">>, <<"/users/444/friends">>,
- {ok, match_users_friends, [], [{id, <<"444">>}]}},
- {<<"ninenines.fr">>, <<"/threads/987">>,
- {ok, match_duplicate_vars, [we, {expect, two}, var, here],
- [{var, <<"fr">>}, {var, <<"987">>}]}}
+ {ok, match_users_friends, [], [{id, <<"444">>}]}}
],
[{lists:flatten(io_lib:format("~p, ~p", [H, P])), fun() ->
{ok, Handler, Opts, Binds, undefined, undefined}
@@ -537,4 +541,25 @@ match_constraints_test() ->
<<"ninenines.eu">>, <<"/path/ESSEN">>),
ok.
+match_same_bindings_test() ->
+ Dispatch = [{[same, same], [], [{'_', [], match, []}]}],
+ {ok, _, [], [{same, <<"eu">>}], _, _} = match(Dispatch,
+ <<"eu.eu">>, <<"/">>),
+ {error, notfound, host} = match(Dispatch,
+ <<"ninenines.eu">>, <<"/">>),
+ Dispatch2 = [{[<<"eu">>, <<"ninenines">>, user], [],
+ [{[<<"path">>, user], [], match, []}]}],
+ {ok, _, [], [{user, <<"essen">>}], _, _} = match(Dispatch2,
+ <<"essen.ninenines.eu">>, <<"/path/essen">>),
+ {ok, _, [], [{user, <<"essen">>}], _, _} = match(Dispatch2,
+ <<"essen.ninenines.eu">>, <<"/path/essen/">>),
+ {error, notfound, path} = match(Dispatch2,
+ <<"essen.ninenines.eu">>, <<"/path/notessen">>),
+ Dispatch3 = [{'_', [], [{[same, same], [], match, []}]}],
+ {ok, _, [], [{same, <<"path">>}], _, _} = match(Dispatch3,
+ <<"ninenines.eu">>, <<"/path/path">>),
+ {error, notfound, path} = match(Dispatch3,
+ <<"ninenines.eu">>, <<"/path/to">>),
+ ok.
+
-endif.