From b67f49284e5b41fce17f00c21d54f2fb880d3ea6 Mon Sep 17 00:00:00 2001
From: Harry Barber <106155934+hlbarber@users.noreply.github.com>
Date: Wed, 30 Nov 2022 13:01:43 +0000
Subject: [PATCH] Restore `into_make_service_with_connect_info` module (#2039)

---
 .../generators/ServerServiceGeneratorV2.kt    |   4 +-
 .../src/request/connect_info.rs               | 140 ++----------------
 .../into_make_service_with_connect_info.rs    | 135 +++++++++++++++++
 .../aws-smithy-http-server/src/routing/mod.rs |   8 +-
 4 files changed, 155 insertions(+), 132 deletions(-)
 create mode 100644 rust-runtime/aws-smithy-http-server/src/routing/into_make_service_with_connect_info.rs

diff --git a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt
index ca782f4da6..738c14d8ce 100644
--- a/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt
+++ b/codegen-server/src/main/kotlin/software/amazon/smithy/rust/codegen/server/smithy/generators/ServerServiceGeneratorV2.kt
@@ -378,8 +378,8 @@ class ServerServiceGeneratorV2(
                 }
 
                 /// Converts [`$serviceName`] into a [`MakeService`](tower::make::MakeService) with [`ConnectInfo`](#{SmithyHttpServer}::request::connect_info::ConnectInfo).
-                pub fn into_make_service_with_connect_info<C>(self) -> #{SmithyHttpServer}::request::connect_info::IntoMakeServiceWithConnectInfo<Self, C> {
-                    #{SmithyHttpServer}::request::connect_info::IntoMakeServiceWithConnectInfo::new(self)
+                pub fn into_make_service_with_connect_info<C>(self) -> #{SmithyHttpServer}::routing::IntoMakeServiceWithConnectInfo<Self, C> {
+                    #{SmithyHttpServer}::routing::IntoMakeServiceWithConnectInfo::new(self)
                 }
 
                 /// Applies a [`Layer`](#{Tower}::Layer) uniformly to all routes.
