0
Fork 0
mirror of https://github.com/ninenines/cowboy.git synced 2025-07-14 20:30:23 +00:00

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).
This commit is contained in:
Loïc Hoguin 2016-06-06 17:35:48 +02:00
parent 493794145e
commit c9f5603650

View file

@ -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.