File 0541-inets-Copy-ipfamily-from-state-into-requests.patch of Package erlang
From fc63402c4448fada630ee77ee3577115319487eb Mon Sep 17 00:00:00 2001
From: Johannes Christ <jc@jchri.st>
Date: Sat, 28 Oct 2023 17:07:36 +0200
Subject: [PATCH 1/2] inets: Copy ipfamily from state into requests
On redirected and retried requests, the newly started httpc_handler may
lose the ipfamily that was originally selected in the request. When
sending a request over IPv6 using option `{ipfamily, inet6fb4}` and a
redirect is returned by the server, the second request would end up
wrongly connecting over IPv4 instead.
---
lib/inets/src/http_client/httpc_handler.erl | 19 ++++++++++++++++++-
1 file changed, 18 insertions(+), 1 deletion(-)
diff --git a/lib/inets/src/http_client/httpc_handler.erl b/lib/inets/src/http_client/httpc_handler.erl
index 026cea9b1f..b4ac3b61ee 100644
--- a/lib/inets/src/http_client/httpc_handler.erl
+++ b/lib/inets/src/http_client/httpc_handler.erl
@@ -1025,7 +1025,8 @@ handle_response(#state{status = Status0} = State0) when Status0 =/= new ->
options = Options,
profile_name = ProfileName} = State,
handle_cookies(Headers, Request, Options, ProfileName),
- case httpc_response:result({StatusLine, Headers, Body}, Request) of
+ RequestWithIpFamily = add_ipfamily_to_request(Request, Options#options.ipfamily),
+ case httpc_response:result({StatusLine, Headers, Body}, RequestWithIpFamily) of
%% 100-continue
continue ->
%% Send request body
@@ -1073,6 +1074,22 @@ handle_response(#state{status = Status0} = State0) when Status0 =/= new ->
{stop, normal, NewState}
end.
+sanitize_request_socket_opts(undefined) -> [];
+sanitize_request_socket_opts(Opts) -> Opts.
+
+% Carry over the IP family from the existing state options for the case
+% where we perform a retry or redirect. Without interpolating the ipfamily
+% into the request socket options, the newly started httpc_handler would lose
+% context of the IP family and may try to contact IPv6 hosts over IPv4 via
+% the default ipfamily option "inet". Skip adding it for IPv4 (inet) to
+% prevent TLS errors on following redirects.
+add_ipfamily_to_request(Request, inet) -> Request;
+add_ipfamily_to_request(Request, IpFamily) ->
+ SocketOpts = sanitize_request_socket_opts(Request#request.socket_opts),
+ Request#request{
+ socket_opts = [{ipfamily, IpFamily} | SocketOpts]
+ }.
+
handle_cookies(_,_, #options{cookies = disabled}, _) ->
ok;
%% User wants to verify the cookies before they are stored,
--
2.35.3