Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.
 
 
 

131 linhas
4.0 KiB

%%% @doc multi-OTP version compatibility shim for working with URIs
-module(rebar_uri).
-export([
parse/1, parse/2, scheme_defaults/0,
append_path/2
]).
-ifdef(OTP_RELEASE).
-spec parse(URIString) -> URIMap when
URIString :: uri_string:uri_string(),
URIMap :: uri_string:uri_map() | uri_string:error().
parse(URIString) ->
parse(URIString, []).
parse(URIString, URIOpts) ->
case uri_string:parse(URIString) of
#{path := ""} = Map -> apply_opts(Map#{path => "/"}, URIOpts);
Map when is_map(Map) -> apply_opts(Map, URIOpts);
{error, _, _} = E -> E
end.
-else.
-spec parse(URIString) -> URIMap when
URIString :: iodata(),
URIMap :: map() | {error, term(), term()}.
parse(URIString) ->
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
%% uri_string:parse(<<"h$ttp:::://////lolz">>).
{error, "", Reason};
{ok, {Scheme, UserInfo, Host, Port, Path, Query}} ->
#{
scheme => rebar_utils:to_list(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.
%% OTP 21+
-ifdef(OTP_RELEASE).
append_path(Url, ExtraPath) ->
case parse(Url) of
#{path := Path} = Map ->
FullPath = 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} ->
ListScheme = rebar_utils:to_list(Scheme),
PrefixedQuery = case Query of
[] -> [];
Other -> lists:append(["?", Other])
end,
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.