mirror of
https://github.com/ninenines/cowboy.git
synced 2025-07-14 12:20:24 +00:00
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 / ":" / "@" ```
This commit is contained in:
parent
7cb3a9dbda
commit
82cd22a88b
2 changed files with 16 additions and 5 deletions
|
@ -101,12 +101,11 @@ compile_rules(<< S, Rest/bits >>, S, Segments, Rules, <<>>) ->
|
||||||
compile_rules(Rest, S, Segments, Rules, <<>>);
|
compile_rules(Rest, S, Segments, Rules, <<>>);
|
||||||
compile_rules(<< S, Rest/bits >>, S, Segments, Rules, Acc) ->
|
compile_rules(<< S, Rest/bits >>, S, Segments, Rules, Acc) ->
|
||||||
compile_rules(Rest, S, [Acc|Segments], Rules, <<>>);
|
compile_rules(Rest, S, [Acc|Segments], Rules, <<>>);
|
||||||
|
%% Colon on path segment start is special, otherwise allow.
|
||||||
compile_rules(<< $:, Rest/bits >>, S, Segments, Rules, <<>>) ->
|
compile_rules(<< $:, Rest/bits >>, S, Segments, Rules, <<>>) ->
|
||||||
{NameBin, Rest2} = compile_binding(Rest, S, <<>>),
|
{NameBin, Rest2} = compile_binding(Rest, S, <<>>),
|
||||||
Name = binary_to_atom(NameBin, utf8),
|
Name = binary_to_atom(NameBin, utf8),
|
||||||
compile_rules(Rest2, S, Segments, Rules, Name);
|
compile_rules(Rest2, S, Segments, Rules, Name);
|
||||||
compile_rules(<< $:, _/bits >>, _, _, _, _) ->
|
|
||||||
error(badarg);
|
|
||||||
compile_rules(<< $[, $., $., $., $], Rest/bits >>, S, Segments, Rules, Acc)
|
compile_rules(<< $[, $., $., $., $], Rest/bits >>, S, Segments, Rules, Acc)
|
||||||
when Acc =:= <<>> ->
|
when Acc =:= <<>> ->
|
||||||
compile_rules(Rest, S, ['...'|Segments], Rules, Acc);
|
compile_rules(Rest, S, ['...'|Segments], Rules, Acc);
|
||||||
|
|
|
@ -35,12 +35,13 @@ all() ->
|
||||||
{group, http_compress},
|
{group, http_compress},
|
||||||
{group, https_compress},
|
{group, https_compress},
|
||||||
{group, parse_host},
|
{group, parse_host},
|
||||||
{group, set_env}
|
{group, set_env},
|
||||||
|
{group, router_compile}
|
||||||
].
|
].
|
||||||
|
|
||||||
groups() ->
|
groups() ->
|
||||||
Tests = ct_helper:all(?MODULE) -- [
|
Tests = ct_helper:all(?MODULE) -- [
|
||||||
parse_host, set_env_dispatch
|
parse_host, set_env_dispatch, path_allow_colon
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
{http, [], Tests}, %% @todo parallel
|
{http, [], Tests}, %% @todo parallel
|
||||||
|
@ -52,6 +53,9 @@ groups() ->
|
||||||
]},
|
]},
|
||||||
{set_env, [], [
|
{set_env, [], [
|
||||||
set_env_dispatch
|
set_env_dispatch
|
||||||
|
]},
|
||||||
|
{router_compile, [], [
|
||||||
|
path_allow_colon
|
||||||
]}
|
]}
|
||||||
].
|
].
|
||||||
|
|
||||||
|
@ -85,8 +89,12 @@ init_per_group(set_env, Config) ->
|
||||||
env => #{dispatch => []}
|
env => #{dispatch => []}
|
||||||
}),
|
}),
|
||||||
Port = ranch:get_port(set_env),
|
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, _) ->
|
end_per_group(Name, _) ->
|
||||||
ok = cowboy:stop_listener(Name).
|
ok = cowboy:stop_listener(Name).
|
||||||
|
|
||||||
|
@ -588,6 +596,10 @@ set_env_dispatch(Config) ->
|
||||||
{response, nofin, 200, _} = gun:await(ConnPid2, Ref2),
|
{response, nofin, 200, _} = gun:await(ConnPid2, Ref2),
|
||||||
ok.
|
ok.
|
||||||
|
|
||||||
|
path_allow_colon(_Config) ->
|
||||||
|
cowboy_router:compile([{'_', [{"/foo/bar:blah", http_handler, []}]}]),
|
||||||
|
ok.
|
||||||
|
|
||||||
set_resp_body(Config) ->
|
set_resp_body(Config) ->
|
||||||
ConnPid = gun_open(Config),
|
ConnPid = gun_open(Config),
|
||||||
Ref = gun:get(ConnPid, "/set_resp/body"),
|
Ref = gun:get(ConnPid, "/set_resp/body"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue