diff options
Diffstat (limited to 'src/cowboy_dispatcher.erl')
-rw-r--r-- | src/cowboy_dispatcher.erl | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/src/cowboy_dispatcher.erl b/src/cowboy_dispatcher.erl index cfb8fb6..fae18fc 100644 --- a/src/cowboy_dispatcher.erl +++ b/src/cowboy_dispatcher.erl @@ -21,7 +21,7 @@ -type bindings() :: [{atom(), binary()}]. -type tokens() :: [binary()]. --type match_rule() :: '_' | '*' | [binary() | '_' | '...' | atom()]. +-type match_rule() :: '_' | <<_:8>> | [binary() | '_' | '...' | atom()]. -type dispatch_path() :: [{match_rule(), module(), any()}]. -type dispatch_rule() :: {Host::match_rule(), Path::dispatch_path()}. -type dispatch_rules() :: [dispatch_rule()]. @@ -45,9 +45,10 @@ %% <em>PathRules</em> being a list of <em>{Path, HandlerMod, HandlerOpts}</em>. %% %% <em>Hostname</em> and <em>Path</em> are match rules and can be either the -%% atom <em>'_'</em>, which matches everything for a single token, the atom -%% <em>'*'</em>, which matches everything for the rest of the tokens, or a -%% list of tokens. Each token can be either a binary, the atom <em>'_'</em>, +%% atom <em>'_'</em>, which matches everything, <<"*">>, which match the +%% wildcard path, or a list of tokens. +%% +%% Each token can be either a binary, the atom <em>'_'</em>, %% the atom '...' or a named atom. A binary token must match exactly, %% <em>'_'</em> matches everything for a single token, <em>'...'</em> matches %% everything for the rest of the tokens and a named atom will bind the @@ -67,7 +68,8 @@ -> {ok, module(), any(), bindings(), HostInfo::undefined | tokens(), PathInfo::undefined | tokens()} - | {error, notfound, host} | {error, notfound, path}. + | {error, notfound, host} | {error, notfound, path} + | {error, badrequest, path}. match([], _, _) -> {error, notfound, host}; match([{'_', PathMatchs}|_Tail], _, Path) -> @@ -91,12 +93,12 @@ match(Dispatch, Host, Path) -> -> {ok, module(), any(), bindings(), HostInfo::undefined | tokens(), PathInfo::undefined | tokens()} - | {error, notfound, path}. + | {error, notfound, path} | {error, badrequest, path}. match_path([], _, _, _) -> {error, notfound, path}; match_path([{'_', Handler, Opts}|_Tail], HostInfo, _, Bindings) -> {ok, Handler, Opts, Bindings, HostInfo, undefined}; -match_path([{'*', Handler, Opts}|_Tail], HostInfo, '*', Bindings) -> +match_path([{<<"*">>, Handler, Opts}|_Tail], HostInfo, <<"*">>, Bindings) -> {ok, Handler, Opts, Bindings, HostInfo, undefined}; match_path([{PathMatch, Handler, Opts}|Tail], HostInfo, Tokens, Bindings) when is_list(Tokens) -> @@ -106,6 +108,8 @@ match_path([{PathMatch, Handler, Opts}|Tail], HostInfo, Tokens, {true, PathBinds, PathInfo} -> {ok, Handler, Opts, Bindings ++ PathBinds, HostInfo, PathInfo} end; +match_path(_Dispatch, _HostInfo, badrequest, _Bindings) -> + {error, badrequest, path}; match_path(Dispatch, HostInfo, Path, Bindings) -> match_path(Dispatch, HostInfo, split_path(Path), Bindings). @@ -138,14 +142,19 @@ split_path(<< $/, Path/bits >>) -> split_path(Path, []). split_path(Path, Acc) -> - case binary:match(Path, <<"/">>) of - nomatch when Path =:= <<>> -> - lists:reverse([cowboy_http:urldecode(S) || S <- Acc]); - nomatch -> - lists:reverse([cowboy_http:urldecode(S) || S <- [Path|Acc]]); - {Pos, _} -> - << Segment:Pos/binary, _:8, Rest/bits >> = Path, - split_path(Rest, [Segment|Acc]) + try + case binary:match(Path, <<"/">>) of + nomatch when Path =:= <<>> -> + lists:reverse([cowboy_http:urldecode(S) || S <- Acc]); + nomatch -> + lists:reverse([cowboy_http:urldecode(S) || S <- [Path|Acc]]); + {Pos, _} -> + << Segment:Pos/binary, _:8, Rest/bits >> = Path, + split_path(Rest, [Segment|Acc]) + end + catch + error:badarg -> + badrequest end. -spec list_match(tokens(), match_rule(), bindings()) |