diff --git a/Cargo.lock b/Cargo.lock index cee82d3..5cc7e58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -333,6 +333,16 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "etag" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b3d0661a2ccddc26cba0b834e9b717959ed6fdd76c7129ee159c170a875bf44" +dependencies = [ + "str-buf", + "xxhash-rust", +] + [[package]] name = "fastrand" version = "2.3.0" @@ -1325,7 +1335,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.2", "system-configuration", "tokio", "tokio-native-tls", @@ -1441,6 +1451,7 @@ dependencies = [ "salvo-jwt-auth", "salvo-proxy", "salvo_core", + "salvo_extra", ] [[package]] @@ -1523,11 +1534,12 @@ dependencies = [ "pin-project", "rand", "regex", + "rustls-pemfile", "salvo_macros", "serde", "serde-xml-rs", "serde_json", - "sync_wrapper", + "sync_wrapper 1.0.2", "tempfile", "thiserror 2.0.9", "tokio", @@ -1536,6 +1548,28 @@ dependencies = [ "tracing", ] +[[package]] +name = "salvo_extra" +version = "0.74.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "647f414b9f7cefc341b3c445b65d1226f375e51e469199cfd8caf4996e681610" +dependencies = [ + "base64 0.22.1", + "etag", + "futures-util", + "http-body-util", + "hyper", + "pin-project", + "salvo_core", + "serde", + "serde_json", + "tokio", + "tokio-tungstenite", + "tower", + "tracing", + "ulid", +] + [[package]] name = "salvo_macros" version = "0.74.3" @@ -1743,6 +1777,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "str-buf" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34" + [[package]] name = "subtle" version = "2.6.1" @@ -1760,6 +1800,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "sync_wrapper" version = "1.0.2" @@ -1952,6 +1998,18 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + [[package]] name = "tokio-util" version = "0.7.13" @@ -1982,6 +2040,29 @@ dependencies = [ "winnow", ] +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -2051,12 +2132,37 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" +dependencies = [ + "byteorder", + "bytes", + "log", + "rand", + "thiserror 1.0.69", + "utf-8", +] + [[package]] name = "typenum" version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ulid" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04f903f293d11f31c0c29e4148f6dc0d033a7f80cebc0282bea147611667d289" +dependencies = [ + "getrandom", + "rand", + "web-time", +] + [[package]] name = "unicase" version = "2.8.0" @@ -2096,6 +2202,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -2231,6 +2343,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "winapi" version = "0.3.9" @@ -2392,6 +2514,12 @@ version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" +[[package]] +name = "xxhash-rust" +version = "0.8.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a08fd76779ae1883bbf1e46c2c46a75a0c4e37c445e68a24b01479d438f26ae6" + [[package]] name = "yoke" version = "0.7.5" diff --git a/Cargo.toml b/Cargo.toml index 3fb003c..e0fd87c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -salvo = "0.74.3" +salvo = { version = "0.74.3", features = ["affix-state", "logging"] } tokio = { version = "1", features = ["macros"] } tracing = "0.1" -tracing-subscriber = "0.3" \ No newline at end of file +tracing-subscriber = "0.3" diff --git a/src/main.rs b/src/main.rs index d486b93..e3ac953 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,17 +1,127 @@ +use salvo::http::HeaderValue; +use salvo::logging::Logger; + use salvo::prelude::*; +fn search(buf: &[u8], pattern: &[u8], start_index: usize) -> Option { + let mut i = start_index; + + // If the buffer is empty, the pattern is too long + if pattern.len() > buf.len() { + return None; + } + + // If the pattern is empty + if pattern.len() == 0 { + return None; + } + + // If the starting index is too high + if start_index >= buf.len() { + return None; + } + + while i < buf.len() { + for j in 0..pattern.len() { + // If the pattern is too long to fit in the buffer anymore + if i + j >= buf.len() { + return None; + } + + // If the pattern stops matching + if buf[i + j] != pattern[j] { + break; + } + + // If the pattern is found + if j == pattern.len() - 1 { + return Some(i); + } + } + + i += 1; + } + None +} + #[handler] async fn hello() -> &'static str { "Hello World" } +#[handler] +async fn download(depot: &mut Depot, req: &mut Request, res: &mut Response) { + let state = depot.obtain::().unwrap(); + let data = state.with_key(b"test"); // Clone the data + + if let Err(e) = res.write_body(data) { + eprintln!("Error writing body: {}", e); + } + + res.headers.insert( + "Content-Disposition", + HeaderValue::from_static("attachment; filename=demo"), + ); + res.headers.insert( + "Content-Type", + HeaderValue::from_static("application/octet-stream"), + ); +} + +#[allow(dead_code)] +#[derive(Default, Clone, Debug)] +struct State { + data: Vec, + key_start: usize, + key_end: usize, +} + +impl State { + fn with_key(&self, new_key: &[u8]) -> Vec { + let mut data = self.data.clone(); + + // Copy the key into the data + for i in 0..new_key.len() { + data[self.key_start + i] = new_key[i]; + } + + // If the new key is shorter than the old key, we just write over the remaining data + if new_key.len() < self.key_end - self.key_start { + for i in self.key_start + new_key.len()..self.key_end { + data[i] = b' '; + } + } + + return data; + } +} + #[tokio::main] async fn main() { let port = std::env::var("PORT").unwrap_or_else(|_| "5800".to_string()); let addr = format!("0.0.0.0:{}", port); tracing_subscriber::fmt().init(); - let router = Router::new().get(hello); + let path = "./demo/target/release/demo"; + let data = std::fs::read(&path).expect("Unable to read file"); + + let pattern = "a".repeat(1024); + let key_start = search(&data, pattern.as_bytes(), 0).unwrap(); + let key_end = key_start + pattern.len(); + + let state = State { + data, + key_start: key_start, + key_end: key_end, + }; + + let router = Router::new() + .hoop(affix_state::inject(state)) + .get(hello) + .push(Router::with_path("download").get(download)); + + let service = Service::new(router).hoop(Logger::new()); + let acceptor = TcpListener::new(addr).bind().await; - Server::new(acceptor).serve(router).await; + Server::new(acceptor).serve(service).await; }