From 3e8b48d77eda92c981757e21ea9cbb59d5b59030 Mon Sep 17 00:00:00 2001 From: Juan Jose Nicola Date: Tue, 4 Jul 2023 11:40:52 +0200 Subject: [PATCH] Test stream response --- rust/Cargo.lock | 357 +++++++++++++++++++++++++- rust/Cargo.toml | 1 + rust/examples/simple_scan.json | 45 ++++ rust/openvasd/Cargo.toml | 5 + rust/openvasd/src/controller/entry.rs | 11 +- rust/openvasd/src/response.rs | 37 ++- rust/streamer/Cargo.toml | 32 +++ rust/streamer/src/main.rs | 68 +++++ 8 files changed, 546 insertions(+), 10 deletions(-) create mode 100644 rust/examples/simple_scan.json create mode 100644 rust/streamer/Cargo.toml create mode 100644 rust/streamer/src/main.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index c3fc24b9d..84a3c9d56 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -43,6 +52,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "1.0.1" @@ -122,6 +142,26 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "async-stdin" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1ff8b5d9b5ec29e0f49583ba71847b8c8888b67a8510133048a380903aa6822" +dependencies = [ + "tokio", +] + +[[package]] +name = "async-throttle" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c99532de164435a0b91279e715bff4fa0d164643b409a67761907ffc210ee8f" +dependencies = [ + "backoff", + "dashmap", + "tokio", +] + [[package]] name = "async-trait" version = "0.1.68" @@ -150,6 +190,35 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "futures-core", + "getrandom", + "instant", + "pin-project-lite", + "rand", + "tokio", +] + +[[package]] +name = "backtrace" +version = "0.3.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.21.2" @@ -480,6 +549,16 @@ dependencies = [ "scopeguard", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.15" @@ -509,6 +588,19 @@ dependencies = [ "cipher", ] +[[package]] +name = "dashmap" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" +dependencies = [ + "cfg-if", + "hashbrown", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "dbl" version = "0.3.2" @@ -535,6 +627,19 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + [[package]] name = "errno" version = "0.2.8" @@ -586,6 +691,12 @@ dependencies = [ "redis", ] +[[package]] +name = "file-format" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "805eab5eeca901cbdfabf3f54adb2f27464073617279fd4e14eedb2a0757222e" + [[package]] name = "flate2" version = "1.0.26" @@ -611,6 +722,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "futures" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + [[package]] name = "futures-channel" version = "0.3.28" @@ -618,6 +744,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -626,6 +753,23 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +[[package]] +name = "futures-executor" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" + [[package]] name = "futures-macro" version = "0.3.28" @@ -655,9 +799,13 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ + "futures-channel", "futures-core", + "futures-io", "futures-macro", + "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", @@ -694,6 +842,12 @@ dependencies = [ "polyval", ] +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + [[package]] name = "glob" version = "0.3.1" @@ -730,6 +884,9 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "heck" @@ -798,6 +955,29 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-body" +version = "1.0.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "951dfc2e32ac02d67c90c0d65bd27009a635dc9b381a2cc7d284ab01e3a0150d" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.0-rc.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92445bc9cc14bfa0a3ce56817dc3b5bcc227a168781a356b702410789cec0d10" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body 1.0.0-rc.2", + "pin-project-lite", +] + [[package]] name = "httparse" version = "1.8.0" @@ -810,11 +990,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -822,7 +1008,7 @@ dependencies = [ "futures-util", "h2", "http", - "http-body", + "http-body 0.4.5", "httparse", "httpdate", "itoa", @@ -902,6 +1088,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "io-lifetimes" version = "1.0.11" @@ -974,9 +1169,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "libloading" @@ -1302,6 +1497,15 @@ dependencies = [ "libc", ] +[[package]] +name = "object" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -1346,6 +1550,8 @@ dependencies = [ "async-trait", "clap 4.3.0", "feed", + "file-format", + "futures", "futures-util", "hyper", "hyper-rustls", @@ -1359,6 +1565,9 @@ dependencies = [ "storage", "tokio", "tokio-rustls", + "tokio-serde", + "tokio-stream", + "tokio-util", "toml", "tracing", "tracing-subscriber", @@ -1432,6 +1641,26 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.18", +] + [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1587,6 +1816,16 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty_env_logger" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "865724d4dbe39d9f3dd3b52b88d859d66bcb2d6a0acfd5ea68a65fb66d4bdc1c" +dependencies = [ + "env_logger", + "log", +] + [[package]] name = "proc-macro2" version = "1.0.59" @@ -1754,6 +1993,12 @@ dependencies = [ "digest", ] +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + [[package]] name = "rustix" version = "0.37.19" @@ -1951,6 +2196,15 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shutdown-async" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2799e69bde7e68bedd86c6d94bffa783219114f1f31435ddda61f4aeba348ff" +dependencies = [ + "tokio", +] + [[package]] name = "signal-hook-registry" version = "1.4.1" @@ -2009,6 +2263,36 @@ dependencies = [ "time", ] +[[package]] +name = "streamer" +version = "0.1.0" +dependencies = [ + "async-trait", + "clap 4.3.0", + "feed", + "futures-util", + "http-body-util", + "hyper", + "hyper-rustls", + "models", + "nasl-interpreter", + "osp", + "pretty_env_logger", + "rustls", + "rustls-pemfile", + "serde", + "serde_json", + "storage", + "tokio", + "tokio-rustls", + "tokio-util", + "tokio-utils", + "toml", + "tracing", + "tracing-subscriber", + "uuid", +] + [[package]] name = "strsim" version = "0.10.0" @@ -2043,6 +2327,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + [[package]] name = "textwrap" version = "0.16.0" @@ -2132,11 +2425,12 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.28.2" +version = "1.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da" dependencies = [ "autocfg", + "backtrace", "bytes", "libc", "mio", @@ -2170,6 +2464,29 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-util" version = "0.7.8" @@ -2178,12 +2495,28 @@ checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", + "hashbrown", "pin-project-lite", + "slab", "tokio", "tracing", ] +[[package]] +name = "tokio-utils" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de75f75f464153a50fe48b9675360e3cf2ae1d7d81f9751363bd2ee4888f5ce8" +dependencies = [ + "async-stdin", + "async-throttle", + "shutdown-async", + "tub", +] + [[package]] name = "toml" version = "0.7.4" @@ -2292,6 +2625,16 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +[[package]] +name = "tub" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bca43faba247bc76eb1d6c1b8b561e4a1c5bdd427cc3d7a007faabea75c683a" +dependencies = [ + "crossbeam-queue", + "tokio", +] + [[package]] name = "typenum" version = "1.16.0" diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 0012998fe..de294c2d7 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -22,4 +22,5 @@ members = [ "models", "osp", "openvasd", + "streamer", ] diff --git a/rust/examples/simple_scan.json b/rust/examples/simple_scan.json new file mode 100644 index 000000000..36468a499 --- /dev/null +++ b/rust/examples/simple_scan.json @@ -0,0 +1,45 @@ +{ + "scan_id": "6c591f83-8f7b-452a-8c78-ba35779e682f", + "target": { + "hosts": [ + "127.0.0.1", + "::1", + "10.0.0.1" + ], + "ports": [ + { + "protocol": "udp", + "range": [ + { + "start": 1, + "end": 3000 + } + ] + }, + { + "protocol": "tcp", + "range": [ + { + "start": 1, + "end": 3000 + } + ] + } + ], + "credentials": [ + { + "service": "ssh", + "port": 22, + "up": { + "username": "user", + "password": "pw" + } + } + ] + }, + "vts": [ + { + "oid": "1.3.6.1.4.1.25623.1.0.50282" + } + ] +} diff --git a/rust/openvasd/Cargo.toml b/rust/openvasd/Cargo.toml index a9ca95ef1..c40903dc9 100644 --- a/rust/openvasd/Cargo.toml +++ b/rust/openvasd/Cargo.toml @@ -26,5 +26,10 @@ rustls-pemfile = "1.0.2" async-trait = "0.1.68" clap = { version = "4.3.0", features = ["derive", "env"] } toml = "0.7.4" +tokio-util = { version = "0.7.8", features = ["full"] } +tokio-serde = "0.8.0" +tokio-stream = "0.1.14" +file-format = "0.17.3" +futures = "0.3.28" [dev-dependencies] diff --git a/rust/openvasd/src/controller/entry.rs b/rust/openvasd/src/controller/entry.rs index 3422f636c..35e97efe9 100644 --- a/rust/openvasd/src/controller/entry.rs +++ b/rust/openvasd/src/controller/entry.rs @@ -6,6 +6,8 @@ //! //! All known paths must be handled in the entrypoint function. +use std::convert::Infallible; + use std::{fmt::Display, sync::Arc}; use super::{context::Context, quit_on_poison}; @@ -294,7 +296,14 @@ where } (&Method::GET, Vts) => { let (_, oids) = ctx.oids.read()?.clone(); - Ok(ctx.response.ok(&oids)) + + let stream = futures::stream::iter(oids.into_iter().map( + |s: String| -> Result { + Ok(format!("{},", serde_json::to_string(&s).unwrap())) + }, + )); + + Ok(ctx.response.ok_stream(stream).await) } _ => Ok(ctx.response.not_found("path", req.uri().path())), } diff --git a/rust/openvasd/src/response.rs b/rust/openvasd/src/response.rs index a4fe8921d..92b3a8497 100644 --- a/rust/openvasd/src/response.rs +++ b/rust/openvasd/src/response.rs @@ -4,8 +4,9 @@ use std::error::Error; +use futures::Stream; +use hyper::body::Bytes; use serde::Serialize; - type Result = hyper::Response; #[derive(Debug, Default)] @@ -15,7 +16,39 @@ pub struct Response { } impl Response { - #[tracing::instrument] + async fn create_stream(&self, code: hyper::StatusCode, value: S) -> Result + where + S: Stream> + Send + 'static, + O: Into + 'static, + E: Into> + 'static, + { + match hyper::Response::builder() + .status(code) + .header("Content-Type", "application/json") + .header("authentication", &self.authentication) + .header("version", &self.version) + .body(hyper::Body::wrap_stream(value)) + { + Ok(resp) => resp, + Err(e) => { + tracing::error!("Error creating response: {}", e); + hyper::Response::builder() + .status(hyper::StatusCode::INTERNAL_SERVER_ERROR) + .body(hyper::Body::empty()) + .unwrap() + } + } + } + + pub async fn ok_stream(&self, value: S) -> Result + where + S: Stream> + Send + 'static, + O: Into + 'static, + E: Into> + 'static, + { + self.create_stream(hyper::StatusCode::OK, value).await + } + fn create(&self, code: hyper::StatusCode, value: &T) -> Result where T: ?Sized + Serialize + std::fmt::Debug, diff --git a/rust/streamer/Cargo.toml b/rust/streamer/Cargo.toml new file mode 100644 index 000000000..a936bc752 --- /dev/null +++ b/rust/streamer/Cargo.toml @@ -0,0 +1,32 @@ +[package] +name = "streamer" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +models = {path = "../models"} +osp = {path = "../osp"} +nasl-interpreter = { path = "../nasl-interpreter" } +feed = {path = "../feed"} +storage = { path = "../storage" } +hyper = { version = "0.14.26", features = ["full", "stream"] } +tokio = { version = "1.28.1", features = ["full"] } +tracing = "0.1.37" +tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } +serde_json = "1.0.96" +serde = { version = "1.0.163", features = ["derive"] } +uuid = {version = "1", features = ["v4", "fast-rng", "serde"]} +hyper-rustls = "0.24.0" +rustls = "0.21.1" +tokio-rustls = "0.24.0" +futures-util = "0.3.28" +rustls-pemfile = "1.0.2" +async-trait = "0.1.68" +clap = { version = "4.3.0", features = ["derive", "env"] } +toml = "0.7.4" +http-body-util = "0.1.0-rc.2" +tokio-utils = "0.1.2" +tokio-util = "0.7.8" +pretty_env_logger = "0.5.0" diff --git a/rust/streamer/src/main.rs b/rust/streamer/src/main.rs new file mode 100644 index 000000000..8adf79bcc --- /dev/null +++ b/rust/streamer/src/main.rs @@ -0,0 +1,68 @@ +#![deny(warnings)] + +use tokio::fs::File; + +use tokio_util::codec::{BytesCodec, FramedRead}; + +use hyper::service::{make_service_fn, service_fn}; +use hyper::{Body, Method, Request, Response, Result, Server, StatusCode}; + +static INDEX: &str = "/tmp/feed.json"; +static NOTFOUND: &[u8] = b"Not Found"; + +#[tokio::main] +async fn main() { + pretty_env_logger::init(); + + let addr = "127.0.0.1:1337".parse().unwrap(); + + let make_service = + make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(response_examples)) }); + + let server = Server::bind(&addr).serve(make_service); + + println!("Listening on http://{}", addr); + + if let Err(e) = server.await { + eprintln!("server error: {}", e); + } +} + +async fn response_examples(req: Request) -> Result> { + match (req.method(), req.uri().path()) { + (&Method::GET, "/") | (&Method::GET, "/index.html") => simple_file_send(INDEX).await, + (&Method::GET, "/no_file.html") => { + // Test what happens when file cannot be be found + simple_file_send("this_file_should_not_exist.html").await + } + _ => Ok(not_found()), + } +} + +/// HTTP status code 404 +fn not_found() -> Response { + Response::builder() + .status(StatusCode::NOT_FOUND) + .body(NOTFOUND.into()) + .unwrap() +} + +async fn simple_file_send(filename: &str) -> Result> { + // Serve a file by asynchronously reading it by chunks using tokio-util crate. + + if let Ok(file) = File::open(filename).await { + let stream = FramedRead::new(file, BytesCodec::new()); + let body = Body::wrap_stream(stream); + //return Ok(Response::new(body)); + match hyper::Response::builder() + .status(hyper::StatusCode::OK) + .header(hyper::header::CONTENT_TYPE, "application/json") + .header(hyper::header::CONTENT_ENCODING, "chuncked") + .body(body) { + Ok(resp) => return Ok(resp), + _ => return Ok(not_found()) + } + }; + Ok(not_found()) +} +