From 2093456d91b254651b864b0d51de029ffd8405eb Mon Sep 17 00:00:00 2001 From: midefos Date: Wed, 11 Mar 2026 21:01:01 +0100 Subject: [PATCH] adding jwt middlewares, and improving overall middlewares structure and server --- Cargo.lock | 842 +++++++++++++++++++++++++++++++---- Cargo.toml | 5 +- src/builder.rs | 50 ++- src/config.rs | 55 --- src/lib.rs | 2 + src/middleware/api_key.rs | 42 ++ src/middleware/auth_types.rs | 17 + src/middleware/ip_filter.rs | 56 +++ src/middleware/jwt.rs | 71 +++ src/middleware/mod.rs | 26 ++ src/responder.rs | 58 +-- src/server.rs | 75 ++-- 12 files changed, 1082 insertions(+), 217 deletions(-) create mode 100644 src/middleware/api_key.rs create mode 100644 src/middleware/auth_types.rs create mode 100644 src/middleware/ip_filter.rs create mode 100644 src/middleware/jwt.rs create mode 100644 src/middleware/mod.rs diff --git a/Cargo.lock b/Cargo.lock index ecdc45d..b819835 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,12 +8,212 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "der" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" +dependencies = [ + "const-oid", + "pem-rfc7468", + "zeroize", +] + +[[package]] +name = "deranged" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9" +dependencies = [ + "curve25519-dalek", + "ed25519", + "serde", + "sha2", + "subtle", + "zeroize", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "hkdf", + "pem-rfc7468", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + [[package]] name = "errno" version = "0.3.14" @@ -21,9 +221,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys", ] +[[package]] +name = "ff" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + [[package]] name = "futures-channel" version = "0.3.32" @@ -45,6 +261,57 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +[[package]] +name = "generic-array" +version = "0.14.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "http" version = "1.4.0" @@ -132,10 +399,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] -name = "libc" -version = "0.2.182" +name = "js-sys" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "jsonwebtoken" +version = "10.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0529410abe238729a60b108898784df8984c87f6054c9c4fcacc47e4803c1ce1" +dependencies = [ + "base64", + "ed25519-dalek", + "getrandom", + "hmac", + "js-sys", + "p256", + "p384", + "pem", + "rand", + "rsa", + "serde", + "serde_json", + "sha2", + "signature", + "simple_asn1", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.183" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "log" @@ -157,7 +472,118 @@ checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "wasi", - "windows-sys 0.61.2", + "windows-sys", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" +dependencies = [ + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "pem" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" +dependencies = [ + "base64", + "serde_core", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", ] [[package]] @@ -172,6 +598,51 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "proc-macro2" version = "1.0.106" @@ -183,13 +654,108 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "rsa" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" + [[package]] name = "serde" version = "1.0.228" @@ -235,12 +801,13 @@ dependencies = [ [[package]] name = "servme" -version = "0.1.0" +version = "0.1.1" dependencies = [ "http", "http-body-util", "hyper", "hyper-util", + "jsonwebtoken", "log", "serde", "serde_json", @@ -248,6 +815,17 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" @@ -258,6 +836,28 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simple_asn1" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" +dependencies = [ + "num-bigint", + "num-traits", + "thiserror", + "time", +] + [[package]] name = "smallvec" version = "1.15.1" @@ -266,14 +866,36 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "2.0.117" @@ -286,10 +908,61 @@ dependencies = [ ] [[package]] -name = "tokio" -version = "1.49.0" +name = "thiserror" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tokio" +version = "1.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "libc", "mio", @@ -297,14 +970,14 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.61.2", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", @@ -324,33 +997,81 @@ dependencies = [ "tokio", ] +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" +[[package]] +name = "wasm-bindgen" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.114" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +dependencies = [ + "unicode-ident", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -361,69 +1082,30 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.53.5" +name = "zerocopy" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ - "windows-link", - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "zerocopy-derive", ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" +name = "zerocopy-derive" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] [[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" +name = "zeroize" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] name = "zmij" diff --git a/Cargo.toml b/Cargo.toml index c961ae5..22d7e57 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "servme" -version = "0.1.0" -edition = "2021" +version = "0.1.1" +edition = "2024" [dependencies] tokio = { version = "1.49.0", features = ["macros", "rt", "rt-multi-thread", "signal", "net"] } @@ -9,6 +9,7 @@ tokio-util = "0.7.18" http = "1.4.0" http-body-util = "0.1.3" +jsonwebtoken = { version = "10", features = ["rust_crypto"] } hyper = { version = "1.8.1", features = ["http1", "server"] } hyper-util = { version = "0.1", features = ["http1", "server", "tokio"] } diff --git a/src/builder.rs b/src/builder.rs index b316eb2..2400f04 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,8 +1,13 @@ -use crate::{config::ServerConfig, server::Server}; +use crate::{ + config::ServerConfig, + middleware::{ApiKeyMiddleware, IpFilterMiddleware, JwtMiddleware, Middleware}, + server::Server, +}; use std::sync::Arc; pub struct ServerBuilder { pub config: ServerConfig, + pub middlewares: Vec>, } impl ServerBuilder { @@ -12,36 +17,51 @@ impl ServerBuilder { self } - pub fn enable_private_ips(self) -> Self { - self.set_private_ips(true) - } - - pub fn set_private_ips(mut self, enabled: bool) -> Self { - self.config.private_ips = enabled; - self.update_ip_filter_state(); + pub fn add_api_key_middleware(mut self, api_key: &str) -> Self { + self.middlewares + .push(Box::new(ApiKeyMiddleware::new(api_key))); self } - pub fn ips(mut self, ips: Vec) -> Self { - self.config.ips = ips; - self.update_ip_filter_state(); + pub fn add_ip_filter_middleware( + mut self, + allowed_ips: Vec, + allow_private: bool, + ) -> Self { + self.middlewares.push(Box::new(IpFilterMiddleware::new( + allowed_ips, + allow_private, + ))); self } + pub fn add_jwt_middleware(mut self, public_key: &str, public_routes: Vec) -> Self { + let middleware = JwtMiddleware::new(public_key, public_routes) + .expect("Failed to initialize JWT Middleware: Invalid Public Key"); + + self.middlewares.push(Box::new(middleware)); + self + } + pub fn api_key(mut self, api_key: &str) -> Self { self.config.api_key = Some(api_key.to_string()); self } + pub fn middleware(mut self, middleware: M) -> Self + where + M: Middleware + 'static, + { + self.middlewares.push(Box::new(middleware)); + self + } + pub fn build(self) -> Server { Server { config: Arc::new(self.config), + middlewares: Arc::new(self.middlewares), } } - - fn update_ip_filter_state(&mut self) { - self.config.ip_filter = self.config.private_ips || !self.config.ips.is_empty(); - } } diff --git a/src/config.rs b/src/config.rs index 6494d9b..86ce88a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,58 +1,9 @@ -use http::Request; -use hyper::body::Incoming; -use std::net::IpAddr; - pub struct ServerConfig { pub ip: String, pub port: u16, - // IP filtering - pub ip_filter: bool, - pub private_ips: bool, - pub ips: Vec, - // Request filtering pub api_key: Option, - - pub log_unauthorized: bool, -} - -impl ServerConfig { - pub fn is_ip_authorized(&self, ip: &IpAddr) -> bool { - if !self.ip_filter { - return true; - } - - if self.private_ips { - let is_private = match ip { - IpAddr::V4(ip4) => ip4.is_private(), - IpAddr::V6(_) => false, - }; - - if is_private { - return true; - } - } - - let ips = &self.ips; - if ips.is_empty() { - return true; - } - - ips.iter() - .any(|authorized_ip| &ip.to_string() == authorized_ip) - } - - pub fn is_req_authorized(&self, req: &Request) -> bool { - if self.api_key.is_none() { - return true; - } - - match req.headers().get("X-API-Key") { - Some(header) => header.eq(self.api_key.as_ref().unwrap()), - None => false, - } - } } impl Default for ServerConfig { @@ -61,13 +12,7 @@ impl Default for ServerConfig { ip: "127.0.0.1".to_string(), port: 8080, - ip_filter: false, - private_ips: false, - ips: Vec::new(), - api_key: None, - - log_unauthorized: true, } } } diff --git a/src/lib.rs b/src/lib.rs index 2ead33d..4a3736d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,12 @@ mod builder; mod config; +mod middleware; mod requester; mod responder; mod server; mod url_extract; +pub use middleware::{Middleware, MiddlewareFuture, MiddlewareResult}; pub use requester::Requester; pub use responder::Responder; pub use server::Server; diff --git a/src/middleware/api_key.rs b/src/middleware/api_key.rs new file mode 100644 index 0000000..751686c --- /dev/null +++ b/src/middleware/api_key.rs @@ -0,0 +1,42 @@ +use crate::{ + middleware::{Middleware, MiddlewareFuture, MiddlewareResult}, + Responder, +}; +use http::Request; +use hyper::body::Incoming; +use log::warn; + +pub struct ApiKeyMiddleware { + api_key: String, +} + +impl ApiKeyMiddleware { + pub fn new(api_key: &str) -> Self { + Self { + api_key: api_key.to_string(), + } + } +} + +impl Middleware for ApiKeyMiddleware { + fn run<'a>(&'a self, req: Request) -> MiddlewareFuture<'a> { + let expected_key = self.api_key.clone(); + + Box::pin(async move { + match req.headers().get("X-API-Key") { + Some(header) => { + if header == expected_key.as_str() { + MiddlewareResult::Continue(req) + } else { + warn!("X-API-Key wrong"); + MiddlewareResult::Respond(Responder::unauthorized().unwrap()) + } + } + None => { + warn!("X-API-Key missing"); + MiddlewareResult::Respond(Responder::unauthorized().unwrap()) + } + } + }) + } +} diff --git a/src/middleware/auth_types.rs b/src/middleware/auth_types.rs new file mode 100644 index 0000000..b175953 --- /dev/null +++ b/src/middleware/auth_types.rs @@ -0,0 +1,17 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Serialize, Deserialize)] +pub struct Claims { + pub sub: String, + pub exp: usize, +} + +impl Claims { + pub fn is_expired(&self, current_timestamp: i64) -> bool { + current_timestamp > self.exp as i64 + } + + pub fn username(&self) -> &str { + &self.sub + } +} diff --git a/src/middleware/ip_filter.rs b/src/middleware/ip_filter.rs new file mode 100644 index 0000000..376e5ab --- /dev/null +++ b/src/middleware/ip_filter.rs @@ -0,0 +1,56 @@ +use crate::{ + Responder, + middleware::{Middleware, MiddlewareFuture, MiddlewareResult}, +}; +use http::Request; +use hyper::body::Incoming; +use log::warn; +use std::net::IpAddr; + +pub struct IpFilterMiddleware { + allowed_ips: Vec, + allow_private: bool, +} + +impl IpFilterMiddleware { + pub fn new(allowed_ips: Vec, allow_private: bool) -> Self { + Self { + allowed_ips, + allow_private, + } + } + + fn is_authorized(&self, ip: &IpAddr) -> bool { + if self.allow_private { + let is_private = match ip { + IpAddr::V4(ip4) => ip4.is_private(), + IpAddr::V6(_) => false, + }; + if is_private { + return true; + } + } + + if self.allowed_ips.is_empty() { + return true; + } + + self.allowed_ips.iter().any(|auth| &ip.to_string() == auth) + } +} + +impl Middleware for IpFilterMiddleware { + fn run<'a>(&'a self, req: Request) -> MiddlewareFuture<'a> { + Box::pin(async move { + let client_ip = req.extensions().get::(); + + match client_ip { + Some(ip) if self.is_authorized(ip) => MiddlewareResult::Continue(req), + _ => { + warn!("Unauthorized IP"); + MiddlewareResult::Respond(Responder::unauthorized().unwrap()) + } + } + }) + } +} diff --git a/src/middleware/jwt.rs b/src/middleware/jwt.rs new file mode 100644 index 0000000..7755381 --- /dev/null +++ b/src/middleware/jwt.rs @@ -0,0 +1,71 @@ +use crate::{ + middleware::{auth_types::Claims, Middleware, MiddlewareFuture, MiddlewareResult}, + Responder, +}; +use http::Request; +use hyper::body::Incoming; +use jsonwebtoken::{decode, Algorithm, DecodingKey, Validation}; +use log::error; + +pub struct JwtMiddleware { + decoding_key: DecodingKey, + public_routes: Vec, +} + +impl JwtMiddleware { + pub fn new( + public_key: &str, + public_routes: Vec, + ) -> Result> { + let decoding_key = DecodingKey::from_rsa_pem(public_key.as_bytes())?; + + Ok(Self { + decoding_key, + public_routes, + }) + } + + fn validate_request( + &self, + req: &Request, + ) -> Result> { + let auth_header = req + .headers() + .get("Authorization") + .and_then(|v| v.to_str().ok()) + .filter(|h| h.starts_with("Bearer ")) + .map(|h| &h[7..]) + .ok_or("No token found")?; + + let mut validation = Validation::new(Algorithm::RS256); + validation.set_required_spec_claims(&["exp", "sub"]); + let token_data = decode::(auth_header, &self.decoding_key, &validation)?; + + Ok(token_data.claims) + } +} + +impl Middleware for JwtMiddleware { + fn run(&self, mut req: Request) -> MiddlewareFuture<'_> { + let path = req.uri().path().to_string(); + let public_routes = self.public_routes.clone(); + + Box::pin(async move { + if public_routes.contains(&path) { + return MiddlewareResult::Continue(req); + } + + match self.validate_request(&req) { + Ok(claims) => { + req.extensions_mut().insert(claims); + MiddlewareResult::Continue(req) + } + Err(e) => { + error!(target: "auth", "JWT validation failed: {}", e); + let res = Responder::unauthorized().expect("Responder failed"); + MiddlewareResult::Respond(res) + } + } + }) + } +} diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs new file mode 100644 index 0000000..f546e54 --- /dev/null +++ b/src/middleware/mod.rs @@ -0,0 +1,26 @@ +mod api_key; +mod auth_types; +mod ip_filter; +mod jwt; + +use http::{Request, Response}; +use http_body_util::Full; +use hyper::body::{Bytes, Incoming}; +use std::future::Future; +use std::pin::Pin; + +pub enum MiddlewareResult { + Continue(Request), + Respond(Response>), +} + +pub type MiddlewareFuture<'a> = Pin + Send + 'a>>; + +pub trait Middleware: Send + Sync { + fn run<'a>(&'a self, req: Request) -> MiddlewareFuture<'a>; +} + +pub use api_key::ApiKeyMiddleware; +pub use auth_types::Claims; +pub use ip_filter::IpFilterMiddleware; +pub use jwt::JwtMiddleware; diff --git a/src/responder.rs b/src/responder.rs index 50cf549..035f078 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -1,4 +1,4 @@ -use http::{header::CONTENT_TYPE, response::Builder, Response}; +use http::{header::CONTENT_TYPE, Response, StatusCode}; use http_body_util::Full; use hyper::body::Bytes; use serde::Serialize; @@ -8,50 +8,52 @@ pub struct Responder; impl Responder { pub fn not_found() -> Result>, Infallible> { - Self::response_using_builder(Self::create_builder(404), "Not Found") + Self::text_using_status(StatusCode::NOT_FOUND.as_u16(), "Not Found") } - pub fn unathorized() -> Result>, Infallible> { - Self::response_using_builder(Self::create_builder(401), "Unathorized") + pub fn unauthorized() -> Result>, Infallible> { + Self::text_using_status(StatusCode::UNAUTHORIZED.as_u16(), "Unauthorized") } pub fn text(response: &str) -> Result>, Infallible> { - Self::response_using_builder(Self::create_builder(200), response) + Self::text_using_status(StatusCode::OK.as_u16(), response) } - pub fn json(json: &T) -> Result>, Infallible> - where - T: Serialize, - { - Self::json_using_status(200, json) + pub fn json(json: &T) -> Result>, Infallible> { + Self::json_using_status(StatusCode::OK.as_u16(), json) } pub fn text_using_status( status: u16, response: &str, ) -> Result>, Infallible> { - Self::response_using_builder(Self::create_builder(status), response) + let builder = Response::builder().status(status); + Self::build_response(builder, response.to_string().into()) } - pub fn json_using_status(status: u16, json: &T) -> Result>, Infallible> - where - T: Serialize, - { - let builder = Self::create_builder(status).header(CONTENT_TYPE, "application/json"); - - Self::response_using_builder(builder, &serde_json::to_string(json).unwrap()) - } - - fn response_using_builder( - builder: Builder, - response: &str, + pub fn json_using_status( + status: u16, + json: &T, ) -> Result>, Infallible> { - Ok(builder - .body(Full::::from(response.to_string())) - .unwrap()) + let builder = Response::builder() + .status(status) + .header(CONTENT_TYPE, "application/json"); + + match serde_json::to_string(json) { + Ok(body) => Self::build_response(builder, body.into()), + Err(e) => Self::text_using_status(500, &format!("JSON Error: {}", e)), + } } - fn create_builder(status: u16) -> Builder { - Response::builder().status(status) + // Método privado interno para centralizar la construcción + fn build_response( + builder: http::response::Builder, + body: Bytes, + ) -> Result>, Infallible> { + // En un servidor web real, un error de construcción aquí es casi imposible, + // pero manejarlo formalmente es mejor que hacer unwrap() + Ok(builder + .body(Full::new(body)) + .unwrap_or_else(|_| Response::new(Full::new(Bytes::from("Internal Server Error"))))) } } diff --git a/src/server.rs b/src/server.rs index dc2ac98..bb33a59 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,8 +1,12 @@ -use crate::{builder::ServerBuilder, config::ServerConfig, responder::Responder}; +use crate::{ + builder::ServerBuilder, + config::ServerConfig, + middleware::{Middleware, MiddlewareResult}, +}; use http1::Builder; use http_body_util::Full; use hyper::{body::Incoming, server::conn::http1, service::service_fn, Request, Response}; -use hyper_util::rt::{TokioIo, TokioTimer}; +use hyper_util::rt::TokioIo; use log::error; use std::{convert::Infallible, future::Future, net::SocketAddr, sync::Arc}; use tokio::{net::TcpListener, spawn}; @@ -10,12 +14,14 @@ use tokio_util::bytes::Bytes; pub struct Server { pub config: Arc, + pub middlewares: Arc>>, } impl Server { pub fn builder() -> ServerBuilder { ServerBuilder { config: ServerConfig::default(), + middlewares: vec![], } } @@ -27,56 +33,51 @@ impl Server { let addr: SocketAddr = format!("{}:{}", self.config.ip, self.config.port) .parse() .expect("Invalid IP or port"); - let listener = TcpListener::bind(addr).await.unwrap(); + let listener = TcpListener::bind(addr) + .await + .expect("Failed to bind to address"); let handler = Arc::new(handler); + + let shared_middlewares = self.middlewares; loop { let (tcp, client_addr) = match listener.accept().await { Ok(conn) => conn, - Err(error) => { - error!( - error = error.to_string().as_str(); - "Failed to accept connection" - ); + Err(e) => { + error!("Accept error: {}", e); continue; } }; + let io = TokioIo::new(tcp); - let config = Arc::clone(&self.config); - let handler = Arc::clone(&handler); + let mws = Arc::clone(&shared_middlewares); + let h = Arc::clone(&handler); + let client_ip = client_addr.ip(); + spawn(async move { - if let Err(error) = Builder::new() - .timer(TokioTimer::new()) - .serve_connection( - io, - service_fn(move |req| { - let config = Arc::clone(&config); - let handler = Arc::clone(&handler); + let conn = Builder::new().serve_connection( + io, + service_fn(move |mut req| { + let mws = Arc::clone(&mws); + let h = Arc::clone(&h); - async move { - if !config.is_ip_authorized(&client_addr.ip()) - || !config.is_req_authorized(&req) - { - if config.log_unauthorized { - error!(tag = "ban", - ip = client_addr.ip().to_string().as_str(); - "Unauthorized" - ); - } + async move { + req.extensions_mut().insert(client_ip); - Responder::unathorized() - } else { - handler(req).await + for mw in mws.iter() { + match mw.run(req).await { + MiddlewareResult::Continue(next_req) => req = next_req, + MiddlewareResult::Respond(res) => return Ok(res), } } - }), - ) - .await - { - error!(error = error.to_string().as_str(); - "Serving connection" - ); + h(req).await + } + }), + ); + + if let Err(err) = conn.await { + error!("Error serving connection: {:?}", err); } }); }