File 0210-inets-Fix-broken-httpc-options-handling.patch of Package erlang

From 1986e3746f495519c04d540683d1b9b78548b870 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A9ter=20Dimitrov?= <peterdmv@erlang.org>
Date: Tue, 10 Apr 2018 16:25:57 +0200
Subject: [PATCH] inets: Fix broken httpc options handling

- Add support for setting socket options per request.
- Add http_ipv6 test group.

Change-Id: Ia2aca37c0b5fe64a41995c79ae3399434b17ab8a
---
 lib/inets/doc/src/httpc.xml                 | 20 +++++++----
 lib/inets/src/http_client/httpc_manager.erl | 32 ++++++++++++++++-
 lib/inets/test/httpc_SUITE.erl              | 54 ++++++++++++++++++++++++++++-
 3 files changed, 98 insertions(+), 8 deletions(-)

diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml
index befcd83827..1ef93de301 100644
--- a/lib/inets/doc/src/httpc.xml
+++ b/lib/inets/doc/src/httpc.xml
@@ -450,17 +450,22 @@
 
           <tag><c><![CDATA[socket_opts]]></c></tag>
           <item>
-            <p>Socket options to be used for this and subsequent 
-	    requests.</p>
+            <p>Socket options to be used for this request.</p>
 	    <p>Overrides any value set by function
 	    <seealso marker="#set_options-1">set_options</seealso>.</p>
             <p>The validity of the options is <em>not</em> checked by
             the HTTP client they are assumed to be correct and passed
             on to ssl application and inet driver, which may reject
-            them if they are not correct. Note that the current
-            implementation assumes the requests to the same host, port
-            combination will use the same socket options.
+            them if they are not correct.
 	    </p>
+	    <note>
+	      <p>
+		Persistent connections are not supported when setting the
+		<c>socket_opts</c> option. When <c>socket_opts</c> is not
+		set the current implementation assumes the requests to the
+		same host, port combination will use the same socket options.
+	      </p>
+	    </note>
 	    
             <p>By default the socket options set by function
 	    <seealso marker="#set_options-1">set_options/[1,2]</seealso> 
@@ -633,8 +638,11 @@
 	  to complete. The HTTP/1.1 specification suggests a
 	  limit of two persistent connections per server, which is the
 	  default value of option <c>max_sessions</c>.</p>
+	  <p>
+            The current implementation assumes the requests to the same host, port
+            combination will use the same socket options.
+	  </p>
 	</note>
-
         <marker id="get_options"></marker>
       </desc>
     </func>
diff --git a/lib/inets/src/http_client/httpc_manager.erl b/lib/inets/src/http_client/httpc_manager.erl
index 7b8d7875de..c3404dbb37 100644
--- a/lib/inets/src/http_client/httpc_manager.erl
+++ b/lib/inets/src/http_client/httpc_manager.erl
@@ -750,8 +750,26 @@ handle_request(#request{settings =
     start_handler(NewRequest#request{headers = NewHeaders}, State),
     {reply, {ok, NewRequest#request.id}, State};
 
-handle_request(Request, State = #state{options = Options}) ->
+%% Simple socket options handling (ERL-441).
+%%
+%% TODO: Refactor httpc to enable sending socket options in requests
+%%       using persistent connections. This workaround opens a new
+%%       connection for each request with non-empty socket_opts.
+handle_request(Request0 = #request{socket_opts = SocketOpts},
+               State0 = #state{options = Options0})
+  when is_list(SocketOpts) andalso length(SocketOpts) > 0 ->
+    Request = handle_cookies(generate_request_id(Request0), State0),
+    Options = convert_options(SocketOpts, Options0),
+    State = State0#state{options = Options},
+    Headers =
+	(Request#request.headers)#http_request_h{connection
+						    = "close"},
+    %% Reset socket_opts to avoid setopts failure.
+    start_handler(Request#request{headers = Headers, socket_opts = []}, State),
+    %% Do not change the state
+    {reply, {ok, Request#request.id}, State0};
 
+handle_request(Request, State = #state{options = Options}) ->
     NewRequest = handle_cookies(generate_request_id(Request), State),
     SessionType = session_type(Options),
     case select_session(Request#request.method,
@@ -775,6 +793,18 @@ handle_request(Request, State = #state{options = Options}) ->
     {reply, {ok, NewRequest#request.id}, State}.
 
 
+%% Convert Request options to State options
+convert_options([], Options) ->
+    Options;
+convert_options([{ipfamily, Value}|T], Options) ->
+    convert_options(T, Options#options{ipfamily = Value});
+convert_options([{ip, Value}|T], Options) ->
+    convert_options(T, Options#options{ip = Value});
+convert_options([{port, Value}|T], Options) ->
+    convert_options(T, Options#options{port = Value});
+convert_options([Option|T], Options = #options{socket_opts = SocketOpts}) ->
+    convert_options(T, Options#options{socket_opts = SocketOpts ++ [Option]}).
+
 start_handler(#request{id   = Id, 
 		       from = From} = Request, 
 	      #state{profile_name = ProfileName, 
-- 
2.16.3

openSUSE Build Service is sponsored by