adding jwt middlewares, and improving overall middlewares structure and server

This commit is contained in:
2026-03-11 21:01:01 +01:00
parent 587498c7bc
commit 2093456d91
12 changed files with 1082 additions and 217 deletions

842
Cargo.lock generated
View File

@@ -8,12 +8,212 @@ version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 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]] [[package]]
name = "bytes" name = "bytes"
version = "1.11.1" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" 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]] [[package]]
name = "errno" name = "errno"
version = "0.3.14" version = "0.3.14"
@@ -21,9 +221,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [ dependencies = [
"libc", "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]] [[package]]
name = "futures-channel" name = "futures-channel"
version = "0.3.32" version = "0.3.32"
@@ -45,6 +261,57 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" 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]] [[package]]
name = "http" name = "http"
version = "1.4.0" version = "1.4.0"
@@ -132,10 +399,58 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
[[package]] [[package]]
name = "libc" name = "js-sys"
version = "0.2.182" version = "0.3.91"
source = "registry+https://github.com/rust-lang/crates.io-index" 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]] [[package]]
name = "log" name = "log"
@@ -157,7 +472,118 @@ checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
dependencies = [ dependencies = [
"libc", "libc",
"wasi", "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]] [[package]]
@@ -172,6 +598,51 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 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]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.106" version = "1.0.106"
@@ -183,13 +654,108 @@ dependencies = [
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.44" version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [ dependencies = [
"proc-macro2", "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]] [[package]]
name = "serde" name = "serde"
version = "1.0.228" version = "1.0.228"
@@ -235,12 +801,13 @@ dependencies = [
[[package]] [[package]]
name = "servme" name = "servme"
version = "0.1.0" version = "0.1.1"
dependencies = [ dependencies = [
"http", "http",
"http-body-util", "http-body-util",
"hyper", "hyper",
"hyper-util", "hyper-util",
"jsonwebtoken",
"log", "log",
"serde", "serde",
"serde_json", "serde_json",
@@ -248,6 +815,17 @@ dependencies = [
"tokio-util", "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]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.8" version = "1.4.8"
@@ -258,6 +836,28 @@ dependencies = [
"libc", "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]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.15.1" version = "1.15.1"
@@ -266,14 +866,36 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.6.2" version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
dependencies = [ dependencies = [
"libc", "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]] [[package]]
name = "syn" name = "syn"
version = "2.0.117" version = "2.0.117"
@@ -286,10 +908,61 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tokio" name = "thiserror"
version = "1.49.0" version = "2.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"libc", "libc",
"mio", "mio",
@@ -297,14 +970,14 @@ dependencies = [
"signal-hook-registry", "signal-hook-registry",
"socket2", "socket2",
"tokio-macros", "tokio-macros",
"windows-sys 0.61.2", "windows-sys",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.6.0" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -324,33 +997,81 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "typenum"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.24" version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "version_check"
version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.11.1+wasi-snapshot-preview1" version = "0.11.1+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 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]] [[package]]
name = "windows-link" name = "windows-link"
version = "0.2.1" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 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]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.2" version = "0.61.2"
@@ -361,69 +1082,30 @@ dependencies = [
] ]
[[package]] [[package]]
name = "windows-targets" name = "zerocopy"
version = "0.53.5" version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
dependencies = [ dependencies = [
"windows-link", "zerocopy-derive",
"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",
] ]
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "zerocopy-derive"
version = "0.53.1" version = "0.8.42"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "zeroize"
version = "0.53.1" version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
[[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"
[[package]] [[package]]
name = "zmij" name = "zmij"

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "servme" name = "servme"
version = "0.1.0" version = "0.1.1"
edition = "2021" edition = "2024"
[dependencies] [dependencies]
tokio = { version = "1.49.0", features = ["macros", "rt", "rt-multi-thread", "signal", "net"] } 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 = "1.4.0"
http-body-util = "0.1.3" http-body-util = "0.1.3"
jsonwebtoken = { version = "10", features = ["rust_crypto"] }
hyper = { version = "1.8.1", features = ["http1", "server"] } hyper = { version = "1.8.1", features = ["http1", "server"] }
hyper-util = { version = "0.1", features = ["http1", "server", "tokio"] } hyper-util = { version = "0.1", features = ["http1", "server", "tokio"] }

View File

@@ -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; use std::sync::Arc;
pub struct ServerBuilder { pub struct ServerBuilder {
pub config: ServerConfig, pub config: ServerConfig,
pub middlewares: Vec<Box<dyn Middleware>>,
} }
impl ServerBuilder { impl ServerBuilder {
@@ -12,36 +17,51 @@ impl ServerBuilder {
self self
} }
pub fn enable_private_ips(self) -> Self { pub fn add_api_key_middleware(mut self, api_key: &str) -> Self {
self.set_private_ips(true) self.middlewares
} .push(Box::new(ApiKeyMiddleware::new(api_key)));
pub fn set_private_ips(mut self, enabled: bool) -> Self {
self.config.private_ips = enabled;
self.update_ip_filter_state();
self self
} }
pub fn ips(mut self, ips: Vec<String>) -> Self { pub fn add_ip_filter_middleware(
self.config.ips = ips; mut self,
self.update_ip_filter_state(); allowed_ips: Vec<String>,
allow_private: bool,
) -> Self {
self.middlewares.push(Box::new(IpFilterMiddleware::new(
allowed_ips,
allow_private,
)));
self self
} }
pub fn add_jwt_middleware(mut self, public_key: &str, public_routes: Vec<String>) -> 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 { pub fn api_key(mut self, api_key: &str) -> Self {
self.config.api_key = Some(api_key.to_string()); self.config.api_key = Some(api_key.to_string());
self self
} }
pub fn middleware<M>(mut self, middleware: M) -> Self
where
M: Middleware + 'static,
{
self.middlewares.push(Box::new(middleware));
self
}
pub fn build(self) -> Server { pub fn build(self) -> Server {
Server { Server {
config: Arc::new(self.config), 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();
}
} }

View File

@@ -1,58 +1,9 @@
use http::Request;
use hyper::body::Incoming;
use std::net::IpAddr;
pub struct ServerConfig { pub struct ServerConfig {
pub ip: String, pub ip: String,
pub port: u16, pub port: u16,
// IP filtering
pub ip_filter: bool,
pub private_ips: bool,
pub ips: Vec<String>,
// Request filtering // Request filtering
pub api_key: Option<String>, pub api_key: Option<String>,
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<Incoming>) -> 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 { impl Default for ServerConfig {
@@ -61,13 +12,7 @@ impl Default for ServerConfig {
ip: "127.0.0.1".to_string(), ip: "127.0.0.1".to_string(),
port: 8080, port: 8080,
ip_filter: false,
private_ips: false,
ips: Vec::new(),
api_key: None, api_key: None,
log_unauthorized: true,
} }
} }
} }

View File

@@ -1,10 +1,12 @@
mod builder; mod builder;
mod config; mod config;
mod middleware;
mod requester; mod requester;
mod responder; mod responder;
mod server; mod server;
mod url_extract; mod url_extract;
pub use middleware::{Middleware, MiddlewareFuture, MiddlewareResult};
pub use requester::Requester; pub use requester::Requester;
pub use responder::Responder; pub use responder::Responder;
pub use server::Server; pub use server::Server;

42
src/middleware/api_key.rs Normal file
View File

@@ -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<Incoming>) -> 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())
}
}
})
}
}

