Browse Source

Add support for the '*' path.

Mostly used by the following request: OPTIONS * HTTP/1.1
Loïc Hoguin 14 years ago
parent
commit
a4f8bb6573
3 changed files with 13 additions and 4 deletions
  1. 2 2
      include/types.hrl
  2. 6 2
      src/cowboy_dispatcher.erl
  3. 5 0
      src/cowboy_http_protocol.erl

+ 2 - 2
include/types.hrl

@@ -25,8 +25,8 @@
 -type port_number() :: 0..65535.
 
 -type bindings() :: list({Key::atom(), Value::string()}).
--type path_tokens() :: list(string()).
--type match() :: '_' | list(string() | '_' | atom()).
+-type path_tokens() :: '*' | list(string()).
+-type match() :: '_' | '*' | list(string() | '_' | atom()).
 
 -type dispatch_rules() :: {Host::match(), list({Path::match(),
 	Handler::module(), Opts::term()})}.

+ 6 - 2
src/cowboy_dispatcher.erl

@@ -25,6 +25,8 @@ split_host(Host) ->
 	string:tokens(Host, ".").
 
 -spec split_path(Path::string()) -> {Tokens::path_tokens(), Qs::string()}.
+split_path('*') ->
+	{'*', []};
 split_path(Path) ->
 	case string:chr(Path, $?) of
 		0 ->
@@ -57,6 +59,8 @@ match_path(_Path, [], _HostBinds) ->
 	{error, notfound, path};
 match_path(_Path, [{'_', Handler, Opts}|_Tail], HostBinds) ->
 	{ok, Handler, Opts, HostBinds};
+match_path('*', [{'*', Handler, Opts}|_Tail], HostBinds) ->
+	{ok, Handler, Opts, HostBinds};
 match_path(Path, [{PathMatch, Handler, Opts}|Tail], HostBinds) ->
 	case try_match(path, Path, PathMatch) of
 		false ->
@@ -120,7 +124,6 @@ split_path_test_() ->
 	Tests = [
 		{"?", [], []},
 		{"???", [], "??"},
-		{"*", ["*"], []},
 		{"/", [], []},
 		{"/users", ["users"], []},
 		{"/users?", ["users"], []},
@@ -128,7 +131,8 @@ split_path_test_() ->
 		{"/users/42/friends?a=b&c=d&e=notsure?whatever",
 			["users", "42", "friends"], "a=b&c=d&e=notsure?whatever"}
 	],
-	[{P, fun() -> {R, Qs} = split_path(P) end} || {P, R, Qs} <- Tests].
+	[{"atom '*'", fun() -> {'*', []} = split_path('*') end}]
+		++ [{P, fun() -> {R, Qs} = split_path(P) end} || {P, R, Qs} <- Tests].
 
 match_test_() ->
 	Dispatch = [

+ 5 - 0
src/cowboy_http_protocol.erl

@@ -68,6 +68,11 @@ request({http_request, Method, {abs_path, AbsPath}, Version},
 	{ok, Peer} = Transport:peername(Socket),
 	wait_header(#http_req{socket=Socket, transport=Transport, method=Method,
 		version=Version, peer=Peer, path=Path, raw_qs=Qs}, State);
+request({http_request, Method, '*', Version},
+		State=#state{socket=Socket, transport=Transport}) ->
+	{ok, Peer} = Transport:peername(Socket),
+	wait_header(#http_req{socket=Socket, transport=Transport, method=Method,
+		version=Version, peer=Peer, path='*', raw_qs=[]}, State);
 request({http_request, _Method, _URI, _Version}, State) ->
 	error_terminate(501, State);
 request({http_error, "\r\n"}, State) ->