Skip to content

Commit

Permalink
fix parsing query parameters on url without path
Browse files Browse the repository at this point in the history
fix #512
  • Loading branch information
benoitc committed Jun 20, 2018
1 parent 13dd2f4 commit 3de7391
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
37 changes: 24 additions & 13 deletions src/hackney_url.erl
Expand Up @@ -50,8 +50,7 @@ parse_url(URL, S) ->
case binary:split(URL, <<"/">>) of
[Addr] ->
Path = <<"/">>,
parse_addr(Addr, S#hackney_url{raw_path = Path,
path = Path });
parse_addr1(Addr, S#hackney_url{raw_path = Path, path = Path });
[Addr, Path] ->
RawPath = <<"/", Path/binary>>,
{Path1, Query, Fragment} = parse_path(RawPath),
Expand Down Expand Up @@ -82,7 +81,7 @@ normalize(#hackney_url{}=Url, Fun) when is_function(Fun, 1) ->
port = Port,
netloc = Netloc0,
path = Path} = Url,

{Host, Netloc} = case inet_parse:address(Host0) of
{ok, {_, _, _, _}} ->
{Host0, Netloc0};
Expand All @@ -91,7 +90,7 @@ normalize(#hackney_url{}=Url, Fun) when is_function(Fun, 1) ->
_ ->
Host1 = unicode:characters_to_list(
urldecode(unicode:characters_to_binary(Host0))),

%% encode domain if needed
Host2 = idna:to_ascii(Host1),
Netloc1 = case {Scheme, Port} of
Expand Down Expand Up @@ -121,13 +120,13 @@ unparse_url(#hackney_url{}=Url) ->
fragment = Fragment,
user = User,
password = Password} = Url,

Scheme1 = case Scheme of
http -> <<"http://">>;
https -> <<"https://">>;
http_unix -> <<"http+unix://">>
end,

Netloc1 = case User of
<<>> ->
Netloc;
Expand All @@ -136,27 +135,39 @@ unparse_url(#hackney_url{}=Url) ->
_ ->
<< User/binary, "@", Netloc/binary >>
end,

Qs1 = case Qs of
<<>> -> <<>>;
_ -> << "?", Qs/binary >>
end,

Fragment1 = case Fragment of
<<>> -> <<>>;
_ -> << "#", Fragment/binary >>
end,

Path1 = case Path of
nil -> <<>>;
undefined -> <<>>;
<<>> -> <<"/">>;
_ -> Path
end,

<< Scheme1/binary, Netloc1/binary, Path1/binary, Qs1/binary, Fragment1/binary >>.

%% @private
parse_addr1(Addr, S) ->
case binary:split(Addr, <<"?">>) of
[_Addr] ->
{Addr1, Fragment} = parse_fragment(Addr),
parse_addr(Addr1, S#hackney_url{fragment = Fragment});
[Addr1, Query] ->
{Query1, Fragment} = parse_fragment(Query),
#hackney_url{raw_path = RawPath0 } = S,
RawPath1 = << RawPath0/binary, "?", Query1/binary >>,
parse_addr(Addr1, S#hackney_url{raw_path=RawPath1, qs=Query1, fragment=Fragment})
end.

parse_addr(Addr, S) ->
case binary:split(Addr, <<"@">>) of
[Addr] ->
Expand All @@ -172,7 +183,7 @@ parse_addr(Addr, S) ->
user = User,
password = <<>> })
end

end.

parse_netloc(<<"[", Rest/binary>>, #hackney_url{transport=Transport}=S) ->
Expand Down Expand Up @@ -355,13 +366,13 @@ make_url(Url, PathParts, Query) when is_binary(Query) ->
%% create path
PathParts1 = [fix_path(P) || P <- PathParts, P /= "", P /= "/" orelse P /= <<"/">>],
Path = hackney_bstr:join([<<>> | PathParts1], <<"/">>),

%% initialise the query
Query1 = case Query of
<<>> -> <<>>;
_ -> << "?", Query/binary >>
end,

%% make the final uri
iolist_to_binary([fix_path(Url), Path, Query1]).

Expand Down
13 changes: 13 additions & 0 deletions test/hackney_url_tests.erl
Expand Up @@ -181,6 +181,19 @@ parse_url_test_() ->
port = 80,
user = <<"">>,
password = <<"">>}
},
{<<"http://www.example.com?q=123">>,
#hackney_url{transport =hackney_tcp,
scheme = http,
netloc = <<"www.example.com">>,
raw_path = <<"/?q=123">>,
path = <<"/">>,
qs = <<"q=123">>,
fragment = <<"">>,
host = "www.example.com",
port = 80,
user = <<"">>,
password = <<"">>}
}
],
[{V, fun() -> R = hackney_url:parse_url(V) end} || {V, R} <- Tests].
Expand Down

0 comments on commit 3de7391

Please sign in to comment.