From 8ea673c9e1b5485e274a4e0adf28f33b71350fb9 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Thu, 17 Nov 2022 15:13:17 +0100 Subject: [PATCH 1/5] Multiple FromParts in handlers Handlers can have up to 8 extensions: ``` pub async fn handler( input: input::Input, ext0: Extension<...>, ext1: Extension<...>, ext2: Extension<...>, ext3: Extension<...>, ext4: Extension<...>, ext5: Extension<...>, ext6: Extension<...>, ext7: Extension<...>, ) -> Result { ... } ``` Signed-off-by: Daniele Ahmed Co-authored-by: Harry Barber --- .../src/operation/handler.rs | 42 +++++++++++------ .../aws-smithy-http-server/src/rejection.rs | 47 +++++++++++++------ .../aws-smithy-http-server/src/request.rs | 44 ++++++++++------- 3 files changed, 88 insertions(+), 45 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs index 4f0c8255e9..c1bdb516fe 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs @@ -62,7 +62,6 @@ where } } -// fn(Input, Ext0) -> Output impl Handler for F where Op: OperationShape, @@ -77,21 +76,36 @@ where } } -// fn(Input, Ext0, Ext1) -> Output -impl Handler for F -where - Op: OperationShape, - F: Fn(Op::Input, Ext0, Ext1) -> Fut, - Fut: Future, - Fut::Output: IntoResult, -{ - type Future = Map Result>; - - fn call(&mut self, input: Op::Input, exts: (Ext0, Ext1)) -> Self::Future { - (self)(input, exts.0, exts.1).map(IntoResult::into_result) - } +// fn(Input, Ext_i) -> Output +macro_rules! impl_handler { + ($($var:ident),+) => ( + impl Handler for F + where + Op: OperationShape, + F: Fn(Op::Input, $($var,)*) -> Fut, + Fut: Future, + Fut::Output: IntoResult, + { + type Future = Map Result>; + + fn call(&mut self, input: Op::Input, exts: ($($var,)*)) -> Self::Future { + #[allow(non_snake_case)] + let ($($var,)*) = exts; + (self)(input, $($var,)*).map(IntoResult::into_result) + } + } + ) } +impl_handler!(Exts0, Exts1); +impl_handler!(Exts0, Exts1, Exts2); +impl_handler!(Exts0, Exts1, Exts2, Exts3); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7); +impl_handler!(Exts0, Exts1, Exts2, Exts3, Exts4, Exts5, Exts6, Exts7, Exts8); + /// An extension trait for [`Handler`]. pub trait HandlerExt: Handler where diff --git a/rust-runtime/aws-smithy-http-server/src/rejection.rs b/rust-runtime/aws-smithy-http-server/src/rejection.rs index c75b3e466c..513f1ed4fd 100644 --- a/rust-runtime/aws-smithy-http-server/src/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/rejection.rs @@ -264,21 +264,38 @@ convert_to_request_rejection!(hyper::Error, HttpBody); // Required in order to accept Lambda HTTP requests using `Router`. convert_to_request_rejection!(lambda_http::Error, HttpBody); -/// A sum type rejection, implementing [`IntoResponse`] when both variants do. -pub enum EitherRejection { - Left(Left), - Right(Right), -} +macro_rules! any_rejection { + ($name:ident, $($var:ident),+) => ( + pub enum $name<$($var),*> { + $($var ($var),)* + } -impl IntoResponse

for EitherRejection -where - L: IntoResponse

, - R: IntoResponse

