From e5e65bcff157146dfc7465732c91746bf6cea04d Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Thu, 26 Dec 2019 15:11:32 +0300 Subject: [PATCH 1/4] Introduce rebar_uri Attempts to bridge http_uri (deprecated in OTP 23) and uri_string (available as of OTP 21+). (cherry picked from commit 7057cbe281296707771ee3a017406f993f24c77d) --- src/rebar_git_resource.erl | 4 ++-- src/rebar_uri.erl | 44 ++++++++++++++++++++++++++++++++++++++ src/rebar_utils.erl | 33 +++++++++++++++++++++------- test/rebar_utils_SUITE.erl | 16 +++++++++++--- 4 files changed, 84 insertions(+), 13 deletions(-) create mode 100644 src/rebar_uri.erl diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl index 63a0ad41..808f1f8f 100644 --- a/src/rebar_git_resource.erl +++ b/src/rebar_git_resource.erl @@ -117,8 +117,8 @@ parse_git_url(Url) -> end. parse_git_url(not_scp, Url) -> UriOpts = [{scheme_defaults, [{git, 9418} | http_uri:scheme_defaults()]}], - case http_uri:parse(Url, UriOpts) of - {ok, {_Scheme, _User, Host, _Port, Path, _Query}} -> + case rebar_uri:parse(Url, UriOpts) of + #{path := Path, host := Host} -> {ok, {Host, filename:rootname(Path, ".git")}}; {error, Reason} -> {error, Reason} diff --git a/src/rebar_uri.erl b/src/rebar_uri.erl new file mode 100644 index 00000000..6e28a90d --- /dev/null +++ b/src/rebar_uri.erl @@ -0,0 +1,44 @@ +%%% @doc multi-OTP version compatibility shim for working with URIs +-module(rebar_uri). + +-ifdef (OTP_RELEASE). +-export([parse/1]). + +-spec parse(URIString) -> URIMap when + URIString :: uri_string:uri_string(), + URIMap :: uri_string:uri_map() | uri_string:error(). + +parse(URIString) -> + uri_string:parse(URIString). +-else. +-export([parse/1]). + +-spec parse(URIString) -> URIMap when + URIString :: iodata(), + URIMap :: map() | {error, atom(), term()}. + +parse(URIString) -> + case http_uri:parse(URIString) of + {error, Reason} -> + %% no additional parser/term info available to us, + %% e.g. see what uri_string returns in + %% uri_string:parse(<<"h$ttp:::://////lolz">>). + {error, Reason, ""}; + {ok, {Scheme, UserInfo, Host, Port, Path, Query}} -> + #{ + scheme => Scheme, + host => Host, + port => Port, + path => Path, + %% http_uri:parse/1 includes the leading question mark + %% in query string but uri_string:parse/1 leaves it out. + %% string:slice/2 isn't available in OTP <= 19. + query => case Query of + [] -> ""; + _ -> string:substr(Query, 2) + end, + userinfo => UserInfo + } + end. +-endif. + diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index bf1bba56..f72a2dc1 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -910,8 +910,7 @@ get_http_vars(Scheme) -> -ifdef (OTP_RELEASE). -if(?OTP_RELEASE >= 23). - -compile({nowarn_deprecated_function, [{http_uri, parse, 1}, - {http_uri, decode, 1}]}). + -compile({nowarn_deprecated_function, [{http_uri, decode, 1}]}). -endif. -endif. @@ -924,7 +923,10 @@ set_httpc_options(_, []) -> set_httpc_options(Scheme, Proxy) -> URI = normalise_proxy(Scheme, Proxy), - {ok, {_, UserInfo, Host, Port, _, _}} = http_uri:parse(URI), + Parts = rebar_uri:parse(URI), + Host = maps:get(host, Parts, []), + Port = maps:get(port, Parts, []), + UserInfo = maps:get(userinfo, Parts, []), httpc:set_options([{Scheme, {{Host, Port}, []}}], rebar), set_proxy_auth(UserInfo). @@ -935,14 +937,30 @@ normalise_proxy(Scheme, URI) -> _ -> URI end. +%% OTP 21+ +-ifdef (OTP_RELEASE). url_append_path(Url, ExtraPath) -> - case http_uri:parse(Url) of - {ok, {Scheme, UserInfo, Host, Port, Path, Query}} -> + case rebar_uri:parse(Url) of + #{path := Path} = Map -> + FullPath = filename:join(Path, ExtraPath), + {ok, uri_string:recompose(maps:update(path, FullPath, Map))}; + _ -> + error + end. +-else. +url_append_path(Url, ExtraPath) -> + case rebar_uri:parse(Url) of + #{scheme := Scheme, userinfo := UserInfo, host := Host, port := Port, path := Path, query := Query} -> + PrefixedQuery = case Query of + [] -> []; + Other -> lists:append(["?", Other]) + end, {ok, lists:append([atom_to_list(Scheme), "://", UserInfo, Host, ":", integer_to_list(Port), - filename:join(Path, ExtraPath), Query])}; + filename:join(Path, ExtraPath), PrefixedQuery])}; _ -> error end. +-endif. %% escape\ as\ a\ shell\? escape_chars(Str) when is_atom(Str) -> @@ -1028,8 +1046,7 @@ ssl_opts(Url) -> ssl_opts(ssl_verify_enabled, Url) -> case check_ssl_version() of true -> - {ok, {_, _, Hostname, _, _, _}} = - http_uri:parse(rebar_utils:to_list(Url)), + #{host := Hostname} = rebar_uri:parse(rebar_utils:to_list(Url)), VerifyFun = {fun ssl_verify_hostname:verify_fun/3, [{check_hostname, Hostname}]}, CACerts = certifi:cacerts(), diff --git a/test/rebar_utils_SUITE.erl b/test/rebar_utils_SUITE.erl index 4901f40c..3b111f15 100644 --- a/test/rebar_utils_SUITE.erl +++ b/test/rebar_utils_SUITE.erl @@ -322,6 +322,16 @@ is_list_of_strings(_Config) -> ?assert(rebar_utils:is_list_of_strings("foo") == false). url_append_path(_Config) -> - ?assertEqual({ok, "https://repo.hex.pm:443/repos/org"}, rebar_utils:url_append_path("https://repo.hex.pm", "/repos/org")), - ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, rebar_utils:url_append_path("https://repo.hex.pm", - "/repos/org?foo=bar")). + %% OTP version differences + {ok, Val1} = rebar_utils:url_append_path("https://repo.hex.pm", "/repos/org"), + ?assert(lists:member(Val1, [ + "https://repo.hex.pm/repos/org", + "https://repo.hex.pm:443/repos/org" + ])), + {ok, Val2} = rebar_utils:url_append_path("https://repo.hex.pm?foo=bar", "/repos/org"), + ?assert(lists:member(Val2, [ + "https://repo.hex.pm/repos/org?foo=bar", + "https://repo.hex.pm:443/repos/org?foo=bar" + ])), + ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, + rebar_utils:url_append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")). From fc04612ad6b9b7a6fc85aade91d587cacf8a3bb4 Mon Sep 17 00:00:00 2001 From: Michael Klishin Date: Fri, 27 Dec 2019 11:49:27 +0300 Subject: [PATCH 2/4] Continue transitioning away from http_uri (cherry picked from commit fa577bc46e289b5e1a739df7bd3bf08451579552) --- src/rebar_hex_repos.erl | 4 ++-- src/rebar_uri.erl | 37 +++++++++++++++++++++++++---- src/rebar_utils.erl | 28 ++-------------------- test/rebar_uri_SUITE.erl | 48 ++++++++++++++++++++++++++++++++++++++ test/rebar_utils_SUITE.erl | 20 ++-------------- 5 files changed, 86 insertions(+), 51 deletions(-) create mode 100644 test/rebar_uri_SUITE.erl diff --git a/src/rebar_hex_repos.erl b/src/rebar_hex_repos.erl index 3377d907..7b1aa908 100644 --- a/src/rebar_hex_repos.erl +++ b/src/rebar_hex_repos.erl @@ -96,8 +96,8 @@ update_organizations(Repos) -> {ok, Parent} = get_repo_config(ParentName, Repos), ParentRepoUrl = rebar_utils:to_list(maps:get(repo_url, Parent)), {ok, _RepoUrl} = - rebar_utils:url_append_path(ParentRepoUrl, - filename:join("repos", rebar_utils:to_list(RepoName))), + rebar_uri:append_path(ParentRepoUrl, + filename:join("repos", rebar_utils:to_list(RepoName))), %% still let the organization config override this constructed repo url maps:merge(Parent#{repo_url => rebar_utils:to_binary(ParentRepoUrl)}, Repo); (Repo) -> diff --git a/src/rebar_uri.erl b/src/rebar_uri.erl index 6e28a90d..3a6382b1 100644 --- a/src/rebar_uri.erl +++ b/src/rebar_uri.erl @@ -1,9 +1,14 @@ %%% @doc multi-OTP version compatibility shim for working with URIs -module(rebar_uri). --ifdef (OTP_RELEASE). --export([parse/1]). +-export([ + parse/1, + append_path/2 +]). + +-import(rebar_utils, [to_list/1]). +-ifdef (OTP_RELEASE). -spec parse(URIString) -> URIMap when URIString :: uri_string:uri_string(), URIMap :: uri_string:uri_map() | uri_string:error(). @@ -11,8 +16,6 @@ parse(URIString) -> uri_string:parse(URIString). -else. --export([parse/1]). - -spec parse(URIString) -> URIMap when URIString :: iodata(), URIMap :: map() | {error, atom(), term()}. @@ -26,7 +29,7 @@ parse(URIString) -> {error, Reason, ""}; {ok, {Scheme, UserInfo, Host, Port, Path, Query}} -> #{ - scheme => Scheme, + scheme => rebar_utils:to_list(Scheme), host => Host, port => Port, path => Path, @@ -42,3 +45,27 @@ parse(URIString) -> end. -endif. +%% OTP 21+ +-ifdef (OTP_RELEASE). +append_path(Url, ExtraPath) -> + case parse(Url) of + #{path := Path} = Map -> + FullPath = filename:join(Path, ExtraPath), + {ok, uri_string:recompose(maps:update(path, FullPath, Map))}; + _ -> + error + end. +-else. +append_path(Url, ExtraPath) -> + case parse(Url) of + #{scheme := Scheme, userinfo := UserInfo, host := Host, port := Port, path := Path, query := Query} -> + PrefixedQuery = case Query of + [] -> []; + Other -> lists:append(["?", Other]) + end, + {ok, lists:append([to_list(Scheme), "://", UserInfo, Host, ":", to_list(Port), + filename:join(Path, ExtraPath), PrefixedQuery])}; + _ -> + error + end. +-endif. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index f72a2dc1..6be50f14 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -64,7 +64,6 @@ tup_find/2, line_count/1, set_httpc_options/0, - url_append_path/2, escape_chars/1, escape_double_quotes/1, escape_double_quotes_weak/1, @@ -266,6 +265,8 @@ to_binary(A) when is_atom(A) -> atom_to_binary(A, unicode); to_binary(Str) -> unicode:characters_to_binary(Str). to_list(A) when is_atom(A) -> atom_to_list(A); +to_list(B) when is_binary(B) -> unicode:characters_to_list(B); +to_list(I) when is_integer(I) -> integer_to_list(I); to_list(Str) -> unicode:characters_to_list(Str). tup_dedup(List) -> @@ -937,31 +938,6 @@ normalise_proxy(Scheme, URI) -> _ -> URI end. -%% OTP 21+ --ifdef (OTP_RELEASE). -url_append_path(Url, ExtraPath) -> - case rebar_uri:parse(Url) of - #{path := Path} = Map -> - FullPath = filename:join(Path, ExtraPath), - {ok, uri_string:recompose(maps:update(path, FullPath, Map))}; - _ -> - error - end. --else. -url_append_path(Url, ExtraPath) -> - case rebar_uri:parse(Url) of - #{scheme := Scheme, userinfo := UserInfo, host := Host, port := Port, path := Path, query := Query} -> - PrefixedQuery = case Query of - [] -> []; - Other -> lists:append(["?", Other]) - end, - {ok, lists:append([atom_to_list(Scheme), "://", UserInfo, Host, ":", integer_to_list(Port), - filename:join(Path, ExtraPath), PrefixedQuery])}; - _ -> - error - end. --endif. - %% escape\ as\ a\ shell\? escape_chars(Str) when is_atom(Str) -> escape_chars(atom_to_list(Str)); diff --git a/test/rebar_uri_SUITE.erl b/test/rebar_uri_SUITE.erl new file mode 100644 index 00000000..4db93690 --- /dev/null +++ b/test/rebar_uri_SUITE.erl @@ -0,0 +1,48 @@ +-module(rebar_uri_SUITE). + +-export([all/0, + parse/1, + append_path/1]). + +-include_lib("common_test/include/ct.hrl"). +-include_lib("eunit/include/eunit.hrl"). +-include_lib("kernel/include/file.hrl"). + +all() -> + [parse]. + +parse(_Config) -> + #{scheme := Scheme, host := Host, path := Path} = rebar_uri:parse("https://repo.hex.pm"), + ?assertEqual("https", Scheme), + ?assertEqual("repo.hex.pm", Host), + ?assert(lists:member(Path, ["", "/"])), + + #{scheme := Scheme2, host := Host2, port := Port2, path := Path2, query := Query2} = + rebar_uri:parse("https://repo.hex.pm:443?foo=bar"), + ?assertEqual("https", Scheme2), + ?assertEqual("repo.hex.pm", Host2), + ?assertEqual(443, Port2), + ?assert(lists:member(Path2, ["", "/"])), + ?assertEqual("foo=bar", Query2), + + #{scheme := Scheme3, host := Host3, path := Path3, query := Query3} = + rebar_uri:parse("https://repo.hex.pm/over/here?foo=bar"), + ?assertEqual("https", Scheme3), + ?assertEqual("repo.hex.pm", Host3), + ?assertEqual("/over/here", Path3), + ?assertEqual("foo=bar", Query3). + +append_path(_Config) -> + %% OTP version differences + {ok, Val1} = rebar_utils:append_path("https://repo.hex.pm", "/repos/org"), + ?assert(lists:member(Val1, [ + "https://repo.hex.pm/repos/org", + "https://repo.hex.pm:443/repos/org" + ])), + {ok, Val2} = rebar_utils:append_path("https://repo.hex.pm?foo=bar", "/repos/org"), + ?assert(lists:member(Val2, [ + "https://repo.hex.pm/repos/org?foo=bar", + "https://repo.hex.pm:443/repos/org?foo=bar" + ])), + ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, + rebar_utils:append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")). diff --git a/test/rebar_utils_SUITE.erl b/test/rebar_utils_SUITE.erl index 3b111f15..233fcff3 100644 --- a/test/rebar_utils_SUITE.erl +++ b/test/rebar_utils_SUITE.erl @@ -33,8 +33,7 @@ sh_does_not_miss_messages/1, tup_merge/1, proxy_auth/1, - is_list_of_strings/1, - url_append_path/1]). + is_list_of_strings/1]). -include_lib("common_test/include/ct.hrl"). -include_lib("eunit/include/eunit.hrl"). @@ -50,7 +49,7 @@ all() -> [{group, args_to_tasks}, sh_does_not_miss_messages, tup_merge, - proxy_auth, is_list_of_strings, url_append_path]. + proxy_auth, is_list_of_strings]. groups() -> [{args_to_tasks, [], [empty_arglist, @@ -320,18 +319,3 @@ is_list_of_strings(_Config) -> ?assert(rebar_utils:is_list_of_strings([])), ?assert(rebar_utils:is_list_of_strings("")), ?assert(rebar_utils:is_list_of_strings("foo") == false). - -url_append_path(_Config) -> - %% OTP version differences - {ok, Val1} = rebar_utils:url_append_path("https://repo.hex.pm", "/repos/org"), - ?assert(lists:member(Val1, [ - "https://repo.hex.pm/repos/org", - "https://repo.hex.pm:443/repos/org" - ])), - {ok, Val2} = rebar_utils:url_append_path("https://repo.hex.pm?foo=bar", "/repos/org"), - ?assert(lists:member(Val2, [ - "https://repo.hex.pm/repos/org?foo=bar", - "https://repo.hex.pm:443/repos/org?foo=bar" - ])), - ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, - rebar_utils:url_append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")). From 5625faf4003df9894cecc1b4d0079268b8a15d1c Mon Sep 17 00:00:00 2001 From: Fred Hebert Date: Thu, 27 Feb 2020 17:04:58 -0500 Subject: [PATCH 4/4] Fix previous OTP-23 compat patches - Normalize path behaviour to always be "/" across versions - Normalize port visibility behaviour to match input string when appending - restore rebar_utils function to avoid breaking random plugins that peek into our libs for their stuff - Support URIOpts equivalent and protocol-based overrides; the behaviour there is not necessarily consistent across versions in terms of what ports are returned (http_uri always returned a port but uri_string only returns it if explicitly specified -- we choose the latter behaviour on newer releases), but the calls work to ensure URI parsing consistently works across versions The latter judgement call is a bit of an odd one; for consistency we could always mandate ports, but this would come at a performance penalty when appending URL paths (i.e. when fetching packages). The reason for this is that we standardize on the new uri_string behaviour for path appending (if the port wasn't specified, we don't add it), and with the http_uri rules, we need to do a kind of parsing round that checks if the port was included or not to make it equivalent. This is costly, and _not_ returning the port when it isn't specified lets us do this transparently. This allows to maintain backwards compat in older append functions, and nobody aside from us currently uses the new rebar_uri module so we can decide to introduce this potential inconsistency if we wish to. --- src/rebar_git_resource.erl | 9 +---- src/rebar_uri.erl | 81 ++++++++++++++++++++++++++++++++------ src/rebar_utils.erl | 4 ++ test/rebar_uri_SUITE.erl | 34 ++++++++-------- 4 files changed, 93 insertions(+), 35 deletions(-) diff --git a/src/rebar_git_resource.erl b/src/rebar_git_resource.erl index 808f1f8f..4a37a02b 100644 --- a/src/rebar_git_resource.erl +++ b/src/rebar_git_resource.erl @@ -100,13 +100,6 @@ compare_url(Dir, Url) -> ?DEBUG("Comparing git url ~p with ~p", [ParsedUrl, ParsedCurrentUrl]), ParsedCurrentUrl =:= ParsedUrl. --ifdef (OTP_RELEASE). - -if(?OTP_RELEASE >= 23). - -compile({nowarn_deprecated_function, [{http_uri, parse, 2}, - {http_uri, scheme_defaults, 0}]}). - -endif. --endif. - parse_git_url(Url) -> %% Checks for standard scp style git remote case re:run(Url, ?SCP_PATTERN, [{capture, [host, path], list}, unicode]) of @@ -116,7 +109,7 @@ parse_git_url(Url) -> parse_git_url(not_scp, Url) end. parse_git_url(not_scp, Url) -> - UriOpts = [{scheme_defaults, [{git, 9418} | http_uri:scheme_defaults()]}], + UriOpts = [{scheme_defaults, [{git, 9418} | rebar_uri:scheme_defaults()]}], case rebar_uri:parse(Url, UriOpts) of #{path := Path, host := Host} -> {ok, {Host, filename:rootname(Path, ".git")}}; diff --git a/src/rebar_uri.erl b/src/rebar_uri.erl index 3a6382b1..a52f0e02 100644 --- a/src/rebar_uri.erl +++ b/src/rebar_uri.erl @@ -2,26 +2,33 @@ -module(rebar_uri). -export([ - parse/1, + parse/1, parse/2, scheme_defaults/0, append_path/2 ]). --import(rebar_utils, [to_list/1]). - --ifdef (OTP_RELEASE). +-ifdef(OTP_RELEASE). -spec parse(URIString) -> URIMap when URIString :: uri_string:uri_string(), URIMap :: uri_string:uri_map() | uri_string:error(). parse(URIString) -> - uri_string:parse(URIString). + parse(URIString, []). + +parse(URIString, URIOpts) -> + case uri_string:parse(URIString) of + #{path := ""} = Map -> apply_opts(Map#{path => "/"}, URIOpts); + Map -> apply_opts(Map, URIOpts) + end. -else. -spec parse(URIString) -> URIMap when URIString :: iodata(), URIMap :: map() | {error, atom(), term()}. parse(URIString) -> - case http_uri:parse(URIString) of + parse(URIString, []). + +parse(URIString, URIOpts) -> + case http_uri:parse(URIString, URIOpts) of {error, Reason} -> %% no additional parser/term info available to us, %% e.g. see what uri_string returns in @@ -46,11 +53,11 @@ parse(URIString) -> -endif. %% OTP 21+ --ifdef (OTP_RELEASE). +-ifdef(OTP_RELEASE). append_path(Url, ExtraPath) -> case parse(Url) of #{path := Path} = Map -> - FullPath = filename:join(Path, ExtraPath), + FullPath = join(Path, ExtraPath), {ok, uri_string:recompose(maps:update(path, FullPath, Map))}; _ -> error @@ -58,14 +65,66 @@ append_path(Url, ExtraPath) -> -else. append_path(Url, ExtraPath) -> case parse(Url) of - #{scheme := Scheme, userinfo := UserInfo, host := Host, port := Port, path := Path, query := Query} -> + #{scheme := Scheme, userinfo := UserInfo, host := Host, + port := Port, path := Path, query := Query} -> + ListScheme = rebar_utils:to_list(Scheme), PrefixedQuery = case Query of [] -> []; Other -> lists:append(["?", Other]) end, - {ok, lists:append([to_list(Scheme), "://", UserInfo, Host, ":", to_list(Port), - filename:join(Path, ExtraPath), PrefixedQuery])}; + NormPath = case Path of + "" -> "/"; + _ -> Path + end, + {ok, maybe_port( + Url, lists:append([ListScheme, "://", UserInfo, Host]), + [$: | rebar_utils:to_list(Port)], + lists:append([join(NormPath, ExtraPath), PrefixedQuery]) + )}; _ -> error end. -endif. + +%% OTP 21+ +-ifdef(OTP_RELEASE). +scheme_defaults() -> + %% no scheme defaults here; just custom ones + []. +-else. +scheme_defaults() -> + http_uri:scheme_defaults(). +-endif. + +join(URI, "") -> URI; +join(URI, "/") -> URI; +join("/", [$/|_] = Path) -> Path; +join("/", Path) -> [$/ | Path]; +join("", [$/|_] = Path) -> Path; +join("", Path) -> [$/ | Path]; +join([H|T], Path) -> [H | join(T, Path)]. + + +-ifdef(OTP_RELEASE). +apply_opts(Map = #{port := _}, _) -> + Map; +apply_opts(Map = #{scheme := Scheme}, URIOpts) -> + SchemeDefaults = proplists:get_value(scheme_defaults, URIOpts, []), + %% Here is the funky bit: don't add the port number if it's in a default + %% to maintain proper default behaviour. + try lists:keyfind(list_to_existing_atom(Scheme), 1, SchemeDefaults) of + {_, Port} -> + Map#{port => Port}; + false -> + Map + catch + error:badarg -> % not an existing atom, not in the list + Map + end. +-else. +maybe_port(Url, Host, Port, PathQ) -> + case lists:prefix(Host ++ Port, Url) of + true -> Host ++ Port ++ PathQ; % port was explicit + false -> Host ++ PathQ % port was implicit + end. +-endif. diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 6be50f14..0933bb6c 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -64,6 +64,7 @@ tup_find/2, line_count/1, set_httpc_options/0, + url_append_path/2, escape_chars/1, escape_double_quotes/1, escape_double_quotes_weak/1, @@ -938,6 +939,9 @@ normalise_proxy(Scheme, URI) -> _ -> URI end. +url_append_path(Url, ExtraPath) -> + rebar_uri:append_path(Url, ExtraPath). + %% escape\ as\ a\ shell\? escape_chars(Str) when is_atom(Str) -> escape_chars(atom_to_list(Str)); diff --git a/test/rebar_uri_SUITE.erl b/test/rebar_uri_SUITE.erl index 4db93690..a7fde27b 100644 --- a/test/rebar_uri_SUITE.erl +++ b/test/rebar_uri_SUITE.erl @@ -9,20 +9,20 @@ -include_lib("kernel/include/file.hrl"). all() -> - [parse]. + [parse, append_path]. parse(_Config) -> #{scheme := Scheme, host := Host, path := Path} = rebar_uri:parse("https://repo.hex.pm"), ?assertEqual("https", Scheme), ?assertEqual("repo.hex.pm", Host), - ?assert(lists:member(Path, ["", "/"])), + ?assertEqual(Path, "/"), % Normalize on OTP-23 behaviour. #{scheme := Scheme2, host := Host2, port := Port2, path := Path2, query := Query2} = rebar_uri:parse("https://repo.hex.pm:443?foo=bar"), ?assertEqual("https", Scheme2), ?assertEqual("repo.hex.pm", Host2), ?assertEqual(443, Port2), - ?assert(lists:member(Path2, ["", "/"])), + ?assertEqual(Path2, "/"), % Normalize on old http_uri behaviour ?assertEqual("foo=bar", Query2), #{scheme := Scheme3, host := Host3, path := Path3, query := Query3} = @@ -30,19 +30,21 @@ parse(_Config) -> ?assertEqual("https", Scheme3), ?assertEqual("repo.hex.pm", Host3), ?assertEqual("/over/here", Path3), - ?assertEqual("foo=bar", Query3). + ?assertEqual("foo=bar", Query3), + + %% override default port and get it parsed as such + ?assertMatch(#{port := 1337}, + rebar_uri:parse("https://repo.hex.pm/", + [{scheme_defaults, [{https,1337}]}])), + ok. append_path(_Config) -> - %% OTP version differences - {ok, Val1} = rebar_utils:append_path("https://repo.hex.pm", "/repos/org"), - ?assert(lists:member(Val1, [ - "https://repo.hex.pm/repos/org", - "https://repo.hex.pm:443/repos/org" - ])), - {ok, Val2} = rebar_utils:append_path("https://repo.hex.pm?foo=bar", "/repos/org"), - ?assert(lists:member(Val2, [ - "https://repo.hex.pm/repos/org?foo=bar", - "https://repo.hex.pm:443/repos/org?foo=bar" - ])), + %% Default port for the proto is omitted if not mentioned originally + {ok, Val1} = rebar_uri:append_path("https://repo.hex.pm/", "/repos/org"), + ?assertEqual("https://repo.hex.pm/repos/org", Val1), + %% QS elements come after the path + {ok, Val2} = rebar_uri:append_path("https://repo.hex.pm?foo=bar", "/repos/org"), + ?assertEqual("https://repo.hex.pm/repos/org?foo=bar", Val2), + %% If the port is explicitly mentioned, keep it. ?assertEqual({ok, "https://repo.hex.pm:443/repos/org?foo=bar"}, - rebar_utils:append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")). + rebar_uri:append_path("https://repo.hex.pm:443?foo=bar", "/repos/org")).