diff --git a/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs b/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs
index fd66475fc9..71b744ef5b 100644
--- a/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs
+++ b/rust-runtime/aws-smithy-http-server/src/request/connect_info.rs
@@ -3,143 +3,25 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-// This code was copied and then modified from Tokio's Axum.
-
-/* Copyright (c) 2021 Tower Contributors
- *
- * Permission is hereby granted, free of charge, to any
- * person obtaining a copy of this software and associated
- * documentation files (the "Software"), to deal in the
- * Software without restriction, including without
- * limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of
- * the Software, and to permit persons to whom the Software
- * is furnished to do so, subject to the following
- * conditions:
- *
- * The above copyright notice and this permission notice
- * shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
- * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
- * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
- * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-//! Extractor for getting connection information from a client.
-
-use std::{
-    convert::Infallible,
-    fmt,
-    future::ready,
-    marker::PhantomData,
-    net::SocketAddr,
-    task::{Context, Poll},
-};
+//! The [`ConnectInfo`] struct is included in [`http::Request`]s when
+//! [`IntoMakeServiceWithConnectInfo`](crate::routing::IntoMakeServiceWithConnectInfo) is used. [`ConnectInfo`]'s
+//! [`FromParts`] implementation allows it to be extracted from the [`http::Request`].
+//!
+//! The [`pokemon-service-connect-info.rs`](https://github.com/awslabs/smithy-rs/blob/main/rust-runtime/aws-smithy-http-server/examples/pokemon-service/src/bin/pokemon-service-connect-info.rs)
+//! example illustrates the use of [`IntoMakeServiceWithConnectInfo`](crate::routing::IntoMakeServiceWithConnectInfo)
+//! and [`ConnectInfo`] with a service builder.
 
 use http::request::Parts;
-use hyper::server::conn::AddrStream;
-use tower::{Layer, Service};
-use tower_http::add_extension::{AddExtension, AddExtensionLayer};
-
-use crate::{request::FromParts, Extension};
-
-/// A [`MakeService`] used to insert [`ConnectInfo<T>`] into [`http::Request`]s.
-///
-/// The `T` must be derivable from the underlying IO resource using the [`Connected`] trait.
-///
-/// [`MakeService`]: tower::make::MakeService
-pub struct IntoMakeServiceWithConnectInfo<S, C> {
-    inner: S,
-    _connect_info: PhantomData<fn() -> C>,
-}
-
-impl<S, C> IntoMakeServiceWithConnectInfo<S, C> {
-    pub fn new(svc: S) -> Self {
-        Self {
-            inner: svc,
-            _connect_info: PhantomData,
-        }
-    }
-}
-
-impl<S, C> fmt::Debug for IntoMakeServiceWithConnectInfo<S, C>
-where
-    S: fmt::Debug,
-{
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("IntoMakeServiceWithConnectInfo")
-            .field("inner", &self.inner)
-            .finish()
-    }
-}
-
-impl<S, C> Clone for IntoMakeServiceWithConnectInfo<S, C>
-where
-    S: Clone,
-{
-    fn clone(&self) -> Self {
-        Self {
-            inner: self.inner.clone(),
-            _connect_info: PhantomData,
-        }
-    }
-}
-
-/// Trait that connected IO resources implement and use to produce information
-/// about the connection.
-///
-/// The goal for this trait is to allow users to implement custom IO types that
-/// can still provide the same connection metadata.
-pub trait Connected<T>: Clone {
-    /// Create type holding information about the connection.
-    fn connect_info(target: T) -> Self;
-}
-
-impl Connected<&AddrStream> for SocketAddr {
-    fn connect_info(target: &AddrStream) -> Self {
-        target.remote_addr()
-    }
-}
 
-impl<S, C, T> Service<T> for IntoMakeServiceWithConnectInfo<S, C>
-where
-    S: Clone,
-    C: Connected<T>,
-{
-    type Response = AddExtension<S, ConnectInfo<C>>;
-    type Error = Infallible;
-    type Future = ResponseFuture<S, C>;
-
-    #[inline]
-    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
-        Poll::Ready(Ok(()))
-    }
+use crate::Extension;
 
-    fn call(&mut self, target: T) -> Self::Future {
-        let connect_info = ConnectInfo(C::connect_info(target));
-        let svc = AddExtensionLayer::new(connect_info).layer(self.inner.clone());
-        ResponseFuture::new(ready(Ok(svc)))
-    }
-}
-
-opaque_future! {
-    /// Response future for [`IntoMakeServiceWithConnectInfo`].
-    pub type ResponseFuture<S, C> =
-        std::future::Ready<Result<AddExtension<S, ConnectInfo<C>>, Infallible>>;
-}
+use super::FromParts;
 
 /// Extractor for getting connection information produced by a `Connected`.
 ///
 /// Note this extractor requires the existence of [`Extension<ConnectInfo<T>>`] in the [`http::Extensions`]. This is
-/// automatically inserted by the [`IntoMakeServiceWithConnectInfo`] middleware, which can be applied using the
-/// `into_make_service_with_connect_info` method on your generated service.
+/// automatically inserted by the [`IntoMakeServiceWithConnectInfo`](crate::routing::IntoMakeServiceWithConnectInfo)
+/// middleware, which can be applied using the `into_make_service_with_connect_info` method on your generated service.
 #[derive(Clone, Debug)]
 pub struct ConnectInfo<T>(pub T);
 
diff --git a/rust-runtime/aws-smithy-http-server/src/routing/into_make_service_with_connect_info.rs b/rust-runtime/aws-smithy-http-server/src/routing/into_make_service_with_connect_info.rs
new file mode 100644
index 0000000000..3a43dc9e18
--- /dev/null
+++ b/rust-runtime/aws-smithy-http-server/src/routing/into_make_service_with_connect_info.rs
@@ -0,0 +1,135 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// This code was copied and then modified from Tokio's Axum.
+
+/* Copyright (c) 2021 Tower Contributors
+ *
+ * Permission is hereby granted, free of charge, to any
+ * person obtaining a copy of this software and associated
+ * documentation files (the "Software"), to deal in the
+ * Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software
+ * is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice
+ * shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+ * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+//! The [`IntoMakeServiceWithConnectInfo`] is a service factory which adjoins [`ConnectInfo`] to the requests.
+
+use std::{
+    convert::Infallible,
+    fmt,
+    future::ready,
+    marker::PhantomData,
+    net::SocketAddr,
+    task::{Context, Poll},
+};
+
+use hyper::server::conn::AddrStream;
+use tower::{Layer, Service};
+use tower_http::add_extension::{AddExtension, AddExtensionLayer};
+
+use crate::request::connect_info::ConnectInfo;
+
+/// A [`MakeService`] used to insert [`ConnectInfo<T>`] into [`http::Request`]s.
+///
+/// The `T` must be derivable from the underlying IO resource using the [`Connected`] trait.
+///
+/// [`MakeService`]: tower::make::MakeService
+pub struct IntoMakeServiceWithConnectInfo<S, C> {
+    inner: S,
+    _connect_info: PhantomData<fn() -> C>,
+}
+
+impl<S, C> IntoMakeServiceWithConnectInfo<S, C> {
+    pub fn new(svc: S) -> Self {
+        Self {
+            inner: svc,
+            _connect_info: PhantomData,
+        }
+    }
+}
+
+impl<S, C> fmt::Debug for IntoMakeServiceWithConnectInfo<S, C>
+where
+    S: fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("IntoMakeServiceWithConnectInfo")
+            .field("inner", &self.inner)
+            .finish()
+    }
+}
+
+impl<S, C> Clone for IntoMakeServiceWithConnectInfo<S, C>
+where
+    S: Clone,
+{
+    fn clone(&self) -> Self {
+        Self {
+            inner: self.inner.clone(),
+            _connect_info: PhantomData,
+        }
+    }
+}
+
+/// Trait that connected IO resources implement and use to produce information
+/// about the connection.
+///
+/// The goal for this trait is to allow users to implement custom IO types that
+/// can still provide the same connection metadata.
+pub trait Connected<T>: Clone {
+    /// Create type holding information about the connection.
+    fn connect_info(target: T) -> Self;
+}
+
+impl Connected<&AddrStream> for SocketAddr {
+    fn connect_info(target: &AddrStream) -> Self {
+        target.remote_addr()
+    }
+}
+
+impl<S, C, T> Service<T> for IntoMakeServiceWithConnectInfo<S, C>
+where
+    S: Clone,
+    C: Connected<T>,
+{
+    type Response = AddExtension<S, ConnectInfo<C>>;
+    type Error = Infallible;
+    type Future = ResponseFuture<S, C>;
+
+    #[inline]
+    fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
+        Poll::Ready(Ok(()))
+    }
+
+    fn call(&mut self, target: T) -> Self::Future {
+        let connect_info = ConnectInfo(C::connect_info(target));
+        let svc = AddExtensionLayer::new(connect_info).layer(self.inner.clone());
+        ResponseFuture::new(ready(Ok(svc)))
+    }
+}
+
+opaque_future! {
+    /// Response future for [`IntoMakeServiceWithConnectInfo`].
+    pub type ResponseFuture<S, C> =
+        std::future::Ready<Result<AddExtension<S, ConnectInfo<C>>, Infallible>>;
+}
diff --git a/rust-runtime/aws-smithy-http-server/src/routing/mod.rs b/rust-runtime/aws-smithy-http-server/src/routing/mod.rs
index 3872c3a90b..d007f99fcf 100644
--- a/rust-runtime/aws-smithy-http-server/src/routing/mod.rs
+++ b/rust-runtime/aws-smithy-http-server/src/routing/mod.rs
@@ -29,6 +29,7 @@ use tower_http::map_response_body::MapResponseBodyLayer;
 
 mod future;
 mod into_make_service;
+mod into_make_service_with_connect_info;
 #[cfg(feature = "aws-lambda")]
 #[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))]
 mod lambda_handler;
@@ -43,7 +44,12 @@ pub(crate) mod tiny_map;
 #[cfg(feature = "aws-lambda")]
 #[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))]
 pub use self::lambda_handler::LambdaHandler;
-pub use self::{future::RouterFuture, into_make_service::IntoMakeService, route::Route};
+pub use self::{
+    future::RouterFuture,
+    into_make_service::IntoMakeService,
+    into_make_service_with_connect_info::{Connected, IntoMakeServiceWithConnectInfo},
+    route::Route,
+};
 
 /// The router is a [`tower::Service`] that routes incoming requests to other `Service`s
 /// based on the request's URI and HTTP method or on some specific header setting the target operation.