, -{ - fn into_response(self) -> http::Response { - match self { - EitherRejection::Left(left) => left.into_response(), - EitherRejection::Right(right) => right.into_response(), + impl IntoResponse

for $name<$($var),*> + where + $($var: IntoResponse

,)* + { + #[allow(non_snake_case)] + fn into_response(self) -> http::Response { + match self { + $($name::$var ($var) => $var.into_response(),)* + } + } } - } + ) +} + +pub mod any_rejections { + //! This module hosts enums, up to size 8, which implement [`IntoResponse`] when their variants implement + //! [`IntoResponse`]. + + use super::IntoResponse; + + // any_rejection!(One, A); + any_rejection!(Two, A, B); + any_rejection!(Three, A, B, C); + any_rejection!(Four, A, B, C, D); + any_rejection!(Five, A, B, C, D, E); + any_rejection!(Six, A, B, C, D, E, F); + any_rejection!(Seven, A, B, C, D, E, F, G); + any_rejection!(Eight, A, B, C, D, E, F, G, H); } diff --git a/rust-runtime/aws-smithy-http-server/src/request.rs b/rust-runtime/aws-smithy-http-server/src/request.rs index 36b880e228..9faf1ea58d 100644 --- a/rust-runtime/aws-smithy-http-server/src/request.rs +++ b/rust-runtime/aws-smithy-http-server/src/request.rs @@ -43,7 +43,7 @@ use futures_util::{ }; use http::{request::Parts, Extensions, HeaderMap, Request, Uri}; -use crate::{rejection::EitherRejection, response::IntoResponse}; +use crate::{rejection::any_rejections, response::IntoResponse}; #[doc(hidden)] #[derive(Debug)] @@ -139,20 +139,32 @@ where } } -impl FromParts

for (T1, T2) -where - T1: FromParts

, - T2: FromParts

, -{ - type Rejection = EitherRejection; - - fn from_parts(parts: &mut Parts) -> Result { - let t1 = T1::from_parts(parts).map_err(EitherRejection::Left)?; - let t2 = T2::from_parts(parts).map_err(EitherRejection::Right)?; - Ok((t1, t2)) - } +macro_rules! impl_from_parts { + ($error_name:ident, $($var:ident),+) => ( + impl FromParts

for ($($var),*) + where + $($var: FromParts

,)* + { + type Rejection = any_rejections::$error_name<$($var::Rejection),*>; + + fn from_parts(parts: &mut Parts) -> Result { + let tuple = ( + $($var::from_parts(parts).map_err(any_rejections::$error_name::$var)?,)* + ); + Ok(tuple) + } + } + ) } +impl_from_parts!(Two, A, B); +impl_from_parts!(Three, A, B, C); +impl_from_parts!(Four, A, B, C, D); +impl_from_parts!(Five, A, B, C, D, E); +impl_from_parts!(Six, A, B, C, D, E, F); +impl_from_parts!(Seven, A, B, C, D, E, F, G); +impl_from_parts!(Eight, A, B, C, D, E, F, G, H); + /// Provides a protocol aware extraction from a [`Request`]. This consumes the /// [`Request`], in contrast to [`FromParts`]. pub trait FromRequest: Sized { @@ -180,14 +192,14 @@ where T1: FromRequest, T2: FromParts

, { - type Rejection = EitherRejection; + type Rejection = any_rejections::Two; type Future = TryJoin Self::Rejection>, Ready>>; fn from_request(request: Request) -> Self::Future { let (mut parts, body) = request.into_parts(); - let t2_result = T2::from_parts(&mut parts).map_err(EitherRejection::Right); + let t2_result = T2::from_parts(&mut parts).map_err(any_rejections::Two::B); try_join( - T1::from_request(Request::from_parts(parts, body)).map_err(EitherRejection::Left), + T1::from_request(Request::from_parts(parts, body)).map_err(any_rejections::Two::A), ready(t2_result), ) } From ced56b7511feb936d7fc565086cc95655119f0c2 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 18 Nov 2022 11:43:42 +0100 Subject: [PATCH 2/5] Address comments Signed-off-by: Daniele Ahmed --- .../src/operation/handler.rs | 17 +------- .../aws-smithy-http-server/src/rejection.rs | 40 +++++++++---------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs index c1bdb516fe..fc3191f8a0 100644 --- a/rust-runtime/aws-smithy-http-server/src/operation/handler.rs +++ b/rust-runtime/aws-smithy-http-server/src/operation/handler.rs @@ -62,24 +62,10 @@ where } } -impl Handler for F -where - Op: OperationShape, - F: Fn(Op::Input, Ext0) -> Fut, - Fut: Future, - Fut::Output: IntoResult, -{ - type Future = Map Result>; - - fn call(&mut self, input: Op::Input, exts: (Ext0,)) -> Self::Future { - (self)(input, exts.0).map(IntoResult::into_result) - } -} - // fn(Input, Ext_i) -> Output macro_rules! impl_handler { ($($var:ident),+) => ( - impl Handler for F + impl Handler for F where Op: OperationShape, F: Fn(Op::Input, $($var,)*) -> Fut, @@ -97,6 +83,7 @@ macro_rules! impl_handler { ) } +impl_handler!(Exts0); impl_handler!(Exts0, Exts1); impl_handler!(Exts0, Exts1, Exts2); impl_handler!(Exts0, Exts1, Exts2, Exts3); diff --git a/rust-runtime/aws-smithy-http-server/src/rejection.rs b/rust-runtime/aws-smithy-http-server/src/rejection.rs index 513f1ed4fd..4ad682e6b8 100644 --- a/rust-runtime/aws-smithy-http-server/src/rejection.rs +++ b/rust-runtime/aws-smithy-http-server/src/rejection.rs @@ -264,32 +264,32 @@ convert_to_request_rejection!(hyper::Error, HttpBody); // Required in order to accept Lambda HTTP requests using `Router`. convert_to_request_rejection!(lambda_http::Error, HttpBody); -macro_rules! any_rejection { - ($name:ident, $($var:ident),+) => ( - pub enum $name<$($var),*> { - $($var ($var),)* - } - - impl IntoResponse

for $name<$($var),*> - where - $($var: IntoResponse

,)* - { - #[allow(non_snake_case)] - fn into_response(self) -> http::Response { - match self { - $($name::$var ($var) => $var.into_response(),)* - } - } - } - ) -} - pub mod any_rejections { //! This module hosts enums, up to size 8, which implement [`IntoResponse`] when their variants implement //! [`IntoResponse`]. use super::IntoResponse; + macro_rules! any_rejection { + ($name:ident, $($var:ident),+) => ( + pub enum $name<$($var),*> { + $($var ($var),)* + } + + impl IntoResponse

for $name<$($var),*> + where + $($var: IntoResponse

,)* + { + #[allow(non_snake_case)] + fn into_response(self) -> http::Response { + match self { + $($name::$var ($var) => $var.into_response(),)* + } + } + } + ) + } + // any_rejection!(One, A); any_rejection!(Two, A, B); any_rejection!(Three, A, B, C); From 1f4206537a91b3dbd4b4807a18cec71728d5ed41 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 18 Nov 2022 11:49:51 +0100 Subject: [PATCH 3/5] Add CHANGELOG entry Signed-off-by: Daniele Ahmed --- CHANGELOG.next.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index ab05df0124..f4da2fd439 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -431,3 +431,9 @@ message = "`Endpoint::immutable` now takes `impl AsRef` instead of `Uri`. F references = ["smithy-rs#1984", "smithy-rs#1496"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" } author = "jdisanti" + +[[smithy-rs]] +message = "Business logic handlers can have up to 8 extensions in input" +references = ["smithy-rs#1999"] +meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" } +author = "82marbag" From 91320a784376f621e5b5718605478ead12ca5e80 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 18 Nov 2022 10:57:46 +0000 Subject: [PATCH 4/5] Update CHANGELOG.next.toml Co-authored-by: Luca Palmieri <20745048+LukeMathWalker@users.noreply.github.com> --- CHANGELOG.next.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index f4da2fd439..664c608fb8 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -433,7 +433,7 @@ meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" } author = "jdisanti" [[smithy-rs]] -message = "Business logic handlers can have up to 8 extensions in input" +message = "Operation handlers can now have up to 8 extensions as input parameters. They were previously limited to 1 extension input parameter." references = ["smithy-rs#1999"] meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" } author = "82marbag" From 4fdc1d15b9744a5a318ed5f0666c2adb0a827230 Mon Sep 17 00:00:00 2001 From: 82marbag <69267416+82marbag@users.noreply.github.com> Date: Fri, 18 Nov 2022 12:45:11 +0100 Subject: [PATCH 5/5] Revert CHANGELOG entry Signed-off-by: Daniele Ahmed --- CHANGELOG.next.toml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/CHANGELOG.next.toml b/CHANGELOG.next.toml index 664c608fb8..ab05df0124 100644 --- a/CHANGELOG.next.toml +++ b/CHANGELOG.next.toml @@ -431,9 +431,3 @@ message = "`Endpoint::immutable` now takes `impl AsRef` instead of `Uri`. F references = ["smithy-rs#1984", "smithy-rs#1496"] meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "client" } author = "jdisanti" - -[[smithy-rs]] -message = "Operation handlers can now have up to 8 extensions as input parameters. They were previously limited to 1 extension input parameter." -references = ["smithy-rs#1999"] -meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "server" } -author = "82marbag"