aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Fisher <[email protected]>2015-12-22 12:19:28 -0600
committerLoïc Hoguin <[email protected]>2018-01-16 11:24:49 +0100
commit82cd22a88b3f87064d9f17e36652b104b709a679 (patch)
treeb5213d9ce5120381cd3d2179ff12bc24622fe9be
parent7cb3a9dbda1c836057e439ed28ebda9799453b34 (diff)
downloadcowboy-82cd22a88b3f87064d9f17e36652b104b709a679.tar.gz
cowboy-82cd22a88b3f87064d9f17e36652b104b709a679.tar.bz2
cowboy-82cd22a88b3f87064d9f17e36652b104b709a679.zip
Allow colon within path segments
Allow `cowboy_router:compile` to handle colon characters within path segments, rather than exiting with `badarg`. This is allowed via RFC 7230 2.7 -> [RFC 3986 3.3](https://tools.ietf.org/html/rfc3986#section-3.3): ``` segment = *pchar segment-nz = 1*pchar segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) ; non-zero-length segment without any colon ":" pchar = unreserved / pct-encoded / sub-delims / ":" / "@" ```
-rw-r--r--src/cowboy_router.erl3
-rw-r--r--test/http_SUITE.erl18
2 files changed, 16 insertions, 5 deletions
diff --git a/src/cowboy_router.erl b/src/cowboy_router.erl
index fb5c383..92ecf25 100644
--- a/src/cowboy_router.erl
+++ b/src/cowboy_router.erl
@@ -101,12 +101,11 @@ compile_rules(<< S, Rest/bits >>, S, Segments, Rules, <<>>) ->
compile_rules(Rest, S, Segments, Rules, <<>>);
compile_rules(<< S, Rest/bits >>, S, Segments, Rules, Acc) ->
compile_rules(Rest, S, [Acc|Segments], Rules, <<>>);
+%% Colon on path segment start is special, otherwise allow.
compile_rules(<< $:, Rest/bits >>, S, Segments, Rules, <<>>) ->
{NameBin, Rest2} = compile_binding(Rest, S, <<>>),
Name = binary_to_atom(NameBin, utf8),
compile_rules(Rest2, S, Segments, Rules, Name);
-compile_rules(<< $:, _/bits >>, _, _, _, _) ->
- error(badarg);
compile_rules(<< $[, $., $., $., $], Rest/bits >>, S, Segments, Rules, Acc)
when Acc =:= <<>> ->
compile_rules(Rest, S, ['...'|Segments], Rules, Acc);
diff --git a/test/http_SUITE.erl b/test/http_SUITE.erl
index 52ef86b..d77b760 100644
--- a/test/http_SUITE.erl
+++ b/test/http_SUITE.erl
@@ -35,12 +35,13 @@ all() ->
{group, http_compress},
{group, https_compress},
{group, parse_host},
- {group, set_env}
+ {group, set_env},
+ {group, router_compile}
].
groups() ->
Tests = ct_helper:all(?MODULE) -- [
- parse_host, set_env_dispatch
+ parse_host, set_env_dispatch, path_allow_colon
],
[
{http, [], Tests}, %% @todo parallel
@@ -52,6 +53,9 @@ groups() ->
]},
{set_env, [], [
set_env_dispatch
+ ]},
+ {router_compile, [], [
+ path_allow_colon
]}
].
@@ -85,8 +89,12 @@ init_per_group(set_env, Config) ->
env => #{dispatch => []}
}),
Port = ranch:get_port(set_env),
- [{type, tcp}, {protocol, http}, {port, Port}, {opts, []}|Config].
+ [{type, tcp}, {protocol, http}, {port, Port}, {opts, []}|Config];
+init_per_group(router_compile, Config) ->
+ Config.
+end_per_group(router_compile, _) ->
+ ok;
end_per_group(Name, _) ->
ok = cowboy:stop_listener(Name).
@@ -588,6 +596,10 @@ set_env_dispatch(Config) ->
{response, nofin, 200, _} = gun:await(ConnPid2, Ref2),
ok.
+path_allow_colon(_Config) ->
+ cowboy_router:compile([{'_', [{"/foo/bar:blah", http_handler, []}]}]),
+ ok.
+
set_resp_body(Config) ->
ConnPid = gun_open(Config),
Ref = gun:get(ConnPid, "/set_resp/body"),