View File

@@ -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
}
}

View File

@@ -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<String>,
allow_private: bool,
}
impl IpFilterMiddleware {
pub fn new(allowed_ips: Vec<String>, 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<Incoming>) -> MiddlewareFuture<'a> {
Box::pin(async move {
let client_ip = req.extensions().get::<IpAddr>();
match client_ip {
Some(ip) if self.is_authorized(ip) => MiddlewareResult::Continue(req),
_ => {
warn!("Unauthorized IP");
MiddlewareResult::Respond(Responder::unauthorized().unwrap())
}
}
})
}
}

71
src/middleware/jwt.rs Normal file
View File

@@ -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<String>,
}
impl JwtMiddleware {
pub fn new(
public_key: &str,
public_routes: Vec<String>,
) -> Result<Self, Box<dyn std::error::Error + Send + Sync>> {
let decoding_key = DecodingKey::from_rsa_pem(public_key.as_bytes())?;
Ok(Self {
decoding_key,
public_routes,
})
}
fn validate_request(
&self,
req: &Request<Incoming>,
) -> Result<Claims, Box<dyn std::error::Error + Send + Sync>> {
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::<Claims>(auth_header, &self.decoding_key, &validation)?;
Ok(token_data.claims)
}
}
impl Middleware for JwtMiddleware {
fn run(&self, mut req: Request<Incoming>) -> 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)
}
}
})
}
}

26
src/middleware/mod.rs Normal file
View File

@@ -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<Incoming>),
Respond(Response<Full<Bytes>>),
}
pub type MiddlewareFuture<'a> = Pin<Box<dyn Future<Output = MiddlewareResult> + Send + 'a>>;
pub trait Middleware: Send + Sync {
fn run<'a>(&'a self, req: Request<Incoming>) -> MiddlewareFuture<'a>;
}
pub use api_key::ApiKeyMiddleware;
pub use auth_types::Claims;
pub use ip_filter::IpFilterMiddleware;
pub use jwt::JwtMiddleware;

View File

