aboutsummaryrefslogtreecommitdiffstats
path: root/src/cowboy_router.erl
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2016-06-06 17:35:48 +0200
committerLoïc Hoguin <[email protected]>2016-06-06 17:35:48 +0200
commitc9f5603650db717efe24dbf4d266071331f4e2f9 (patch)
tree6d5b4f54445d90fb65f1ca171d3a52bdf612c596 /src/cowboy_router.erl
parent493794145ef51a8402f0e07d5a28ea64597c9945 (diff)
downloadcowboy-c9f5603650db717efe24dbf4d266071331f4e2f9.tar.gz
cowboy-c9f5603650db717efe24dbf4d266071331f4e2f9.tar.bz2
cowboy-c9f5603650db717efe24dbf4d266071331f4e2f9.zip
Router: properly handle path segments
The path segments . and .. are now removed according to the rules found in RFC3986. The path segments are now percent-decoded using the correct algorithm (the one in RFC3986 and not the "query string" one).
Diffstat (limited to 'src/cowboy_router.erl')
-rw-r--r--src/cowboy_router.erl25
1 files changed, 23 insertions, 2 deletions
diff --git a/src/cowboy_router.erl b/src/cowboy_router.erl
index f07b307..f2f8fb4 100644
--- a/src/cowboy_router.erl
+++ b/src/cowboy_router.erl
@@ -322,9 +322,9 @@ split_path(Path, Acc) ->
try
case binary:match(Path, <<"/">>) of
nomatch when Path =:= <<>> ->
- lists:reverse([cow_qs:urldecode(S) || S <- Acc]);
+ remove_dot_segments(lists:reverse([cow_uri:urldecode(S) || S <- Acc]), []);
nomatch ->
- lists:reverse([cow_qs:urldecode(S) || S <- [Path|Acc]]);
+ remove_dot_segments(lists:reverse([cow_uri:urldecode(S) || S <- [Path|Acc]]), []);
{Pos, _} ->
<< Segment:Pos/binary, _:8, Rest/bits >> = Path,
split_path(Rest, [Segment|Acc])
@@ -334,6 +334,27 @@ split_path(Path, Acc) ->
badrequest
end.
+remove_dot_segments([], Acc) ->
+ lists:reverse(Acc);
+remove_dot_segments([<<".">>|Segments], Acc) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([<<"..">>|Segments], Acc=[]) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([<<"..">>|Segments], [_|Acc]) ->
+ remove_dot_segments(Segments, Acc);
+remove_dot_segments([S|Segments], Acc) ->
+ remove_dot_segments(Segments, [S|Acc]).
+
+-ifdef(TEST).
+remove_dot_segments_test_() ->
+ Tests = [
+ {[<<"a">>, <<"b">>, <<"c">>, <<".">>, <<"..">>, <<"..">>, <<"g">>], [<<"a">>, <<"g">>]},
+ {[<<"mid">>, <<"content=5">>, <<"..">>, <<"6">>], [<<"mid">>, <<"6">>]},
+ {[<<"..">>, <<"a">>], [<<"a">>]}
+ ],
+ [fun() -> R = remove_dot_segments(S, []) end || {S, R} <- Tests].
+-endif.
+
-spec list_match(tokens(), dispatch_match(), bindings())
-> {true, bindings(), undefined | tokens()} | false.
%% Atom '...' matches any trailing path, stop right now.