aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib
diff options
context:
space:
mode:
authorPéter Dimitrov <[email protected]>2017-10-25 10:11:14 +0200
committerPéter Dimitrov <[email protected]>2017-10-25 11:17:29 +0200
commit992cda82f16ee23b0114563858d5a082711f659b (patch)
treeb6f86f3dbec15036552ff46cfa23edee53b0d929 /lib/stdlib
parent3c80849dc9167018a66542b76b441e675d404a78 (diff)
downloadotp-992cda82f16ee23b0114563858d5a082711f659b.tar.gz
otp-992cda82f16ee23b0114563858d5a082711f659b.tar.bz2
otp-992cda82f16ee23b0114563858d5a082711f659b.zip
stdlib: Refactor compose_query
Diffstat (limited to 'lib/stdlib')
-rw-r--r--lib/stdlib/src/uri_string.erl73
-rw-r--r--lib/stdlib/test/uri_string_SUITE.erl9
2 files changed, 45 insertions, 37 deletions
diff --git a/lib/stdlib/src/uri_string.erl b/lib/stdlib/src/uri_string.erl
index 684087b870..2bf7ceaff1 100644
--- a/lib/stdlib/src/uri_string.erl
+++ b/lib/stdlib/src/uri_string.erl
@@ -396,19 +396,24 @@ compose_query(List) ->
compose_query([],_Options) ->
[];
compose_query(List, Options) ->
- try compose_query(List, Options, []) of
+ try compose_query(List, Options, false, <<>>) of
Result -> Result
catch
throw:{error, Atom, RestData} -> {error, Atom, RestData}
end.
%%
-compose_query([{Key,Value}|Rest], Options, Acc) ->
- Separator = get_separator(Options, Acc),
+compose_query([{Key,Value}|Rest], Options, IsList, Acc) ->
+ Separator = get_separator(Options, Rest),
K = form_urlencode(Key),
V = form_urlencode(Value),
- compose_query(Rest, Options, Acc ++ Separator ++ K ++ "=" ++ V);
-compose_query([], _Options, Acc) ->
- Acc.
+ Flag = is_list(Key) orelse is_list(Value),
+ IsListNew = IsList orelse Flag,
+ compose_query(Rest, Options, IsListNew, <<Acc/binary,K/binary,"=",V/binary,Separator/binary>>);
+compose_query([], _Options, IsList, Acc) ->
+ case IsList of
+ true -> convert_list(Acc, utf8);
+ false -> Acc
+ end.
%%-------------------------------------------------------------------------
@@ -1711,43 +1716,41 @@ percent_encode_segment(Segment) ->
%%-------------------------------------------------------------------------
%% Returns separator to be used between key-value pairs
-get_separator(_, Acc) when length(Acc) =:= 0 ->
- [];
-get_separator([], _Acc) ->
- "&amp;";
-get_separator([{separator, amp}], _Acc) ->
- "&";
-get_separator([{separator, escaped_amp}], _Acc) ->
- "&amp;";
-get_separator([{separator, semicolon}], _Acc) ->
- ";".
+get_separator(_, L) when length(L) =:= 0 ->
+ <<>>;
+get_separator([], _L) ->
+ <<"&amp;">>;
+get_separator([{separator, amp}], _L) ->
+ <<"&">>;
+get_separator([{separator, escaped_amp}], _L) ->
+ <<"&amp;">>;
+get_separator([{separator, semicolon}], _L) ->
+ <<";">>.
%% Form-urlencode input based on RFC 1866 [8.2.1]
-form_urlencode(Cs) when is_binary(Cs) ->
- L = convert_list(Cs, utf8),
- form_urlencode(L, []);
+form_urlencode(Cs) when is_list(Cs) ->
+ B = convert_binary(Cs, utf8, utf8),
+ form_urlencode(B, <<>>);
form_urlencode(Cs) ->
- L = flatten_list(Cs, utf8),
- form_urlencode(L, []).
+ form_urlencode(Cs, <<>>).
%%
-form_urlencode([], Acc) ->
- lists:reverse(Acc);
-form_urlencode([$ |T], Acc) ->
- form_urlencode(T, [$+|Acc]);
-form_urlencode([H|T], Acc) ->
+form_urlencode(<<>>, Acc) ->
+ Acc;
+form_urlencode(<<$ ,T/binary>>, Acc) ->
+ form_urlencode(T, <<Acc/binary,$+>>);
+form_urlencode(<<H/utf8,T/binary>>, Acc) ->
case is_url_char(H) of
true ->
- form_urlencode(T, [H|Acc]);
+ form_urlencode(T, <<Acc/binary,H>>);
false ->
- E = urlencode_char(H),
- form_urlencode(T, lists:reverse(E) ++ Acc)
- end.
-
-
-urlencode_char(C) ->
- B = percent_encode_binary(C),
- unicode:characters_to_list(B).
+ E = percent_encode_binary(H),
+ form_urlencode(T, <<Acc/binary,E/binary>>)
+ end;
+form_urlencode(<<H,_T/binary>>, _Acc) ->
+ throw({error,invalid_utf8,<<H>>});
+form_urlencode(H, _Acc) ->
+ throw({error,badarg, H}).
%% Return true if input char can appear in URL according to
diff --git a/lib/stdlib/test/uri_string_SUITE.erl b/lib/stdlib/test/uri_string_SUITE.erl
index fe832ac82c..c230f7c631 100644
--- a/lib/stdlib/test/uri_string_SUITE.erl
+++ b/lib/stdlib/test/uri_string_SUITE.erl
@@ -830,10 +830,15 @@ compose_query(_Config) ->
"foo=1&amp;bar=2" = uri_string:compose_query([{"foo","1"}, {"bar", "2"}],[{separator,escaped_amp}]),
"foo=1&bar=2" = uri_string:compose_query([{"foo","1"}, {"bar", "2"}],[{separator,amp}]),
"foo=1;bar=2" = uri_string:compose_query([{"foo","1"}, {"bar", "2"}],[{separator,semicolon}]),
- "foo+bar=1&amp;%C3%B6=2" = uri_string:compose_query([{"foo bar","1"}, {"ö", "2"}]).
+ "foo+bar=1&amp;%C3%B6=2" = uri_string:compose_query([{"foo bar","1"}, {"ö", "2"}]),
+ "foo+bar=1&amp;%C3%B6=2" = uri_string:compose_query([{<<"foo bar">>,<<"1">>}, {"ö", <<"2">>}]),
+ <<"foo+bar=1&amp;%C3%B6=2">> =
+ uri_string:compose_query([{<<"foo bar">>,<<"1">>}, {<<"ö"/utf8>>, <<"2">>}]).
compose_query_negative(_Config) ->
- {error,badarg,4} = uri_string:compose_query([{"",4}]).
+ {error,badarg,4} = uri_string:compose_query([{"",4}]),
+ {error,badarg,5} = uri_string:compose_query([{5,""}]),
+ {error,invalid_utf8,<<"ö">>} = uri_string:compose_query([{"foo bar","1"}, {<<"ö">>, "2"}]).
dissect_query(_Config) ->
[] = uri_string:dissect_query(""),