From 3fc01c48878ee487b872551d9ac5898fc2031086 Mon Sep 17 00:00:00 2001
From: Rob Ede <robjtede@icloud.com>
Date: Sat, 11 Mar 2023 22:17:52 +0000
Subject: [PATCH] refactor server binding

---
 actix-web/src/server.rs       | 67 +++++++++++++++++++----------------
 actix-web/src/types/either.rs |  6 ++--
 2 files changed, 39 insertions(+), 34 deletions(-)

diff --git a/actix-web/src/server.rs b/actix-web/src/server.rs
index c87fea7f..1fa279a6 100644
--- a/actix-web/src/server.rs
+++ b/actix-web/src/server.rs
@@ -338,7 +338,7 @@ where
     /// # ; Ok(()) }
     /// ```
     pub fn bind<A: net::ToSocketAddrs>(mut self, addrs: A) -> io::Result<Self> {
-        let sockets = self.bind2(addrs)?;
+        let sockets = bind_addrs(addrs, self.backlog)?;
 
         for lst in sockets {
             self = self.listen(lst)?;
@@ -347,33 +347,6 @@ where
         Ok(self)
     }
 
-    fn bind2<A: net::ToSocketAddrs>(&self, addrs: A) -> io::Result<Vec<net::TcpListener>> {
-        let mut err = None;
-        let mut success = false;
-        let mut sockets = Vec::new();
-
-        for addr in addrs.to_socket_addrs()? {
-            match create_tcp_listener(addr, self.backlog) {
-                Ok(lst) => {
-                    success = true;
-                    sockets.push(lst);
-                }
-                Err(e) => err = Some(e),
-            }
-        }
-
-        if success {
-            Ok(sockets)
-        } else if let Some(e) = err.take() {
-            Err(e)
-        } else {
-            Err(io::Error::new(
-                io::ErrorKind::Other,
-                "Can not bind to address.",
-            ))
-        }
-    }
-
     /// Resolves socket address(es) and binds server to created listener(s) for TLS connections
     /// using Rustls.
     ///
@@ -386,7 +359,7 @@ where
         addrs: A,
         config: RustlsServerConfig,
     ) -> io::Result<Self> {
-        let sockets = self.bind2(addrs)?;
+        let sockets = bind_addrs(addrs, self.backlog)?;
         for lst in sockets {
             self = self.listen_rustls_inner(lst, config.clone())?;
         }
@@ -404,7 +377,7 @@ where
     where
         A: net::ToSocketAddrs,
     {
-        let sockets = self.bind2(addrs)?;
+        let sockets = bind_addrs(addrs, self.backlog)?;
         let acceptor = openssl_acceptor(builder)?;
 
         for lst in sockets {
@@ -719,6 +692,38 @@ where
     }
 }
 
+/// Bind TCP listeners to socket addresses resolved from `addrs` with options.
+fn bind_addrs(
+    addrs: impl net::ToSocketAddrs,
+    backlog: u32,
+) -> io::Result<Vec<net::TcpListener>> {
+    let mut err = None;
+    let mut success = false;
+    let mut sockets = Vec::new();
+
+    for addr in addrs.to_socket_addrs()? {
+        match create_tcp_listener(addr, backlog) {
+            Ok(lst) => {
+                success = true;
+                sockets.push(lst);
+            }
+            Err(e) => err = Some(e),
+        }
+    }
+
+    if success {
+        Ok(sockets)
+    } else if let Some(err) = err.take() {
+        Err(err)
+    } else {
+        Err(io::Error::new(
+            io::ErrorKind::Other,
+            "Can not bind to address.",
+        ))
+    }
+}
+
+/// Creates a TCP listener from socket address and options.
 fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::TcpListener> {
     use socket2::{Domain, Protocol, Socket, Type};
     let domain = Domain::for_address(addr);
@@ -731,7 +736,7 @@ fn create_tcp_listener(addr: net::SocketAddr, backlog: u32) -> io::Result<net::T
     Ok(net::TcpListener::from(socket))
 }
 
-/// Configure `SslAcceptorBuilder` with custom server flags.
+/// Configures OpenSSL acceptor `builder` with ALPN protocols.
 #[cfg(feature = "openssl")]
 fn openssl_acceptor(mut builder: SslAcceptorBuilder) -> io::Result<SslAcceptor> {
     builder.set_alpn_select_callback(|_, protocols| {
diff --git a/actix-web/src/types/either.rs b/actix-web/src/types/either.rs
index 119dd0d6..df93fb5e 100644
--- a/actix-web/src/types/either.rs
+++ b/actix-web/src/types/either.rs
@@ -304,7 +304,7 @@ mod tests {
     #[actix_rt::test]
     async fn test_either_extract_first_try() {
         let (req, mut pl) = TestRequest::default()
-            .set_form(&TestForm {
+            .set_form(TestForm {
                 hello: "world".to_owned(),
             })
             .to_http_parts();
@@ -320,7 +320,7 @@ mod tests {
     #[actix_rt::test]
     async fn test_either_extract_fallback() {
         let (req, mut pl) = TestRequest::default()
-            .set_json(&TestForm {
+            .set_json(TestForm {
                 hello: "world".to_owned(),
             })
             .to_http_parts();
@@ -351,7 +351,7 @@ mod tests {
     #[actix_rt::test]
     async fn test_either_extract_recursive_fallback_inner() {
         let (req, mut pl) = TestRequest::default()
-            .set_json(&TestForm {
+            .set_json(TestForm {
                 hello: "world".to_owned(),
             })
             .to_http_parts();