From b1db1a0a47b10a6da9a8175cf7a6527246271309 Mon Sep 17 00:00:00 2001 From: Amit Upadhyay Date: Mon, 30 Dec 2024 12:45:01 +0530 Subject: [PATCH] moved more stuff to fastn-wasm --- Cargo.lock | 9 +- fastn-core/src/commands/serve.rs | 2 +- fastn-ds/src/lib.rs | 2 +- fastn-ds/src/main.rs | 2 +- fastn-utils/Cargo.toml | 6 -- fastn-utils/src/lib.rs | 113 -------------------- v0.5/Cargo.lock | 2 + v0.5/Cargo.toml | 27 ++--- v0.5/fastn-wasm/Cargo.toml | 3 + v0.5/fastn-wasm/src/lib.rs | 2 + v0.5/fastn-wasm/src/process_http_request.rs | 112 +++++++++++++++++++ 11 files changed, 140 insertions(+), 140 deletions(-) create mode 100644 v0.5/fastn-wasm/src/process_http_request.rs diff --git a/Cargo.lock b/Cargo.lock index aee1bfd10..a2f0cd00b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1606,21 +1606,16 @@ dependencies = [ name = "fastn-utils" version = "0.1.0" dependencies = [ - "actix-http", - "actix-web", - "fastn-wasm", - "ft-sys-shared", "rusqlite", "serde_json", "thiserror 2.0.9", - "tracing", - "wasmtime", ] [[package]] name = "fastn-wasm" version = "0.1.0" dependencies = [ + "actix-http", "actix-web", "async-lock", "bytes", @@ -1639,7 +1634,9 @@ dependencies = [ "scc", "serde", "serde_json", + "thiserror 2.0.9", "tokio-postgres", + "tracing", "wasmtime", ] diff --git a/fastn-core/src/commands/serve.rs b/fastn-core/src/commands/serve.rs index 322c47e63..ee874478b 100644 --- a/fastn-core/src/commands/serve.rs +++ b/fastn-core/src/commands/serve.rs @@ -526,7 +526,7 @@ async fn handle_endpoints( .handle_wasm(url, req, endpoint.mountpoint.to_string(), session_id) .await { - Ok(r) => Some(Ok(fastn_utils::to_response(r))), + Ok(r) => Some(Ok(fastn_wasm::to_response(r))), Err(e) => return Some(Err(e.into())), }; } diff --git a/fastn-ds/src/lib.rs b/fastn-ds/src/lib.rs index 518ed3bdc..1d9814c75 100644 --- a/fastn-ds/src/lib.rs +++ b/fastn-ds/src/lib.rs @@ -506,7 +506,7 @@ impl DocumentStore { }; let store = fastn_wasm::Store::new(req, self.pg_pools.clone(), db_path, fastn_ds::wasm::Store); - Ok(fastn_utils::process_http_request(&wasm_url, module, store).await?) + Ok(fastn_wasm::process_http_request(&wasm_url, module, store).await?) } // This method will connect client request to the out of the world diff --git a/fastn-ds/src/main.rs b/fastn-ds/src/main.rs index ed424ed14..10865deb5 100644 --- a/fastn-ds/src/main.rs +++ b/fastn-ds/src/main.rs @@ -23,7 +23,7 @@ async fn main() { "".to_string(), fastn_ds::wasm::Store, ); - let resp = fastn_utils::process_http_request("/", module, store) + let resp = fastn_wasm::process_http_request("/", module, store) .await .unwrap(); diff --git a/fastn-utils/Cargo.toml b/fastn-utils/Cargo.toml index 060e5e6e3..136c620ed 100644 --- a/fastn-utils/Cargo.toml +++ b/fastn-utils/Cargo.toml @@ -9,12 +9,6 @@ repository.workspace = true homepage.workspace = true [dependencies] -actix-http.workspace = true -actix-web.workspace = true -fastn-wasm.workspace = true -ft-sys-shared = { workspace = true, features = ["rusqlite"] } rusqlite.workspace = true serde_json.workspace = true thiserror.workspace = true -tracing.workspace = true -wasmtime.workspace = true diff --git a/fastn-utils/src/lib.rs b/fastn-utils/src/lib.rs index 4436aebf1..007d56295 100644 --- a/fastn-utils/src/lib.rs +++ b/fastn-utils/src/lib.rs @@ -3,119 +3,6 @@ pub mod sql; -#[tracing::instrument(skip_all)] -pub async fn process_http_request( - path: &str, - module: wasmtime::Module, - store: fastn_wasm::Store, -) -> wasmtime::Result { - let mut linker = wasmtime::Linker::new(module.engine()); - store.register_functions(&mut linker); - let wasm_store = wasmtime::Store::new(module.engine(), store); - let (wasm_store, r) = handle(wasm_store, module, linker, path).await?; - if let Some(r) = r { - return Ok(r); - } - - Ok(wasm_store - .into_data() - .response - .ok_or(crate::WasmError::EndpointDidNotReturnResponse)?) -} - -pub fn to_response(req: ft_sys_shared::Request) -> actix_web::HttpResponse { - println!("{req:?}"); - let mut builder = actix_web::HttpResponse::build(req.method.parse().unwrap()); - let mut resp = builder.status(req.method.parse().unwrap()).body(req.body); - - for (k, v) in req.headers { - resp.headers_mut().insert( - k.parse().unwrap(), - actix_http::header::HeaderValue::from_bytes(v.as_slice()).unwrap(), - ); - } - - resp -} - -pub async fn handle( - mut wasm_store: wasmtime::Store, - module: wasmtime::Module, - linker: wasmtime::Linker, - path: &str, -) -> wasmtime::Result<(wasmtime::Store, Option)> { - let instance = match linker.instantiate_async(&mut wasm_store, &module).await { - Ok(i) => i, - Err(e) => { - return Ok(( - wasm_store, - Some(ft_sys_shared::Request::server_error(format!( - "failed to instantiate wasm module: {e:?}" - ))), - )); - } - }; - - let (mut wasm_store, main) = get_entrypoint(instance, wasm_store, path); - - let main = match main { - Ok(v) => v, - Err(e) => { - return Ok(( - wasm_store, - Some(ft_sys_shared::Request { - uri: "server-error".to_string(), - method: "404".to_string(), - headers: vec![], - body: format!("no endpoint found for {path}: {e:?}").into_bytes(), - }), - )); - } - }; - main.call_async(&mut wasm_store, ()).await?; - - Ok((wasm_store, None)) -} - -pub fn get_entrypoint( - instance: wasmtime::Instance, - mut store: wasmtime::Store, - path: &str, -) -> ( - wasmtime::Store, - wasmtime::Result>, -) { - let entrypoint = match path_to_entrypoint(path) { - Ok(v) => v, - Err(e) => return (store, Err(e)), - }; - let r = instance.get_typed_func(&mut store, entrypoint.as_str()); - (store, r) -} - -#[derive(Debug, thiserror::Error)] -pub enum PathToEndpointError { - #[error("no wasm file found in path")] - NoWasm, -} - -#[derive(Debug, thiserror::Error)] -pub enum WasmError { - #[error("endpoint did not return response")] - EndpointDidNotReturnResponse, -} - -pub fn path_to_entrypoint(path: &str) -> wasmtime::Result { - let path = path.split_once('?').map(|(f, _)| f).unwrap_or(path); - match path.split_once(".wasm/") { - Some((_, l)) => { - let l = l.trim_end_matches('/').replace('/', "_"); - Ok(l.trim_end_matches('/').replace('-', "_") + "__entrypoint") - } - None => Err(PathToEndpointError::NoWasm.into()), - } -} - #[derive(thiserror::Error, Debug)] pub enum SqlError { #[error("connection error {0}")] diff --git a/v0.5/Cargo.lock b/v0.5/Cargo.lock index 44241ed9c..a42d8a48a 100644 --- a/v0.5/Cargo.lock +++ b/v0.5/Cargo.lock @@ -1059,6 +1059,7 @@ version = "0.1.0" name = "fastn-wasm" version = "0.1.0" dependencies = [ + "actix-http", "actix-web", "async-lock", "bytes", @@ -1078,6 +1079,7 @@ dependencies = [ "serde", "serde_json", "tokio-postgres", + "tracing", "wasmtime", ] diff --git a/v0.5/Cargo.toml b/v0.5/Cargo.toml index a12dca93a..c674cf310 100644 --- a/v0.5/Cargo.toml +++ b/v0.5/Cargo.toml @@ -40,8 +40,15 @@ homepage = "https://fastn.com" # and create its own [dependencies.] section. Also, document it with why are you not # using the latest dependency, and what is the plan to move to the latest version. +actix-web = "4" +actix-http = "3" arcstr = "1" +async-lock = "3" async-trait = "0.1" +bytes = "1" +chrono = { version = "0.4", features = ["serde"] } +deadpool = "0.10" +deadpool-postgres = "0.12" fastn-builtins = { path = "../fastn-builtins" } fastn-compiler = { path = "fastn-compiler" } fastn-continuation = { path = "fastn-continuation" } @@ -52,31 +59,27 @@ fastn-runtime = { path = "../fastn-runtime" } fastn-section = { path = "fastn-section" } fastn-unresolved = { path = "fastn-unresolved" } ft-sys-shared = "0.1.4" +futures-util = { version = "0.3", default-features = false, features = ["std"] } http = "1" http-body-util = "0.1" hyper = { version = "1.5.1", features = ["server", "http1"] } hyper-util = { version = "0.1.10", features = ["tokio"] } id-arena = "2" indexmap = "2" +libsqlite3-sys = "0.28.0" +magic-crypt = { version = "4", default-features = false } +once_cell = "1" rand = "0.8" reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } +scc = "2" serde = { version = "1", features = ["derive"] } serde_json = "1" string-interner = "0.18" tokio = { version = "1", features = ["macros", "rt-multi-thread", "fs"] } -wasmtime = "28" -chrono = { version = "0.4", features = ["serde"] } -magic-crypt = { version = "4", default-features = false } -actix-web = "4" -async-lock = "3" -deadpool = "0.10" -deadpool-postgres = "0.12" -scc = "2" -once_cell = "1" -libsqlite3-sys = "0.28.0" tokio-postgres = { version = "0.7", features = ["with-serde_json-1", "with-uuid-1"] } -bytes = "1" -futures-util = { version = "0.3", default-features = false, features = ["std"] } +tracing = "0.1" +thiserror = "2" +wasmtime = "28" [workspace.dependencies.rusqlite] version = "0.31" diff --git a/v0.5/fastn-wasm/Cargo.toml b/v0.5/fastn-wasm/Cargo.toml index 2b3cdf273..ce7810ef2 100644 --- a/v0.5/fastn-wasm/Cargo.toml +++ b/v0.5/fastn-wasm/Cargo.toml @@ -9,6 +9,7 @@ repository.workspace = true homepage.workspace = true [dependencies] +actix-http.workspace = true wasmtime.workspace = true serde_json.workspace = true serde.workspace = true @@ -20,6 +21,8 @@ chrono.workspace = true magic-crypt.workspace = true async-lock.workspace = true actix-web.workspace = true +tracing.workspace = true +thiserror.workspace = true deadpool.workspace = true deadpool-postgres.workspace = true scc.workspace = true diff --git a/v0.5/fastn-wasm/src/lib.rs b/v0.5/fastn-wasm/src/lib.rs index 46ebbfbcc..ea6196639 100644 --- a/v0.5/fastn-wasm/src/lib.rs +++ b/v0.5/fastn-wasm/src/lib.rs @@ -13,11 +13,13 @@ pub mod helpers; pub mod http; pub mod macros; mod pg; +mod process_http_request; pub mod register; mod sqlite; mod store; pub use create_pool::create_pool; +pub use process_http_request::{process_http_request, to_response}; pub use store::{Conn, ConnectionExt, ExecuteError, Store, StoreExt, Value}; pub static WASM_ENGINE: once_cell::sync::Lazy = diff --git a/v0.5/fastn-wasm/src/process_http_request.rs b/v0.5/fastn-wasm/src/process_http_request.rs new file mode 100644 index 000000000..1b90785bd --- /dev/null +++ b/v0.5/fastn-wasm/src/process_http_request.rs @@ -0,0 +1,112 @@ +#[tracing::instrument(skip_all)] +pub async fn process_http_request( + path: &str, + module: wasmtime::Module, + store: fastn_wasm::Store, +) -> wasmtime::Result { + let mut linker = wasmtime::Linker::new(module.engine()); + store.register_functions(&mut linker); + let wasm_store = wasmtime::Store::new(module.engine(), store); + let (wasm_store, r) = handle(wasm_store, module, linker, path).await?; + if let Some(r) = r { + return Ok(r); + } + + Ok(wasm_store + .into_data() + .response + .ok_or(WasmError::EndpointDidNotReturnResponse)?) +} + +pub fn to_response(req: ft_sys_shared::Request) -> actix_web::HttpResponse { + println!("{req:?}"); + let mut builder = actix_web::HttpResponse::build(req.method.parse().unwrap()); + let mut resp = builder.status(req.method.parse().unwrap()).body(req.body); + + for (k, v) in req.headers { + resp.headers_mut().insert( + k.parse().unwrap(), + actix_http::header::HeaderValue::from_bytes(v.as_slice()).unwrap(), + ); + } + + resp +} + +pub async fn handle( + mut wasm_store: wasmtime::Store, + module: wasmtime::Module, + linker: wasmtime::Linker, + path: &str, +) -> wasmtime::Result<(wasmtime::Store, Option)> { + let instance = match linker.instantiate_async(&mut wasm_store, &module).await { + Ok(i) => i, + Err(e) => { + return Ok(( + wasm_store, + Some(ft_sys_shared::Request::server_error(format!( + "failed to instantiate wasm module: {e:?}" + ))), + )); + } + }; + + let (mut wasm_store, main) = get_entrypoint(instance, wasm_store, path); + + let main = match main { + Ok(v) => v, + Err(e) => { + return Ok(( + wasm_store, + Some(ft_sys_shared::Request { + uri: "server-error".to_string(), + method: "404".to_string(), + headers: vec![], + body: format!("no endpoint found for {path}: {e:?}").into_bytes(), + }), + )); + } + }; + main.call_async(&mut wasm_store, ()).await?; + + Ok((wasm_store, None)) +} + +pub fn get_entrypoint( + instance: wasmtime::Instance, + mut store: wasmtime::Store, + path: &str, +) -> ( + wasmtime::Store, + wasmtime::Result>, +) { + let entrypoint = match path_to_entrypoint(path) { + Ok(v) => v, + Err(e) => return (store, Err(e)), + }; + let r = instance.get_typed_func(&mut store, entrypoint.as_str()); + (store, r) +} + +#[derive(Debug, thiserror::Error)] +pub enum PathToEndpointError { + #[error("no wasm file found in path")] + NoWasm, +} + +#[derive(Debug, thiserror::Error)] +pub enum WasmError { + #[error("endpoint did not return response")] + EndpointDidNotReturnResponse, +} + +pub fn path_to_entrypoint(path: &str) -> wasmtime::Result { + let path = path.split_once('?').map(|(f, _)| f).unwrap_or(path); + match path.split_once(".wasm/") { + Some((_, l)) => { + let l = l.trim_end_matches('/').replace('/', "_"); + Ok(l.trim_end_matches('/').replace('-', "_") + "__entrypoint") + } + None => Err(PathToEndpointError::NoWasm.into()), + } +}