@@ -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 http_body_util::Full;
use hyper::body::Bytes; use hyper::body::Bytes;
use serde::Serialize; use serde::Serialize;
@@ -8,50 +8,52 @@ pub struct Responder;
impl Responder { impl Responder {
pub fn not_found() -> Result<Response<Full<Bytes>>, Infallible> { pub fn not_found() -> Result<Response<Full<Bytes>>, 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<Response<Full<Bytes>>, Infallible> { pub fn unauthorized() -> Result<Response<Full<Bytes>>, Infallible> {
Self::response_using_builder(Self::create_builder(401), "Unathorized") Self::text_using_status(StatusCode::UNAUTHORIZED.as_u16(), "Unauthorized")
} }
pub fn text(response: &str) -> Result<Response<Full<Bytes>>, Infallible> { pub fn text(response: &str) -> Result<Response<Full<Bytes>>, Infallible> {
Self::response_using_builder(Self::create_builder(200), response) Self::text_using_status(StatusCode::OK.as_u16(), response)
} }
pub fn json<T>(json: &T) -> Result<Response<Full<Bytes>>, Infallible> pub fn json<T: Serialize>(json: &T) -> Result<Response<Full<Bytes>>, Infallible> {
where Self::json_using_status(StatusCode::OK.as_u16(), json)
T: Serialize,
{
Self::json_using_status(200, json)
} }
pub fn text_using_status( pub fn text_using_status(
status: u16, status: u16,
response: &str, response: &str,
) -> Result<Response<Full<Bytes>>, Infallible> { ) -> Result<Response<Full<Bytes>>, 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<T>(status: u16, json: &T) -> Result<Response<Full<Bytes>>, Infallible> pub fn json_using_status<T: Serialize>(
where status: u16,
T: Serialize, json: &T,
{
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,
) -> Result<Response<Full<Bytes>>, Infallible> { ) -> Result<Response<Full<Bytes>>, Infallible> {
Ok(builder let builder = Response::builder()
.body(Full::<Bytes>::from(response.to_string())) .status(status)
.unwrap()) .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 { // Método privado interno para centralizar la construcción
Response::builder().status(status) fn build_response(
builder: http::response::Builder,
body: Bytes,
) -> Result<Response<Full<Bytes>>, 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")))))
} }
} }

View File

@@ -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 http1::Builder;
use http_body_util::Full; use http_body_util::Full;
use hyper::{body::Incoming, server::conn::http1, service::service_fn, Request, Response}; 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 log::error;
use std::{convert::Infallible, future::Future, net::SocketAddr, sync::Arc}; use std::{convert::Infallible, future::Future, net::SocketAddr, sync::Arc};
use tokio::{net::TcpListener, spawn}; use tokio::{net::TcpListener, spawn};
@@ -10,12 +14,14 @@ use tokio_util::bytes::Bytes;
pub struct Server { pub struct Server {
pub config: Arc<ServerConfig>, pub config: Arc<ServerConfig>,
pub middlewares: Arc<Vec<Box<dyn Middleware>>>,
} }
impl Server { impl Server {
pub fn builder() -> ServerBuilder { pub fn builder() -> ServerBuilder {
ServerBuilder { ServerBuilder {
config: ServerConfig::default(), config: ServerConfig::default(),
middlewares: vec![],
} }
} }
@@ -27,56 +33,51 @@ impl Server {
let addr: SocketAddr = format!("{}:{}", self.config.ip, self.config.port) let addr: SocketAddr = format!("{}:{}", self.config.ip, self.config.port)
.parse() .parse()
.expect("Invalid IP or port"); .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 handler = Arc::new(handler);
let shared_middlewares = self.middlewares;
loop { loop {
let (tcp, client_addr) = match listener.accept().await { let (tcp, client_addr) = match listener.accept().await {
Ok(conn) => conn, Ok(conn) => conn,
Err(error) => { Err(e) => {
error!( error!("Accept error: {}", e);
error = error.to_string().as_str();
"Failed to accept connection"
);
continue; continue;
} }
}; };
let io = TokioIo::new(tcp); let io = TokioIo::new(tcp);
let config = Arc::clone(&self.config); let mws = Arc::clone(&shared_middlewares);
let handler = Arc::clone(&handler); let h = Arc::clone(&handler);
let client_ip = client_addr.ip();
spawn(async move { spawn(async move {
if let Err(error) = Builder::new() let conn = Builder::new().serve_connection(
.timer(TokioTimer::new()) io,
.serve_connection( service_fn(move |mut req| {
io, let mws = Arc::clone(&mws);
service_fn(move |req| { let h = Arc::clone(&h);
let config = Arc::clone(&config);
let handler = Arc::clone(&handler);
async move { async move {
if !config.is_ip_authorized(&client_addr.ip()) req.extensions_mut().insert(client_ip);
|| !config.is_req_authorized(&req)
{
if config.log_unauthorized {
error!(tag = "ban",
ip = client_addr.ip().to_string().as_str();
"Unauthorized"
);
}
Responder::unathorized() for mw in mws.iter() {
} else { match mw.run(req).await {
handler(req).await MiddlewareResult::Continue(next_req) => req = next_req,
MiddlewareResult::Respond(res) => return Ok(res),
} }
} }
}), h(req).await
) }
.await }),
{ );
error!(error = error.to_string().as_str();
"Serving connection" if let Err(err) = conn.await {
); error!("Error serving connection: {:?}", err);
} }
}); });
} }