From d3feeba2cd01b6d9bb04426a1e58b596200ffbf2 Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 04:16:00 +0200 Subject: [PATCH 1/8] invalid validation of ipfamily-unix_socket combo --- lib/inets/test/httpc_SUITE.erl | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 22bd55355cea..ab1b2f6ad5ae 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -145,7 +145,8 @@ real_requests_esi() -> [slow_connection]. simulated_unix_socket() -> - [unix_domain_socket]. + [unix_domain_socket, + invalid_ipfamily_unix_socket]. only_simulated() -> [ @@ -1858,6 +1859,21 @@ unix_domain_socket(Config) when is_list(Config) -> {ok, {{_,200,_}, [_ | _], _}} = httpc:request(get, {URL, []}, [], []). +invalid_ipfamily_unix_socket() -> + [{doc, "Test that httpc profile can't end up having invalid combination of ipfamily and unix_socket options"}]. +invalid_ipfamily_unix_socket(Config) when is_list(Config) -> + Profile = ?profile(Config), + + ct:log("Using profile ~w", [Profile]), + {ok,[{unix_socket,?UNIX_SOCKET}, {ipfamily, local}]} = + httpc:get_options([unix_socket, ipfamily], Profile), + ?assertMatch({error, _}, httpc:set_option(unix_socket, undefined, Profile)), + ?assertMatch({error, _}, httpc:set_option(ipfamily, inet, Profile)), + ?assertMatch({error, _}, httpc:set_option(ipfamily, inetv6, Profile)), + ok = httpc:set_options([{unix_socket, undefined}, {ipfamily, inet}], Profile), + ?assertMatch({error, _}, httpc:set_option(unix_socket, ?UNIX_SOCKET, Profile)). + + %%------------------------------------------------------------------------- delete_no_body(doc) -> ["Test that a DELETE request without Body does not send a Content-Type header - Solves ERL-536"]; From 8cbebd137334e1d808967f34a594ce6f89015b1e Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 04:32:05 +0200 Subject: [PATCH 2/8] ipfamily-unix_socket combo validation fix --- lib/inets/src/http_client/httpc.erl | 36 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 96d5cd250d1a..f8cfa1d0b2ba 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -382,7 +382,9 @@ set_options(Options) -> DomainDesc :: string(), HostName :: uri_string:uri_string(). set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) -> - case validate_options(Options) of + IpFamily = httpc_manager:get_option(ipfamily, Profile), + UnixSock = httpc_manager:get_option(unix_socket, Profile), + case validate_options(Options, IpFamily, UnixSock) of {ok, Opts} -> httpc_manager:set_options(Opts, profile_name(Profile)); {error, Reason} -> @@ -1170,28 +1172,24 @@ request_options_sanity_check(Opts) -> end, ok. -validate_ipfamily_unix_socket(Options0) -> - IpFamily = proplists:get_value(ipfamily, Options0, inet), - UnixSocket = proplists:get_value(unix_socket, Options0, undefined), - Options1 = proplists:delete(ipfamily, Options0), - Options2 = proplists:delete(ipfamily, Options1), - validate_ipfamily_unix_socket(IpFamily, UnixSocket, Options2, - [{ipfamily, IpFamily}, {unix_socket, UnixSocket}]). -%% -validate_ipfamily_unix_socket(local, undefined, _Options, _Acc) -> - bad_option(unix_socket, undefined); -validate_ipfamily_unix_socket(IpFamily, UnixSocket, _Options, _Acc) +validate_ipfamily_unix_socket(Options0, CurrIpFamily, CurrUnixSock) -> + IpFamily = proplists:get_value(ipfamily, Options0, CurrIpFamily), + UnixSocket = proplists:get_value(unix_socket, Options0, CurrUnixSock), + validate_ipfamily_unix_socket(IpFamily, UnixSocket). + +validate_ipfamily_unix_socket(local, undefined) -> + throw({error, {bad_ipfamily_unix_socket_combination, local, undefined}}); +validate_ipfamily_unix_socket(IpFamily, UnixSocket) when IpFamily =/= local, UnixSocket =/= undefined -> - bad_option(ipfamily, IpFamily); -validate_ipfamily_unix_socket(IpFamily, UnixSocket, Options, Acc) -> + throw({error, {bad_ipfamily_unix_socket_combination, IpFamily, UnixSocket}}); +validate_ipfamily_unix_socket(IpFamily, UnixSocket) -> validate_ipfamily(IpFamily), - validate_unix_socket(UnixSocket), - {Options, Acc}. + validate_unix_socket(UnixSocket). -validate_options(Options0) -> +validate_options(Options0, CurrIpFamily, CurrUnixSock) -> try - {Options, Acc} = validate_ipfamily_unix_socket(Options0), - validate_options(Options, Acc) + validate_ipfamily_unix_socket(Options0, CurrIpFamily, CurrUnixSock), + validate_options(Options0, []) catch error:Reason -> {error, Reason} From ae8cfaae740fcd966498b38a6dec0eba0ea40d74 Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 04:32:40 +0200 Subject: [PATCH 3/8] removed unused legacy option handling --- lib/inets/src/http_client/httpc_manager.erl | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl index cb50e8afbfcd..ef58bdb8d7ea 100644 --- a/lib/inets/src/http_client/httpc_manager.erl +++ b/lib/inets/src/http_client/httpc_manager.erl @@ -1028,19 +1028,7 @@ get_cookies(Opts, #options{cookies = Default}) -> proplists:get_value(cookies, Opts, Default). get_ipfamily(Opts, #options{ipfamily = IpFamily}) -> - case lists:keysearch(ipfamily, 1, Opts) of - false -> - case proplists:get_value(ipv6, Opts) of - enabled -> - inet6fb4; - disabled -> - inet; - _ -> - IpFamily - end; - {value, {_, Value}} -> - Value - end. + proplists:get_value(ipfamily, Opts, IpFamily). get_ip(Opts, #options{ip = Default}) -> proplists:get_value(ip, Opts, Default). From 6b1313fd8142a7f51f702c3a85079a0af2ad0f0a Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 04:36:47 +0200 Subject: [PATCH 4/8] blank line removed --- lib/inets/test/httpc_SUITE.erl | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index ab1b2f6ad5ae..3d4e6cf3583b 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -1873,7 +1873,6 @@ invalid_ipfamily_unix_socket(Config) when is_list(Config) -> ok = httpc:set_options([{unix_socket, undefined}, {ipfamily, inet}], Profile), ?assertMatch({error, _}, httpc:set_option(unix_socket, ?UNIX_SOCKET, Profile)). - %%------------------------------------------------------------------------- delete_no_body(doc) -> ["Test that a DELETE request without Body does not send a Content-Type header - Solves ERL-536"]; From 3a5b02b2c8401474235b430e3afb4ce0a623049c Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 05:03:26 +0200 Subject: [PATCH 5/8] get_option call fix --- lib/inets/src/http_client/httpc.erl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index f8cfa1d0b2ba..ac28b534c7f7 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -382,8 +382,8 @@ set_options(Options) -> DomainDesc :: string(), HostName :: uri_string:uri_string(). set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) -> - IpFamily = httpc_manager:get_option(ipfamily, Profile), - UnixSock = httpc_manager:get_option(unix_socket, Profile), + {ok, IpFamily} = get_option(ipfamily, Profile), + {ok, UnixSock} = get_option(unix_socket, Profile), case validate_options(Options, IpFamily, UnixSock) of {ok, Opts} -> httpc_manager:set_options(Opts, profile_name(Profile)); From 72d654ce84fd712a2532e8db919c63b696eb8eca Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Wed, 2 Oct 2024 11:11:04 +0200 Subject: [PATCH 6/8] catch badoption throw --- lib/inets/src/http_client/httpc.erl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index ac28b534c7f7..6c16fb4f1762 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -1191,7 +1191,7 @@ validate_options(Options0, CurrIpFamily, CurrUnixSock) -> validate_ipfamily_unix_socket(Options0, CurrIpFamily, CurrUnixSock), validate_options(Options0, []) catch - error:Reason -> + throw:Reason -> {error, Reason} end. %% From 114192bc79d79ad4294f1b0dccd6261735c6e1a2 Mon Sep 17 00:00:00 2001 From: Marko Mindek Date: Thu, 3 Oct 2024 10:46:01 +0200 Subject: [PATCH 7/8] get_option error handling --- lib/inets/src/http_client/httpc.erl | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index 6c16fb4f1762..f9d7da4a4f10 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -382,13 +382,11 @@ set_options(Options) -> DomainDesc :: string(), HostName :: uri_string:uri_string(). set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) -> - {ok, IpFamily} = get_option(ipfamily, Profile), - {ok, UnixSock} = get_option(unix_socket, Profile), - case validate_options(Options, IpFamily, UnixSock) of - {ok, Opts} -> - httpc_manager:set_options(Opts, profile_name(Profile)); - {error, Reason} -> - {error, Reason} + maybe + {ok, IpFamily} ?= get_option(ipfamily, Profile), + {ok, UnixSock} ?= get_option(unix_socket, Profile), + {ok, Opts} ?= validate_options(Options, IpFamily, UnixSock), + httpc_manager:set_options(Opts, profile_name(Profile)) end. -spec set_option(atom(), term()) -> ok | {error, term()}. From 4ad15706b1b6b0cf71850dcc98ccfff389124893 Mon Sep 17 00:00:00 2001 From: Konrad Pietrzak Date: Fri, 29 Nov 2024 16:08:01 +0100 Subject: [PATCH 8/8] backport httpc:set_options fix to OTP-25.3.2 --- lib/inets/src/http_client/httpc.erl | 20 ++++++++++++++------ lib/inets/test/httpc_SUITE.erl | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/lib/inets/src/http_client/httpc.erl b/lib/inets/src/http_client/httpc.erl index f9d7da4a4f10..ab7f8ff18db0 100644 --- a/lib/inets/src/http_client/httpc.erl +++ b/lib/inets/src/http_client/httpc.erl @@ -382,12 +382,20 @@ set_options(Options) -> DomainDesc :: string(), HostName :: uri_string:uri_string(). set_options(Options, Profile) when is_atom(Profile) orelse is_pid(Profile) -> - maybe - {ok, IpFamily} ?= get_option(ipfamily, Profile), - {ok, UnixSock} ?= get_option(unix_socket, Profile), - {ok, Opts} ?= validate_options(Options, IpFamily, UnixSock), - httpc_manager:set_options(Opts, profile_name(Profile)) - end. + IsInetsRunning = [Application || {inets, _, _} = Application <- application:which_applications()] =/= [], + case IsInetsRunning of + true -> + {ok, IpFamily} = get_option(ipfamily, Profile), + {ok, UnixSock} = get_option(unix_socket, Profile), + case validate_options(Options, IpFamily, UnixSock) of + {ok, Opts} -> + httpc_manager:set_options(Opts, profile_name(Profile)); + Error -> + Error + end; + _ -> + {error, inets_not_started} + end. -spec set_option(atom(), term()) -> ok | {error, term()}. set_option(Key, Value) -> diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl index 3d4e6cf3583b..d01c75f6620b 100644 --- a/lib/inets/test/httpc_SUITE.erl +++ b/lib/inets/test/httpc_SUITE.erl @@ -1862,7 +1862,7 @@ unix_domain_socket(Config) when is_list(Config) -> invalid_ipfamily_unix_socket() -> [{doc, "Test that httpc profile can't end up having invalid combination of ipfamily and unix_socket options"}]. invalid_ipfamily_unix_socket(Config) when is_list(Config) -> - Profile = ?profile(Config), + Profile = proplists:get_value(profile, Config, httpc:default_profile()), ct:log("Using profile ~w", [Profile]), {ok,[{unix_socket,?UNIX_SOCKET}, {ipfamily, local}]} =