From bb70cc65e0b244d4d995a84a8ceaf140a6f820eb Mon Sep 17 00:00:00 2001 From: Jeff Baskin Date: Sat, 19 Apr 2025 07:57:16 -0400 Subject: [PATCH] Preparing to move session into an extractor. --- Cargo.lock | 82 +++++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 1 + src/client.rs | 42 ++++++++++++++------------ src/lib.rs | 21 +++++++++++-- src/main.rs | 38 +++++++++++++++++++++--- 5 files changed, 146 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f4bcec..1d86fbc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,7 +106,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.4.5", "bytes", "futures-util", "http", @@ -154,6 +154,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-extra" version = "0.9.6" @@ -161,7 +180,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum", - "axum-core", + "axum-core 0.4.5", "bytes", "cookie", "fastrand", @@ -228,9 +247,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" [[package]] name = "cc" -version = "1.2.18" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "shlex", ] @@ -257,9 +276,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.35" +version = "4.5.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8aa86934b44c19c50f87cc2790e19f54f7a67aedb64101c2e1a2e5ecfb73944" +checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04" dependencies = [ "clap_builder", "clap_derive", @@ -267,9 +286,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.35" +version = "4.5.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2414dbb2dd0695280da6ea9261e327479e9d37b0630f6b53ba2a11c60c679fd9" +checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5" dependencies = [ "anstream", "anstyle", @@ -407,6 +426,17 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "futures-task" version = "0.3.31" @@ -420,9 +450,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-macro", "futures-task", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -608,9 +640,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "lock_api" @@ -677,6 +709,7 @@ dependencies = [ "rand", "tokio", "tower", + "tower-cookies", "uuid", ] @@ -785,9 +818,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -950,6 +983,15 @@ dependencies = [ "libc", ] +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + [[package]] name = "smallvec" version = "1.15.0" @@ -1077,6 +1119,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "tower-cookies" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151b5a3e3c45df17466454bb74e9ecedecc955269bdedbf4d150dfa393b55a36" +dependencies = [ + "axum-core 0.5.2", + "cookie", + "futures-util", + "http", + "parking_lot", + "pin-project-lite", + "tower-layer", + "tower-service", +] + [[package]] name = "tower-layer" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index 959517b..2e251a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ chrono = { version = "0.4.40", features = ["now"] } clap = { version = "4.5.1", features = ["derive"] } rand = "0.8.5" tokio = { version = "1.36.0", features = ["full"] } +tower-cookies = "0.11.0" uuid = { version = "1.8.0", features = ["v4"] } [dev-dependencies] diff --git a/src/client.rs b/src/client.rs index a1aca5c..69467ce 100644 --- a/src/client.rs +++ b/src/client.rs @@ -107,7 +107,7 @@ mod replies { #[derive(Clone)] pub struct ClientRegistry { - registry: Arc>>>, + registry: Arc>>>, } impl ClientRegistry { @@ -119,7 +119,7 @@ impl ClientRegistry { fn get_id<'a>( gen: &mut impl Iterator, - data: &HashMap>, + data: &HashMap>, ) -> Uuid { let mut id = gen.next().unwrap(); while data.contains_key(&id) { @@ -128,7 +128,7 @@ impl ClientRegistry { id.clone() } - pub fn add(&mut self, tx: Sender) -> Uuid { + pub fn add(&mut self, tx: Sender) -> Uuid { let mut reg = self.registry.lock().unwrap(); let mut gen_id = GenID::new(); let id = ClientRegistry::get_id(&mut gen_id, ®); @@ -136,7 +136,7 @@ impl ClientRegistry { id } - fn send(&mut self, id: &Uuid, msg: Reply) { + fn send(&mut self, id: &Uuid, msg: Message) { let mut reg = self.registry.lock().unwrap(); let tx = reg.remove(id).unwrap(); tx.send(msg).unwrap(); @@ -165,15 +165,15 @@ mod clientregistries { fn send_from_client() { let mut reg = ClientRegistry::new(); let count = 10; - let mut rxs: HashMap> = HashMap::new(); + let mut rxs: HashMap> = HashMap::new(); for _ in 0..count { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let id = reg.add(tx); rxs.insert(id, rx); } assert_eq!(rxs.len(), count, "should have been {} receivers", count); for (id, rx) in rxs.iter() { - let msg = create_reply(); + let msg = Message::new(MsgType::Document); reg.send(id, msg); rx.recv_timeout(TIMEOUT).unwrap(); } @@ -184,7 +184,7 @@ mod clientregistries { #[test] fn prevent_duplicates() { let mut reg = ClientRegistry::new(); - let (tx, _rx) = channel::(); + let (tx, _rx) = channel::(); let existing = reg.add(tx); let expected = Uuid::new_v4(); let ids = [existing.clone(), expected.clone()]; @@ -208,12 +208,12 @@ impl ClientLink { } } - pub fn send(&mut self, req: Request) -> Receiver { + pub fn send(&mut self, mut req: Message) -> Receiver { let (tx, rx) = channel(); - let mut msg: Message = req.into(); + //let mut msg: Message = req.into(); let id = self.registry.add(tx); - msg.add_data("tx_id", id); - self.tx.send(msg).unwrap(); + req.add_data("tx_id", id); + self.tx.send(req).unwrap(); rx } } @@ -232,7 +232,7 @@ mod clientlinks { let mut registry = ClientRegistry::new(); let mut link = ClientLink::new(tx, registry.clone()); let req = Request::new(None); - let rx_client = link.send(req); + let rx_client = link.send(req.into()); let msg = rx.recv_timeout(TIMEOUT).unwrap(); match msg.get_msg_type() { MsgType::ClientRequest => {} @@ -241,7 +241,7 @@ mod clientlinks { match msg.get_data("tx_id") { Some(result) => { let id = result.to_uuid().unwrap(); - registry.send(&id, create_reply()); + registry.send(&id, msg.reply(MsgType::Document)); rx_client.recv().unwrap(); } None => unreachable!("should have had a seender id"), @@ -319,11 +319,13 @@ impl Client { fn document(&mut self, msg: Message) { let initial_msg = self.return_to.remove(&msg.get_id()).unwrap(); let tx_id = initial_msg.get_data("tx_id").unwrap().to_uuid().unwrap(); + /* let reply = Reply::new( initial_msg.get_data("sess_id").unwrap().to_uuid().unwrap(), msg.get_data("doc").unwrap().to_string(), - ); - self.registry.send(&tx_id, reply); + )s + */ + self.registry.send(&tx_id, initial_msg.reply(MsgType::Document)); } } @@ -335,6 +337,7 @@ mod clients { static TIMEOUT: Duration = Duration::from_millis(500); + /* #[test] fn start_client() { let sess_id1 = Uuid::new_v4(); @@ -348,7 +351,7 @@ mod clients { ); let mut link = Client::start(queue.clone()); let req = get_root_with_session(&sess_id1); - let reply_rx = link.send(req); + let reply_rx = link.send(req.into()); let send1 = rx.recv_timeout(TIMEOUT).unwrap(); match send1.get_msg_type() { MsgType::SessionValidate => {} @@ -376,7 +379,8 @@ mod clients { document.add_data("doc", doc.clone()); queue.send(document).unwrap(); let reply = reply_rx.recv_timeout(TIMEOUT).unwrap(); - assert_eq!(reply.get_session(), sess_id2); - assert_eq!(reply.get_content(), doc); + assert_eq!(reply.get_data("sess_id").unwrap().to_uuid().unwrap(), sess_id2); + assert_eq!(reply.get_data("doc").unwrap().to_string(), doc); } + */ } diff --git a/src/lib.rs b/src/lib.rs index c584347..eb7f28a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,8 +10,9 @@ use client::{Client, ClientLink, Reply, Request}; use clock::Clock; use document::Document; use field::Field; -use queue::Queue; +use queue::{Message, MsgType, Queue}; use session::Session; +use uuid::Uuid; #[derive(Clone)] pub struct MoreThanText { @@ -29,7 +30,21 @@ impl MoreThanText { } } - pub fn request(&mut self, session: Option) -> Reply + pub fn validate_session(&mut self, session: Option) -> Uuid + where + F: Into, + { + let mut msg = Message::new(MsgType::SessionValidate); + match session { + Some(id) => msg.add_data("sess_id", id.into()), + None => {}, + } + let rx = self.client_link.send(msg); + let reply = rx.recv().unwrap(); + reply.get_data("sess_id").unwrap().to_uuid().unwrap() + } + + pub fn request(&mut self, session: Option) -> Message where F: Into, { @@ -38,7 +53,7 @@ impl MoreThanText { None => None, }; let req = Request::new(sess); - let rx = self.client_link.send(req); + let rx = self.client_link.send(req.into()); rx.recv().unwrap() } } diff --git a/src/main.rs b/src/main.rs index 28ec8bf..a1c6068 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,19 @@ -use axum::{extract::State, response::IntoResponse, routing::get, Router}; +use axum::{ + async_trait, + extract::{Extension, FromRequestParts, State}, + http::request::Parts, + response::IntoResponse, + routing::get, + RequestPartsExt, + Router, +}; use axum_extra::extract::cookie::{Cookie, CookieJar}; use clap::Parser; use morethantext::MoreThanText; +use std::convert::Infallible; use tokio::{spawn, sync::mpsc::channel}; +use tower_cookies::{CookieManagerLayer, Cookies}; +use uuid::Uuid; const LOCALHOST: &str = "127.0.0.1"; const SESSION_KEY: &str = "sessionid"; @@ -33,11 +44,30 @@ async fn main() { .unwrap(); } +struct SessionID; + +#[async_trait] +impl FromRequestParts for SessionID +where + S: Send + Sync, +{ + type Rejection = Infallible; + + async fn from_request_parts(parts: &mut Parts, state: &S) -> Result { + let cookies = parts.extract::>(); + Ok(Self {}) + } +} + async fn create_app(state: MoreThanText) -> Router { Router::new().route("/", get(mtt_conn)).with_state(state) } -async fn mtt_conn(jar: CookieJar, state: State) -> impl IntoResponse { +async fn mtt_conn( + jar: CookieJar, + sess_id: SessionID, + state: State, +) -> impl IntoResponse { let sid = match jar.get(SESSION_KEY) { Some(cookie) => Some(cookie.value().to_string()), None => None, @@ -48,9 +78,9 @@ async fn mtt_conn(jar: CookieJar, state: State) -> impl IntoRespon tx.send(state.clone().request(sess_info)).await.unwrap(); }); let reply = rx.recv().await.unwrap(); - let cookie = Cookie::build((SESSION_KEY, reply.get_session().to_string())); + let cookie = Cookie::build((SESSION_KEY, reply.get_data("sess_id").unwrap().to_string())); let cookies = jar.add(cookie); - (cookies, reply.get_content()) + (cookies, reply.get_data("dov").unwrap().to_string()) } #[cfg(test)]