From 0698255084c76bc1fdff5a4da3714f52afd8d3e4 Mon Sep 17 00:00:00 2001 From: Arpita-Jaiswal Date: Tue, 9 Jul 2024 19:55:44 +0530 Subject: [PATCH 1/3] Added request raw body handler --- examples/004-ft-stripe/Cargo.lock | 2 +- ft-derive/src/lib.rs | 8 + ft-sdk/src/from_request/headers.rs | 7 + ft-sdk/src/from_request/mod.rs | 14 + ft-sdk/src/from_request/raw_bytes_handler.rs | 312 +++++++++++++++++++ ft-sdk/src/from_request/text.rs | 7 + ft-sdk/src/lib.rs | 4 +- 7 files changed, 351 insertions(+), 3 deletions(-) create mode 100644 ft-sdk/src/from_request/raw_bytes_handler.rs create mode 100644 ft-sdk/src/from_request/text.rs diff --git a/examples/004-ft-stripe/Cargo.lock b/examples/004-ft-stripe/Cargo.lock index b9856e6..b8443ba 100644 --- a/examples/004-ft-stripe/Cargo.lock +++ b/examples/004-ft-stripe/Cargo.lock @@ -230,7 +230,7 @@ dependencies = [ [[package]] name = "ft-sdk" -version = "0.1.14" +version = "0.1.15" dependencies = [ "anyhow", "bytes", diff --git a/ft-derive/src/lib.rs b/ft-derive/src/lib.rs index d9d48fd..5a0d8de 100644 --- a/ft-derive/src/lib.rs +++ b/ft-derive/src/lib.rs @@ -8,6 +8,14 @@ pub fn processor( handle(item, "processor", "handler") } +#[proc_macro_attribute] +pub fn raw_processor( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + handle(item, "processor", "raw_bytes_handler") +} + #[proc_macro_attribute] pub fn wrapped_processor( _attr: proc_macro::TokenStream, diff --git a/ft-sdk/src/from_request/headers.rs b/ft-sdk/src/from_request/headers.rs index 7ca68a0..5b7bae6 100644 --- a/ft-sdk/src/from_request/headers.rs +++ b/ft-sdk/src/from_request/headers.rs @@ -3,3 +3,10 @@ impl ft_sdk::FromRequest for http::HeaderMap { Ok(req.headers().clone()) } } + + +impl ft_sdk::FromRawRequest for http::HeaderMap { + fn from_request(req: &http::Request) -> Result { + Ok(req.headers().clone()) + } +} diff --git a/ft-sdk/src/from_request/mod.rs b/ft-sdk/src/from_request/mod.rs index 4b8a5aa..ca7f551 100644 --- a/ft-sdk/src/from_request/mod.rs +++ b/ft-sdk/src/from_request/mod.rs @@ -16,8 +16,11 @@ mod query; #[cfg(feature = "field-extractors")] mod required; pub mod wrapped_processor; +mod text; +pub mod raw_bytes_handler; pub use form::Form; +pub use text::Text; pub use host::Host; pub use mountpoint::Mountpoint; pub use path::Path; @@ -28,6 +31,11 @@ pub trait FromRequest: Sized { fn from_request(req: &http::Request) -> Result; } + +pub trait FromRawRequest: Sized { + fn from_request(req: &http::Request) -> Result; +} + impl FromRequest for chrono::DateTime { fn from_request(_req: &http::Request) -> Result { Ok(ft_sdk::env::now()) @@ -40,6 +48,12 @@ impl FromRequest for ft_sdk::Connection { } } +impl FromRawRequest for ft_sdk::Connection { + fn from_request(_req: &http::Request) -> Result { + Ok(ft_sdk::default_connection()?) + } +} + // TODO: need better name pub trait WrappedFromRequest: FromRequest { fn wrap(self, output: serde_json::Value) -> Result; diff --git a/ft-sdk/src/from_request/raw_bytes_handler.rs b/ft-sdk/src/from_request/raw_bytes_handler.rs new file mode 100644 index 0000000..d909d37 --- /dev/null +++ b/ft-sdk/src/from_request/raw_bytes_handler.rs @@ -0,0 +1,312 @@ + +// https://github.com/alexpusch/rust-magic-patterns/blob/master/axum-style-magic-function-param/Readme.md +// https://joshchoo.com/writing/how-actix-web-app-state-and-data-extractor-works +pub fn handle, ft_sdk::Error>>, H: RawHandler>( + h: H, +) { + let req = ft_sys::http::current_request(); + let resp = h.call(&req).and_then(Into::into).unwrap_or_else(|e| { + ft_sdk::println!("Error: {:?}", e); + ft_sdk::error::handle_error(e) + }); + ft_sdk::http::send_response(resp); +} + +pub trait RawHandler: Sized { + fn call(self, req: &http::Request) -> Result; +} + +impl RawHandler<(), O> for F +where + F: Fn() -> Result, +{ + fn call(self, _req: &http::Request) -> Result { + (self)() + } +} + +impl RawHandler for F +where + F: Fn(T) -> Result, + T: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + (self)(T::from_request(req)?) + } +} + +impl RawHandler<(T1, T2), O> for F +where + F: Fn(T1, T2) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)(T1::from_request(req)?, T2::from_request(req)?) + } +} + +impl RawHandler<(T1, T2, T3), O> for F +where + F: Fn(T1, T2, T3) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4), O> for F +where + F: Fn(T1, T2, T3, T4) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4, T5), O> for F +where + F: Fn(T1, T2, T3, T4, T5) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4, T5, T6), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4, T5, T6, T7), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4, T5, T6, T7, T8), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7, T8) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, + T8: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + T8::from_request(req)?, + ) + } +} + +impl RawHandler<(T1, T2, T3, T4, T5, T6, T7, T8, T9), O> + for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7, T8, T9) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, + T8: ft_sdk::FromRawRequest, + T9: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + T8::from_request(req)?, + T9::from_request(req)?, + ) + } +} + +impl + RawHandler<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, + T8: ft_sdk::FromRawRequest, + T9: ft_sdk::FromRawRequest, + T10: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + T8::from_request(req)?, + T9::from_request(req)?, + T10::from_request(req)?, + ) + } +} + +impl + RawHandler<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, + T8: ft_sdk::FromRawRequest, + T9: ft_sdk::FromRawRequest, + T10: ft_sdk::FromRawRequest, + T11: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + T8::from_request(req)?, + T9::from_request(req)?, + T10::from_request(req)?, + T11::from_request(req)?, + ) + } +} + +impl + RawHandler<(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12), O> for F +where + F: Fn(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) -> Result, + T1: ft_sdk::FromRawRequest, + T2: ft_sdk::FromRawRequest, + T3: ft_sdk::FromRawRequest, + T4: ft_sdk::FromRawRequest, + T5: ft_sdk::FromRawRequest, + T6: ft_sdk::FromRawRequest, + T7: ft_sdk::FromRawRequest, + T8: ft_sdk::FromRawRequest, + T9: ft_sdk::FromRawRequest, + T10: ft_sdk::FromRawRequest, + T11: ft_sdk::FromRawRequest, + T12: ft_sdk::FromRawRequest, +{ + fn call(self, req: &http::Request) -> Result { + // TODO: try to parse both t1 and t2 and return result for both together to clients + (self)( + T1::from_request(req)?, + T2::from_request(req)?, + T3::from_request(req)?, + T4::from_request(req)?, + T5::from_request(req)?, + T6::from_request(req)?, + T7::from_request(req)?, + T8::from_request(req)?, + T9::from_request(req)?, + T10::from_request(req)?, + T11::from_request(req)?, + T12::from_request(req)?, + ) + } +} diff --git a/ft-sdk/src/from_request/text.rs b/ft-sdk/src/from_request/text.rs new file mode 100644 index 0000000..6a989c2 --- /dev/null +++ b/ft-sdk/src/from_request/text.rs @@ -0,0 +1,7 @@ +pub struct Text(pub String); + +impl ft_sdk::FromRawRequest for Text { + fn from_request(req: &http::Request) -> Result { + Ok(Text(String::from_utf8(req.body().as_ref().to_vec())?)) + } +} diff --git a/ft-sdk/src/lib.rs b/ft-sdk/src/lib.rs index 83bf571..6e9963a 100644 --- a/ft-sdk/src/lib.rs +++ b/ft-sdk/src/lib.rs @@ -30,8 +30,8 @@ pub use email::{send_email, EmailError}; pub use error::{not_found_, server_error_, single_error, unauthorised_, SpecialError}; #[cfg(feature = "field-extractors")] pub use from_request::{Cookie, Hidden, Optional, Query, Required}; -pub use from_request::{Form, FromRequest, Host, Mountpoint, Path, WrappedFromRequest}; -pub use ft_derive::{data, form, processor, wrapped_processor}; +pub use from_request::{Form, Text, FromRequest, FromRawRequest, Host, Mountpoint, Path, WrappedFromRequest}; +pub use ft_derive::{data, form, processor, wrapped_processor, raw_processor}; #[cfg(feature = "postgres")] pub use ft_sys::PgConnection; #[cfg(feature = "sqlite")] From 55ff837592837e021571c5b83dd2aa3f39804b77 Mon Sep 17 00:00:00 2001 From: Arpita-Jaiswal Date: Wed, 10 Jul 2024 10:01:18 +0530 Subject: [PATCH 2/3] raw_data --- ft-derive/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ft-derive/src/lib.rs b/ft-derive/src/lib.rs index 5a0d8de..ff91aa5 100644 --- a/ft-derive/src/lib.rs +++ b/ft-derive/src/lib.rs @@ -9,11 +9,11 @@ pub fn processor( } #[proc_macro_attribute] -pub fn raw_processor( +pub fn raw_data( _attr: proc_macro::TokenStream, item: proc_macro::TokenStream, ) -> proc_macro::TokenStream { - handle(item, "processor", "raw_bytes_handler") + handle(item, "data", "raw_bytes_handler") } #[proc_macro_attribute] From 783339a87b4e82f563277cb89bd3f753290cbcf0 Mon Sep 17 00:00:00 2001 From: Arpita-Jaiswal Date: Wed, 10 Jul 2024 10:02:44 +0530 Subject: [PATCH 3/3] raw_data --- ft-sdk/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ft-sdk/src/lib.rs b/ft-sdk/src/lib.rs index 6e9963a..6fa5fa3 100644 --- a/ft-sdk/src/lib.rs +++ b/ft-sdk/src/lib.rs @@ -31,7 +31,7 @@ pub use error::{not_found_, server_error_, single_error, unauthorised_, SpecialE #[cfg(feature = "field-extractors")] pub use from_request::{Cookie, Hidden, Optional, Query, Required}; pub use from_request::{Form, Text, FromRequest, FromRawRequest, Host, Mountpoint, Path, WrappedFromRequest}; -pub use ft_derive::{data, form, processor, wrapped_processor, raw_processor}; +pub use ft_derive::{data, form, processor, wrapped_processor, raw_data}; #[cfg(feature = "postgres")] pub use ft_sys::PgConnection; #[cfg(feature = "sqlite")]