Compare commits
21 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ed0b1dc22c | ||
205e1ed373 | |||
d618f10156 | |||
2756856286 | |||
e39c5152fd | |||
0f7b4e82ed | |||
01dda00800 | |||
e593decbed | |||
377090869f | |||
143c701620 | |||
396d8918bd | |||
fe41dc8339 | |||
5538820e03 | |||
7f2e84256a | |||
f65a496d51 | |||
614e1900b7 | |||
e135292817 | |||
da3e5aade0 | |||
2f7d558e02 | |||
ce0a1443dc | |||
cda627cfb5 |
418
Cargo.lock
generated
418
Cargo.lock
generated
@ -2,21 +2,6 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "addr2line"
|
|
||||||
version = "0.24.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
|
||||||
dependencies = [
|
|
||||||
"gimli",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "adler2"
|
|
||||||
version = "2.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
@ -28,9 +13,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.15"
|
version = "0.6.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"anstyle-parse",
|
"anstyle-parse",
|
||||||
@ -43,49 +28,44 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.8"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"utf8parse",
|
"utf8parse",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-query"
|
name = "anstyle-query"
|
||||||
version = "1.1.1"
|
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 = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-wincon"
|
name = "anstyle-wincon"
|
||||||
version = "3.0.4"
|
version = "3.0.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
|
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"windows-sys 0.52.0",
|
"once_cell",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.88"
|
version = "1.0.97"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356"
|
checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "autocfg"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-rs"
|
name = "aws-lc-rs"
|
||||||
@ -110,21 +90,6 @@ dependencies = [
|
|||||||
"fs_extra",
|
"fs_extra",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "backtrace"
|
|
||||||
version = "0.3.74"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
|
||||||
dependencies = [
|
|
||||||
"addr2line",
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"miniz_oxide",
|
|
||||||
"object",
|
|
||||||
"rustc-demangle",
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bindgen"
|
name = "bindgen"
|
||||||
version = "0.69.5"
|
version = "0.69.5"
|
||||||
@ -150,15 +115,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bytes"
|
|
||||||
version = "1.10.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
@ -219,18 +178,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colored"
|
name = "colored"
|
||||||
version = "2.1.0"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8"
|
checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -247,9 +206,9 @@ checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "env_filter"
|
name = "env_filter"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab"
|
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex",
|
||||||
@ -270,9 +229,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.1"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
@ -292,11 +251,8 @@ dependencies = [
|
|||||||
"ignore-result",
|
"ignore-result",
|
||||||
"log",
|
"log",
|
||||||
"rustls",
|
"rustls",
|
||||||
"serde_json",
|
|
||||||
"serde_yml",
|
"serde_yml",
|
||||||
"tokio",
|
"threadpool",
|
||||||
"tokio-io-timeout",
|
|
||||||
"tokio-rustls",
|
|
||||||
"wildmatch",
|
"wildmatch",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -329,12 +285,6 @@ dependencies = [
|
|||||||
"wasi 0.14.2+wasi-0.2.4",
|
"wasi 0.14.2+wasi-0.2.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "gimli"
|
|
||||||
version = "0.31.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -343,9 +293,15 @@ checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.15.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "home"
|
name = "home"
|
||||||
@ -364,9 +320,9 @@ checksum = "665ff4dce8edd10d490641ccb78949832f1ddbff02c584fb1f85ab888fe0e50c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.5.0"
|
version = "2.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
|
checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
@ -389,15 +345,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.11"
|
version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jiff"
|
name = "jiff"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c102670231191d07d37a35af3eb77f1f0dbf7a71be51a962dcd57ea607be7260"
|
checksum = "1f33145a5cbea837164362c7bd596106eb7c5198f97d1ba6f6ebb3223952e488"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jiff-static",
|
"jiff-static",
|
||||||
"log",
|
"log",
|
||||||
@ -408,9 +364,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jiff-static"
|
name = "jiff-static"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4cdde31a9d349f1b1f51a0b3714a5940ac022976f4b49485fc04be052b183b4c"
|
checksum = "43ce13c40ec6956157a3635d97a1ee2df323b263f09ea14165131289cb0f5c19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -452,7 +408,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -471,16 +427,6 @@ version = "0.4.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "lock_api"
|
|
||||||
version = "0.4.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
|
||||||
dependencies = [
|
|
||||||
"autocfg",
|
|
||||||
"scopeguard",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.27"
|
version = "0.4.27"
|
||||||
@ -499,26 +445,6 @@ 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 = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "miniz_oxide"
|
|
||||||
version = "0.8.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ff70ce3e48ae43fa075863cef62e8b43b71a4f2382229920e0df362592919430"
|
|
||||||
dependencies = [
|
|
||||||
"adler2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mio"
|
|
||||||
version = "1.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@ -530,12 +456,13 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "num_cpus"
|
||||||
version = "0.36.7"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -544,35 +471,6 @@ version = "1.21.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot"
|
|
||||||
version = "0.12.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
"parking_lot_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "parking_lot_core"
|
|
||||||
version = "0.9.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall",
|
|
||||||
"smallvec",
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pin-project-lite"
|
|
||||||
version = "0.2.16"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "portable-atomic"
|
name = "portable-atomic"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
@ -590,9 +488,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.2.25"
|
version = "0.2.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033"
|
checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"syn",
|
"syn",
|
||||||
@ -622,20 +520,11 @@ version = "5.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.5.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.10.6"
|
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 = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -645,9 +534,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.7"
|
version = "0.4.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -656,9 +545,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
@ -674,12 +563,6 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustc-demangle"
|
|
||||||
version = "0.1.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@ -701,9 +584,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.25"
|
version = "0.23.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c"
|
checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"log",
|
"log",
|
||||||
@ -734,15 +617,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
version = "1.0.18"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "scopeguard"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
@ -764,18 +641,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_json"
|
|
||||||
version = "1.0.140"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
|
||||||
dependencies = [
|
|
||||||
"itoa",
|
|
||||||
"memchr",
|
|
||||||
"ryu",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yml"
|
name = "serde_yml"
|
||||||
version = "0.0.12"
|
version = "0.0.12"
|
||||||
@ -797,31 +662,6 @@ version = "1.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "signal-hook-registry"
|
|
||||||
version = "1.4.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.15.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "socket2"
|
|
||||||
version = "0.5.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "subtle"
|
name = "subtle"
|
||||||
version = "2.6.1"
|
version = "2.6.1"
|
||||||
@ -840,59 +680,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "threadpool"
|
||||||
version = "1.44.2"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"num_cpus",
|
||||||
"bytes",
|
|
||||||
"libc",
|
|
||||||
"mio",
|
|
||||||
"parking_lot",
|
|
||||||
"pin-project-lite",
|
|
||||||
"signal-hook-registry",
|
|
||||||
"socket2",
|
|
||||||
"tokio-macros",
|
|
||||||
"windows-sys 0.52.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-io-timeout"
|
|
||||||
version = "1.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
|
|
||||||
dependencies = [
|
|
||||||
"pin-project-lite",
|
|
||||||
"tokio",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-macros"
|
|
||||||
version = "2.5.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-rustls"
|
|
||||||
version = "0.26.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
|
|
||||||
dependencies = [
|
|
||||||
"rustls",
|
|
||||||
"tokio",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe"
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
@ -945,22 +745,13 @@ version = "2.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd"
|
checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.48.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.48.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -969,22 +760,7 @@ version = "0.59.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.6",
|
"windows-targets",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm 0.48.5",
|
|
||||||
"windows_aarch64_msvc 0.48.5",
|
|
||||||
"windows_i686_gnu 0.48.5",
|
|
||||||
"windows_i686_msvc 0.48.5",
|
|
||||||
"windows_x86_64_gnu 0.48.5",
|
|
||||||
"windows_x86_64_gnullvm 0.48.5",
|
|
||||||
"windows_x86_64_msvc 0.48.5",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -993,46 +769,28 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.6",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc 0.52.6",
|
"windows_aarch64_msvc",
|
||||||
"windows_i686_gnu 0.52.6",
|
"windows_i686_gnu",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc 0.52.6",
|
"windows_i686_msvc",
|
||||||
"windows_x86_64_gnu 0.52.6",
|
"windows_x86_64_gnu",
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
"windows_x86_64_gnullvm",
|
||||||
"windows_x86_64_msvc 0.52.6",
|
"windows_x86_64_msvc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
@ -1045,48 +803,24 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
|
@ -1,16 +1,13 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "flowgate"
|
name = "flowgate"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.44.2", features = ["full"] }
|
|
||||||
tokio-io-timeout = "1.2.0"
|
|
||||||
tokio-rustls = "0.26.2"
|
|
||||||
rustls = "0.23.25"
|
rustls = "0.23.25"
|
||||||
wildmatch = "2.4.0"
|
wildmatch = "2.4.0"
|
||||||
serde_yml = "0.0.12"
|
serde_yml = "0.0.12"
|
||||||
serde_json = "1.0.140"
|
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
colog = "1.3.0"
|
colog = "1.3.0"
|
||||||
ignore-result = "0.2.0"
|
ignore-result = "0.2.0"
|
||||||
|
threadpool = "1.8.1"
|
18
README.md
18
README.md
@ -3,22 +3,32 @@ HTTP requests redirection system
|
|||||||
|
|
||||||
Features:
|
Features:
|
||||||
- Request redirection
|
- Request redirection
|
||||||
- TLS support
|
- TLS support (via Rustls!)
|
||||||
- Keep-alive connections
|
- Keep-alive connections
|
||||||
- Sending IP in header (X-Real-IP)
|
- Sending IP in header (X-Real-IP)
|
||||||
|
- Multiple ip forwarding methods
|
||||||
|
- Accepts incoming ip forwarding
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
- Remove panics
|
|
||||||
- Creating trees of flowgate
|
|
||||||
- Filter by headers
|
- Filter by headers
|
||||||
- Modify response headers
|
- Modify response headers
|
||||||
- HTTP/3 full support
|
- HTTP/3 full support (quic/udp)
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
|
|
||||||
Firstly, download it from releases. or build from sources (read BUILD.md) \
|
Firstly, download it from releases. or build from sources (read BUILD.md) \
|
||||||
Just run it and configure in `conf.yml` file.
|
Just run it and configure in `conf.yml` file.
|
||||||
|
|
||||||
|
### Logging
|
||||||
|
|
||||||
|
To get all logs (with debug ones), set this env var:
|
||||||
|
|
||||||
|
```
|
||||||
|
RUST_LOG=debug
|
||||||
|
```
|
||||||
|
|
||||||
|
Read more: [env_logger](https://docs.rs/env_logger/latest/env_logger/#enabling-logging)
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### IP forwarding methods
|
### IP forwarding methods
|
||||||
|
21
conf.yml
21
conf.yml
@ -1,15 +1,16 @@
|
|||||||
http_host: localhost:80 # Http server host
|
http_host: localhost:80 # Http server host (optional)
|
||||||
https_host: localhost:443 # Https server host
|
https_host: localhost:443 # Https server host (optional)
|
||||||
|
|
||||||
connection_timeout: 10 # Read and write timeout of connections in seconds (optional, default - 10)
|
connection_timeout: 10 # Read and write timeout of connections in seconds (optional, default - 10)
|
||||||
incoming_ip_forwarding: none # Read IP forwarding on incoming connections (optional, default - none)
|
incoming_ip_forwarding: none # Read IP forwarding on incoming connections (optional, default - none)
|
||||||
|
threadpool_size: 10 # Size of the global threadpool (optional, default - 10)
|
||||||
|
|
||||||
sites:
|
sites:
|
||||||
- domain: localhost # Site domain (use wildcard matching)
|
- domain: localhost # Site domain (use wildcard matching)
|
||||||
host: localhost:8080 # Http server host
|
host: localhost:8080 # Http server host
|
||||||
ip_forwarding: simple # IP forwarding method type (optional, default - header)
|
ip_forwarding: simple # IP forwarding method type (optional, default - header)
|
||||||
enable_keep_alive: true # Enable keep-alive connections (optional, default - true)
|
enable_keep_alive: true # Enable keep-alive connections (optional, default - true)
|
||||||
support_keep_alive: true # Does server supports keep-alive connections (optional, default - true)
|
support_keep_alive: true # Does server supports keep-alive connections (optional, default - true)
|
||||||
# ssl_cert: "/path/to/public/certificate.txt" # Ssl public certificate file (optional)
|
# ssl_cert: "/path/to/public/certificate.txt" # Ssl public certificate file (optional)
|
||||||
# ssl_key: "/path/to/private/key.txt" # Ssl private key file (optional)
|
# ssl_key: "/path/to/private/key.txt" # Ssl private key file (optional)
|
||||||
replace_host: "meex.lol" # Replace Host header in requests to server (optional)
|
replace_host: "meex.lol" # Replace Host header in requests to server (optional)
|
@ -1,6 +1,6 @@
|
|||||||
use std::{fs, time::Duration};
|
use std::{fs, time::Duration};
|
||||||
|
|
||||||
use tokio::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
|
|
||||||
use serde_yml::{Number, Value};
|
use serde_yml::{Number, Value};
|
||||||
use wildmatch::WildMatch;
|
use wildmatch::WildMatch;
|
||||||
@ -19,8 +19,8 @@ pub struct SiteConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SiteConfig {
|
impl SiteConfig {
|
||||||
pub async fn connect(&self) -> Option<TcpStream> {
|
pub fn connect(&self) -> Option<TcpStream> {
|
||||||
TcpStream::connect(self.host.clone()).await.ok()
|
TcpStream::connect(self.host.clone()).ok()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,11 +51,11 @@ impl IpForwarding {
|
|||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub sites: Vec<SiteConfig>,
|
pub sites: Vec<SiteConfig>,
|
||||||
pub http_host: String,
|
pub http_host: Option<String>,
|
||||||
pub https_host: String,
|
pub https_host: Option<String>,
|
||||||
pub threadpool_size: usize,
|
|
||||||
pub connection_timeout: Duration,
|
pub connection_timeout: Duration,
|
||||||
pub incoming_ip_forwarding: IpForwarding
|
pub incoming_ip_forwarding: IpForwarding,
|
||||||
|
pub threadpool_size: usize
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
@ -63,11 +63,11 @@ impl Config {
|
|||||||
let file_content = fs::read_to_string(filename).ok()?;
|
let file_content = fs::read_to_string(filename).ok()?;
|
||||||
let doc = serde_yml::from_str::<Value>(file_content.as_str()).ok()?;
|
let doc = serde_yml::from_str::<Value>(file_content.as_str()).ok()?;
|
||||||
|
|
||||||
let http_host = doc["http_host"].as_str()?.to_string();
|
let http_host = doc.get("http_host").and_then(|o| Some(o.as_str()?.to_string()));
|
||||||
let https_host = doc["https_host"].as_str()?.to_string();
|
let https_host = doc.get("https_host").and_then(|o| Some(o.as_str()?.to_string()));
|
||||||
|
|
||||||
|
let threadpool_size = doc.get("threadpool_size").and_then(|o| Some(o.as_u64()? as usize + 2)).unwrap_or(12);
|
||||||
|
|
||||||
let threadpool_size = doc.get("threadpool_size")
|
|
||||||
.unwrap_or(&Value::Number(Number::from(10))).as_u64()? as usize;
|
|
||||||
let connection_timeout = Duration::from_secs(doc.get("connection_timeout")
|
let connection_timeout = Duration::from_secs(doc.get("connection_timeout")
|
||||||
.unwrap_or(&Value::Number(Number::from(10))).as_u64()?);
|
.unwrap_or(&Value::Number(Number::from(10))).as_u64()?);
|
||||||
let incoming_ip_forwarding = doc.get("incoming_ip_forwarding")
|
let incoming_ip_forwarding = doc.get("incoming_ip_forwarding")
|
||||||
@ -117,9 +117,9 @@ impl Config {
|
|||||||
sites,
|
sites,
|
||||||
http_host,
|
http_host,
|
||||||
https_host,
|
https_host,
|
||||||
threadpool_size,
|
|
||||||
connection_timeout,
|
connection_timeout,
|
||||||
incoming_ip_forwarding
|
incoming_ip_forwarding,
|
||||||
|
threadpool_size
|
||||||
}.clone())
|
}.clone())
|
||||||
}
|
}
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
pub mod config;
|
|
||||||
pub mod server;
|
|
||||||
pub mod tls;
|
|
@ -1,492 +0,0 @@
|
|||||||
use std::{
|
|
||||||
error::Error,
|
|
||||||
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
|
|
||||||
str::FromStr,
|
|
||||||
sync::Arc
|
|
||||||
};
|
|
||||||
|
|
||||||
use ignore_result::Ignore;
|
|
||||||
use tokio::{
|
|
||||||
io::{AsyncReadExt, AsyncWriteExt},
|
|
||||||
net::{TcpListener, TcpStream}
|
|
||||||
};
|
|
||||||
|
|
||||||
use log::info;
|
|
||||||
use tokio_io_timeout::TimeoutStream;
|
|
||||||
use tokio_rustls::TlsAcceptor;
|
|
||||||
|
|
||||||
use crate::tls::create_server_config;
|
|
||||||
|
|
||||||
use super::config::{
|
|
||||||
Config,
|
|
||||||
SiteConfig,
|
|
||||||
IpForwarding
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct FlowgateServer {
|
|
||||||
config: Arc<Config>,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Connection {
|
|
||||||
stream: TcpStream,
|
|
||||||
config: SiteConfig,
|
|
||||||
keep_alive: bool,
|
|
||||||
host: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FlowgateServer {
|
|
||||||
pub fn new(config: Arc<Config>) -> Self {
|
|
||||||
FlowgateServer { config }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn start(self) {
|
|
||||||
let local_self = Arc::new(self);
|
|
||||||
|
|
||||||
tokio::spawn({
|
|
||||||
let local_self = local_self.clone();
|
|
||||||
async move { local_self.run_http().await.ignore(); }
|
|
||||||
});
|
|
||||||
|
|
||||||
tokio::spawn({
|
|
||||||
let local_self = local_self.clone();
|
|
||||||
async move { local_self.run_https().await.ignore(); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run_http(self: Arc<Self>) -> Result<(), Box<dyn Error>> {
|
|
||||||
let listener = TcpListener::bind(&self.config.http_host).await?;
|
|
||||||
|
|
||||||
info!("HTTP server runned on {}", &self.config.http_host);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let Ok((stream, addr)) = listener.accept().await else { break };
|
|
||||||
|
|
||||||
let local_self = self.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let mut stream = TimeoutStream::new(stream);
|
|
||||||
|
|
||||||
stream.set_write_timeout(Some(local_self.config.connection_timeout));
|
|
||||||
stream.set_read_timeout(Some(local_self.config.connection_timeout));
|
|
||||||
|
|
||||||
let mut stream = Box::pin(stream);
|
|
||||||
|
|
||||||
local_self.accept_stream(
|
|
||||||
&mut stream,
|
|
||||||
addr,
|
|
||||||
false
|
|
||||||
).await;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn run_https(self: Arc<Self>) -> Result<(), Box<dyn Error>> {
|
|
||||||
let listener = TcpListener::bind(&self.config.https_host).await?;
|
|
||||||
let acceptor = TlsAcceptor::from(Arc::new(create_server_config(self.config.clone()).await));
|
|
||||||
|
|
||||||
info!("HTTPS server runned on {}", &self.config.https_host);
|
|
||||||
|
|
||||||
loop {
|
|
||||||
let Ok((stream, addr)) = listener.accept().await else { break };
|
|
||||||
|
|
||||||
let local_self = self.clone();
|
|
||||||
let acceptor = acceptor.clone();
|
|
||||||
|
|
||||||
tokio::spawn(async move {
|
|
||||||
let mut stream = TimeoutStream::new(stream);
|
|
||||||
|
|
||||||
stream.set_write_timeout(Some(local_self.config.connection_timeout));
|
|
||||||
stream.set_read_timeout(Some(local_self.config.connection_timeout));
|
|
||||||
|
|
||||||
let Ok(mut stream) = acceptor.accept(Box::pin(stream)).await else { return };
|
|
||||||
|
|
||||||
local_self.accept_stream(
|
|
||||||
&mut stream,
|
|
||||||
addr,
|
|
||||||
true
|
|
||||||
).await;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn accept_stream(
|
|
||||||
self: Arc<Self>,
|
|
||||||
stream: &mut (impl AsyncReadExt + AsyncWriteExt + Unpin),
|
|
||||||
addr: SocketAddr,
|
|
||||||
https: bool
|
|
||||||
) -> Option<()> {
|
|
||||||
let mut conn = self.clone().read_request(stream, addr, https, None).await?;
|
|
||||||
|
|
||||||
if conn.keep_alive && conn.config.enable_keep_alive {
|
|
||||||
loop {
|
|
||||||
if !conn.config.support_keep_alive {
|
|
||||||
conn.stream.shutdown().await.ignore();
|
|
||||||
conn.stream = conn.config.connect().await?;
|
|
||||||
}
|
|
||||||
conn = self.clone().read_request(stream, addr, https, Some(conn)).await?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.stream.shutdown().await.ignore();
|
|
||||||
stream.shutdown().await.ok()?;
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn read_request(
|
|
||||||
self: Arc<Self>,
|
|
||||||
stream: &mut (impl AsyncReadExt + AsyncWriteExt + Unpin),
|
|
||||||
addr: SocketAddr,
|
|
||||||
https: bool,
|
|
||||||
conn: Option<Connection>
|
|
||||||
) -> Option<Connection> {
|
|
||||||
let mut addr = addr;
|
|
||||||
|
|
||||||
match &self.config.incoming_ip_forwarding {
|
|
||||||
IpForwarding::Simple => {
|
|
||||||
let mut header = Vec::new();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
|
|
||||||
while let Ok(1) = stream.read(&mut buf).await {
|
|
||||||
let byte = buf[0];
|
|
||||||
if byte == b'\n' { break }
|
|
||||||
header.push(byte);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = SocketAddr::from_str(&String::from_utf8(header).ok()?).ok()?;
|
|
||||||
},
|
|
||||||
IpForwarding::Modern => {
|
|
||||||
let mut ipver = [0; 1];
|
|
||||||
stream.read(&mut ipver).await.ok()?;
|
|
||||||
addr = match ipver[0] {
|
|
||||||
0x01 => {
|
|
||||||
let mut octets = [0; 4];
|
|
||||||
stream.read(&mut octets).await.ok()?;
|
|
||||||
let mut port = [0; 2];
|
|
||||||
stream.read(&mut port).await.ok()?;
|
|
||||||
let port = u16::from_be_bytes(port);
|
|
||||||
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(octets), port))
|
|
||||||
}, 0x02 => {
|
|
||||||
let mut octets = [0; 16];
|
|
||||||
stream.read(&mut octets).await.ok()?;
|
|
||||||
let mut port = [0; 2];
|
|
||||||
stream.read(&mut port).await.ok()?;
|
|
||||||
let port = u16::from_be_bytes(port);
|
|
||||||
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(octets), port, 0, 0))
|
|
||||||
}, _ => { return None },
|
|
||||||
};
|
|
||||||
},
|
|
||||||
_ => { }
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut head = Vec::new();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
while let Ok(1) = stream.read(&mut buf).await {
|
|
||||||
let byte = buf[0];
|
|
||||||
head.push(byte);
|
|
||||||
|
|
||||||
counter = match (counter, byte) {
|
|
||||||
(0, b'\r') => 1,
|
|
||||||
(1, b'\n') => 2,
|
|
||||||
(2, b'\r') => 3,
|
|
||||||
(3, b'\n') => break,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
head.truncate(head.len() - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if head.is_empty() { return None; }
|
|
||||||
|
|
||||||
let head_str = String::from_utf8(head.clone()).ok()?;
|
|
||||||
let head_str = head_str.trim_matches(char::from(0)).to_string();
|
|
||||||
|
|
||||||
let mut head_lines = head_str.split("\r\n");
|
|
||||||
|
|
||||||
let status = head_lines.next()?;
|
|
||||||
let status_seq: Vec<&str> = status.split(" ").collect();
|
|
||||||
|
|
||||||
let headers: Vec<(&str, &str)> = head_lines
|
|
||||||
.filter(|l| l.contains(": "))
|
|
||||||
.map(|l| l.split_once(": ").unwrap())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let is_chunked = headers.iter()
|
|
||||||
.find(|o| o.0.to_lowercase() == "transfer-encoding")
|
|
||||||
.map(|o| o.1.split(",").map(|x| x.trim_matches(' ').to_string()).collect::<Vec<String>>())
|
|
||||||
.map(|o| o.contains(&"chunked".to_string()))
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if let IpForwarding::Header(header) = &self.config.incoming_ip_forwarding {
|
|
||||||
if let Some(ip) = headers.iter().find(|o| o.0 == header).map(|o| o.1) {
|
|
||||||
addr = SocketAddr::from_str(ip).ok()?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut conn: Connection = if conn.is_none() {
|
|
||||||
let mut host = String::new();
|
|
||||||
let mut keep_alive = false;
|
|
||||||
|
|
||||||
for (key, value) in &headers {
|
|
||||||
match key.to_lowercase().as_str() {
|
|
||||||
"host" => host = value.to_string(),
|
|
||||||
"connection" => keep_alive = *value == "keep-alive",
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let site = self.config.get_site(&host)?.clone();
|
|
||||||
|
|
||||||
Connection {
|
|
||||||
stream: site.connect().await?,
|
|
||||||
config: site,
|
|
||||||
keep_alive,
|
|
||||||
host
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
conn?
|
|
||||||
};
|
|
||||||
|
|
||||||
let content_length = headers
|
|
||||||
.iter()
|
|
||||||
.filter(|(k, _)| k.to_lowercase() == "content-length")
|
|
||||||
.next()
|
|
||||||
.map(|o| o.1.parse().ok())
|
|
||||||
.flatten()
|
|
||||||
.unwrap_or(0usize);
|
|
||||||
|
|
||||||
let mut reqbuf: Vec<u8> = Vec::new();
|
|
||||||
|
|
||||||
if let Some(replace_host) = conn.config.replace_host.clone() {
|
|
||||||
let mut new_head = Vec::new();
|
|
||||||
let mut is_status = true;
|
|
||||||
|
|
||||||
for line in head_str.split("\r\n") {
|
|
||||||
if is_status {
|
|
||||||
new_head.append(&mut line.as_bytes().to_vec());
|
|
||||||
is_status = false;
|
|
||||||
} else {
|
|
||||||
new_head.append(&mut b"\r\n".to_vec());
|
|
||||||
let (key, _) = line.split_once(": ")?;
|
|
||||||
if key.to_lowercase() == "host" {
|
|
||||||
new_head.append(&mut key.as_bytes().to_vec());
|
|
||||||
new_head.append(&mut b": ".to_vec());
|
|
||||||
new_head.append(&mut replace_host.as_bytes().to_vec());
|
|
||||||
} else {
|
|
||||||
new_head.append(&mut line.as_bytes().to_vec());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
head = new_head;
|
|
||||||
}
|
|
||||||
|
|
||||||
match &conn.config.ip_forwarding {
|
|
||||||
IpForwarding::Header(header) => {
|
|
||||||
reqbuf.append(&mut status.to_string().as_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut b"\r\n".to_vec());
|
|
||||||
for (key, value) in String::from_utf8(head.clone()).ok()?
|
|
||||||
.split("\r\n")
|
|
||||||
.skip(1)
|
|
||||||
.filter_map(|o| o.split_once(": ")) {
|
|
||||||
if *key.to_lowercase() == header.to_lowercase() { continue }
|
|
||||||
reqbuf.append(&mut key.to_string().as_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut b": ".to_vec());
|
|
||||||
reqbuf.append(&mut value.to_string().as_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut b"\r\n".to_vec());
|
|
||||||
}
|
|
||||||
reqbuf.append(&mut header.as_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut b": ".to_vec());
|
|
||||||
reqbuf.append(&mut addr.to_string().as_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut b"\r\n\r\n".to_vec());
|
|
||||||
},
|
|
||||||
IpForwarding::Simple => {
|
|
||||||
reqbuf.append(&mut addr.to_string().as_bytes().to_vec());
|
|
||||||
reqbuf.push(b'\n');
|
|
||||||
reqbuf.append(&mut head.clone());
|
|
||||||
reqbuf.append(&mut b"\r\n\r\n".to_vec());
|
|
||||||
},
|
|
||||||
IpForwarding::Modern => {
|
|
||||||
reqbuf.push(if addr.is_ipv4() { 0x01 } else { 0x02 });
|
|
||||||
match addr.ip() {
|
|
||||||
IpAddr::V4(ip) => {
|
|
||||||
reqbuf.append(&mut ip.octets().to_vec());
|
|
||||||
}, IpAddr::V6(ip) => {
|
|
||||||
reqbuf.append(&mut ip.octets().to_vec());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reqbuf.append(&mut addr.port().to_be_bytes().to_vec());
|
|
||||||
reqbuf.append(&mut head.clone());
|
|
||||||
reqbuf.append(&mut b"\r\n\r\n".to_vec());
|
|
||||||
},
|
|
||||||
IpForwarding::None => {
|
|
||||||
reqbuf.append(&mut head.clone());
|
|
||||||
reqbuf.append(&mut b"\r\n\r\n".to_vec());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.stream.write_all(&reqbuf).await.ok()?;
|
|
||||||
|
|
||||||
if content_length > 0 {
|
|
||||||
let mut read = 0usize;
|
|
||||||
let mut buf = vec![0; 4096];
|
|
||||||
while let Ok(size) = stream.read(&mut buf).await {
|
|
||||||
if size == 0 { break }
|
|
||||||
read += size;
|
|
||||||
buf.truncate(size);
|
|
||||||
conn.stream.write_all(&buf).await.ok()?;
|
|
||||||
buf = vec![0; 4096];
|
|
||||||
if read >= content_length { break }
|
|
||||||
}
|
|
||||||
} else if is_chunked {
|
|
||||||
loop {
|
|
||||||
let mut length = Vec::new();
|
|
||||||
{
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
while let Ok(1) = stream.read(&mut buf).await {
|
|
||||||
let byte = buf[0];
|
|
||||||
length.push(byte);
|
|
||||||
|
|
||||||
counter = match (counter, byte) {
|
|
||||||
(0, b'\r') => 1,
|
|
||||||
(1, b'\n') => break,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
conn.stream.write_all(&length).await.ok()?;
|
|
||||||
|
|
||||||
length.truncate(length.len() - 2);
|
|
||||||
}
|
|
||||||
let length = String::from_utf8(length).ok()?;
|
|
||||||
let length = usize::from_str_radix(length.as_str(), 16).ok()?;
|
|
||||||
let mut data = vec![0u8; length+2];
|
|
||||||
stream.read_exact(&mut data).await.ok()?;
|
|
||||||
|
|
||||||
conn.stream.write_all(&data).await.ok()?;
|
|
||||||
if length == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if conn.config.support_keep_alive {
|
|
||||||
let mut head = Vec::new();
|
|
||||||
|
|
||||||
{
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
while let Ok(1) = conn.stream.read(&mut buf).await {
|
|
||||||
let byte = buf[0];
|
|
||||||
head.push(byte);
|
|
||||||
|
|
||||||
stream.write_all(&buf).await.ok()?;
|
|
||||||
|
|
||||||
counter = match (counter, byte) {
|
|
||||||
(0, b'\r') => 1,
|
|
||||||
(1, b'\n') => 2,
|
|
||||||
(2, b'\r') => 3,
|
|
||||||
(3, b'\n') => break,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
head.truncate(head.len() - 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
if head.is_empty() { return None; }
|
|
||||||
|
|
||||||
let head_str = String::from_utf8(head.clone()).ok()?;
|
|
||||||
let head_str = head_str.trim_matches(char::from(0));
|
|
||||||
|
|
||||||
let headers = head_str.split("\r\n")
|
|
||||||
.skip(1)
|
|
||||||
.filter(|l| l.contains(": "))
|
|
||||||
.map(|l| l.split_once(": ").unwrap())
|
|
||||||
.map(|(k,v)| (k.to_lowercase(),v.to_string()))
|
|
||||||
.collect::<Vec<(String,String)>>();
|
|
||||||
|
|
||||||
let content_length = headers.iter()
|
|
||||||
.find(|(k, _)| k == "content-length")
|
|
||||||
.map(|o| o.1.parse().ok())
|
|
||||||
.flatten()
|
|
||||||
.unwrap_or(0usize);
|
|
||||||
|
|
||||||
let is_chunked = headers.iter()
|
|
||||||
.find(|o| o.0.to_lowercase() == "transfer-encoding")
|
|
||||||
.map(|o| o.1.split(",").map(|x| x.trim_matches(' ').to_string()).collect::<Vec<String>>())
|
|
||||||
.map(|o| o.contains(&"chunked".to_string()))
|
|
||||||
.unwrap_or(false);
|
|
||||||
|
|
||||||
if content_length > 0 {
|
|
||||||
let mut read = 0usize;
|
|
||||||
let mut buf = vec![0; 4096];
|
|
||||||
while let Ok(size) = conn.stream.read(&mut buf).await {
|
|
||||||
if size == 0 { break }
|
|
||||||
read += size;
|
|
||||||
buf.truncate(size);
|
|
||||||
stream.write_all(&buf).await.ok()?;
|
|
||||||
buf = vec![0; 4096];
|
|
||||||
if read == content_length { break }
|
|
||||||
}
|
|
||||||
} else if is_chunked {
|
|
||||||
loop {
|
|
||||||
let mut length = Vec::new();
|
|
||||||
{
|
|
||||||
let mut buf = [0; 1];
|
|
||||||
let mut counter = 0;
|
|
||||||
|
|
||||||
while let Ok(1) = conn.stream.read(&mut buf).await {
|
|
||||||
let byte = buf[0];
|
|
||||||
length.push(byte);
|
|
||||||
|
|
||||||
counter = match (counter, byte) {
|
|
||||||
(0, b'\r') => 1,
|
|
||||||
(1, b'\n') => break,
|
|
||||||
_ => 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
stream.write_all(&length).await.ok()?;
|
|
||||||
|
|
||||||
length.truncate(length.len() - 2);
|
|
||||||
}
|
|
||||||
let length = String::from_utf8(length).ok()?;
|
|
||||||
let length = usize::from_str_radix(length.as_str(), 16).ok()?;
|
|
||||||
let mut data = vec![0u8; length+2];
|
|
||||||
conn.stream.read_exact(&mut data).await.ok()?;
|
|
||||||
|
|
||||||
stream.write_all(&data).await.ok()?;
|
|
||||||
if length == 0 {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let mut buf = vec![0;1024];
|
|
||||||
while let Ok(n) = conn.stream.read(&mut buf).await {
|
|
||||||
if n == 0 { break }
|
|
||||||
buf.truncate(n);
|
|
||||||
stream.write_all(&buf).await.ok()?;
|
|
||||||
buf = vec![0;1024];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info!("{addr} > {} {}://{}{}", status_seq[0], if https { "https" } else { "http" }, conn.host, status_seq[1]);
|
|
||||||
|
|
||||||
Some(conn)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,7 @@
|
|||||||
pub mod flowgate;
|
pub mod config;
|
||||||
|
pub mod server;
|
||||||
|
pub mod tls;
|
||||||
|
|
||||||
pub use flowgate::*;
|
pub use config::*;
|
||||||
|
pub use server::*;
|
||||||
|
pub use tls::*;
|
@ -3,8 +3,7 @@ use std::{fs, path::Path, sync::Arc};
|
|||||||
use flowgate::{config::Config, server::FlowgateServer};
|
use flowgate::{config::Config, server::FlowgateServer};
|
||||||
use ignore_result::Ignore;
|
use ignore_result::Ignore;
|
||||||
|
|
||||||
#[tokio::main]
|
fn main() {
|
||||||
async fn main() {
|
|
||||||
colog::init();
|
colog::init();
|
||||||
|
|
||||||
if !Path::new("conf.yml").exists() {
|
if !Path::new("conf.yml").exists() {
|
||||||
@ -14,7 +13,5 @@ async fn main() {
|
|||||||
let config = Arc::new(Config::parse("conf.yml").unwrap());
|
let config = Arc::new(Config::parse("conf.yml").unwrap());
|
||||||
let server = FlowgateServer::new(config.clone());
|
let server = FlowgateServer::new(config.clone());
|
||||||
|
|
||||||
server.start().await;
|
server.run();
|
||||||
|
|
||||||
loop {}
|
|
||||||
}
|
}
|
539
src/server.rs
Executable file
539
src/server.rs
Executable file
@ -0,0 +1,539 @@
|
|||||||
|
use std::{
|
||||||
|
error::Error, io::{BufRead, BufReader, Read, Write},
|
||||||
|
net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6, TcpListener, TcpStream},
|
||||||
|
str::FromStr, sync::Arc
|
||||||
|
};
|
||||||
|
|
||||||
|
use ignore_result::Ignore;
|
||||||
|
use log::{debug, info};
|
||||||
|
use rustls::{ServerConnection, StreamOwned};
|
||||||
|
use threadpool::ThreadPool;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
tls::create_server_config,
|
||||||
|
config::{
|
||||||
|
Config,
|
||||||
|
SiteConfig,
|
||||||
|
IpForwarding
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct FlowgateServer {
|
||||||
|
config: Arc<Config>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Connection {
|
||||||
|
stream: BufReader<TcpStream>,
|
||||||
|
config: SiteConfig,
|
||||||
|
keep_alive: bool,
|
||||||
|
host: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FlowgateServer {
|
||||||
|
pub fn new(config: Arc<Config>) -> Self {
|
||||||
|
FlowgateServer { config }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(self) {
|
||||||
|
self.start().join();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(self) -> ThreadPool {
|
||||||
|
let local_self = Arc::new(self);
|
||||||
|
|
||||||
|
let threadpool = ThreadPool::new(local_self.config.threadpool_size);
|
||||||
|
|
||||||
|
let mut handles = Vec::new();
|
||||||
|
|
||||||
|
handles.push(local_self.clone().start_http(&threadpool));
|
||||||
|
handles.push(local_self.clone().start_https(&threadpool));
|
||||||
|
|
||||||
|
threadpool
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_http(self: Arc<Self>, threadpool: &ThreadPool) {
|
||||||
|
threadpool.execute({
|
||||||
|
let local_self = self.clone();
|
||||||
|
let threadpool = threadpool.clone();
|
||||||
|
move || { local_self.run_http(&threadpool).ignore(); }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_https(self: Arc<Self>, threadpool: &ThreadPool) {
|
||||||
|
threadpool.execute({
|
||||||
|
let local_self = self.clone();
|
||||||
|
let threadpool = threadpool.clone();
|
||||||
|
move || { local_self.run_https(&threadpool).ignore(); }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_http(self: Arc<Self>, threadpool: &ThreadPool) -> Result<(), Box<dyn Error>> {
|
||||||
|
if let Some(host) = self.config.http_host.clone() {
|
||||||
|
let listener = TcpListener::bind(&host)?;
|
||||||
|
|
||||||
|
info!("HTTP server runned on {}", &host);
|
||||||
|
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
if let Ok(mut stream) = stream {
|
||||||
|
let local_self = self.clone();
|
||||||
|
|
||||||
|
let Ok(addr) = stream.peer_addr() else { continue };
|
||||||
|
let Ok(_) = stream.set_write_timeout(Some(local_self.config.connection_timeout)) else { continue };
|
||||||
|
let Ok(_) = stream.set_read_timeout(Some(local_self.config.connection_timeout)) else { continue };
|
||||||
|
|
||||||
|
threadpool.execute(move || {
|
||||||
|
debug!("{} open connection", addr);
|
||||||
|
|
||||||
|
local_self.accept_stream(
|
||||||
|
&mut stream,
|
||||||
|
addr,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!("{} close connection", addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_https(self: Arc<Self>, threadpool: &ThreadPool) -> Result<(), Box<dyn Error>> {
|
||||||
|
if let Some(host) = self.config.https_host.clone() {
|
||||||
|
let listener = TcpListener::bind(&host)?;
|
||||||
|
|
||||||
|
info!("HTTPS server runned on {}", &host);
|
||||||
|
|
||||||
|
let config = Arc::new(create_server_config(self.config.clone()));
|
||||||
|
|
||||||
|
for stream in listener.incoming() {
|
||||||
|
if let Ok(stream) = stream {
|
||||||
|
let local_self = self.clone();
|
||||||
|
let config = config.clone();
|
||||||
|
|
||||||
|
let Ok(addr) = stream.peer_addr() else { continue };
|
||||||
|
let Ok(_) = stream.set_write_timeout(Some(local_self.config.connection_timeout)) else { continue };
|
||||||
|
let Ok(_) = stream.set_read_timeout(Some(local_self.config.connection_timeout)) else { continue };
|
||||||
|
|
||||||
|
threadpool.execute(move || {
|
||||||
|
let Ok(connection) = ServerConnection::new(config) else { return };
|
||||||
|
debug!("{} open connection", addr);
|
||||||
|
let mut stream = StreamOwned::new(connection, stream);
|
||||||
|
|
||||||
|
while stream.conn.is_handshaking() {
|
||||||
|
let Ok(_) = stream.conn.complete_io(&mut stream.sock) else { debug!("{} close connection", addr);return };
|
||||||
|
}
|
||||||
|
local_self.accept_stream(
|
||||||
|
&mut stream,
|
||||||
|
addr,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!("{} close connection", addr);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accept_stream(
|
||||||
|
self: Arc<Self>,
|
||||||
|
stream: &mut (impl Read + Write + Shutdown),
|
||||||
|
addr: SocketAddr,
|
||||||
|
https: bool
|
||||||
|
) -> Option<()> {
|
||||||
|
let mut conn = self.clone().read_request(stream, addr, https, None)?;
|
||||||
|
|
||||||
|
if conn.keep_alive && conn.config.enable_keep_alive {
|
||||||
|
loop {
|
||||||
|
if !conn.config.support_keep_alive {
|
||||||
|
conn.stream.shutdown();
|
||||||
|
conn.stream = BufReader::new(conn.config.connect()?);
|
||||||
|
}
|
||||||
|
conn = self.clone().read_request(stream, addr, https, Some(conn))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.stream.shutdown();
|
||||||
|
stream.shutdown();
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_request(
|
||||||
|
self: Arc<Self>,
|
||||||
|
stream: &mut (impl Read + Write + Shutdown),
|
||||||
|
addr: SocketAddr,
|
||||||
|
https: bool,
|
||||||
|
conn: Option<Connection>
|
||||||
|
) -> Option<Connection> {
|
||||||
|
let mut addr = addr;
|
||||||
|
|
||||||
|
let mut stream = BufReader::new(stream);
|
||||||
|
|
||||||
|
match &self.config.incoming_ip_forwarding {
|
||||||
|
IpForwarding::Simple => {
|
||||||
|
let mut header = Vec::new();
|
||||||
|
stream.read_until(b'\n', &mut header).ok()?;
|
||||||
|
header.truncate(header.len()-1);
|
||||||
|
|
||||||
|
addr = SocketAddr::from_str(&String::from_utf8(header).ok()?).ok()?;
|
||||||
|
},
|
||||||
|
IpForwarding::Modern => {
|
||||||
|
let mut header = [0];
|
||||||
|
stream.read(&mut header).ok()?;
|
||||||
|
|
||||||
|
addr = match header[0] {
|
||||||
|
0x01 => {
|
||||||
|
let mut octets = [0; 4];
|
||||||
|
stream.read(&mut octets).ok()?;
|
||||||
|
|
||||||
|
let mut port = [0; 2];
|
||||||
|
stream.read(&mut port).ok()?;
|
||||||
|
let port = u16::from_be_bytes(port);
|
||||||
|
|
||||||
|
SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::from(octets), port))
|
||||||
|
}, 0x02 => {
|
||||||
|
let mut octets = [0; 16];
|
||||||
|
stream.read(&mut octets).ok()?;
|
||||||
|
|
||||||
|
let mut port = [0; 2];
|
||||||
|
stream.read(&mut port).ok()?;
|
||||||
|
let port = u16::from_be_bytes(port);
|
||||||
|
|
||||||
|
SocketAddr::V6(SocketAddrV6::new(Ipv6Addr::from(octets), port, 0, 0))
|
||||||
|
}, _ => { return None },
|
||||||
|
};
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut raw_status = read_until(&mut stream, b"\r\n")?;
|
||||||
|
|
||||||
|
let mut request = Vec::new();
|
||||||
|
request.append(&mut raw_status.clone());
|
||||||
|
|
||||||
|
raw_status.truncate(raw_status.len() - 2);
|
||||||
|
|
||||||
|
let status = String::from_utf8(raw_status.clone()).ok()?;
|
||||||
|
let status = status.split(" ").collect::<Vec<&str>>();
|
||||||
|
|
||||||
|
debug!("{} {} read status", addr, status[1]);
|
||||||
|
|
||||||
|
let mut content_length = 0;
|
||||||
|
let mut host = None;
|
||||||
|
let mut is_chunked = false;
|
||||||
|
let mut keep_alive = false;
|
||||||
|
|
||||||
|
let mut headers = Vec::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut header = read_until(&mut stream, b"\r\n")?;
|
||||||
|
header.truncate(header.len() - 2);
|
||||||
|
|
||||||
|
if header.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let header = String::from_utf8(header).ok()?;
|
||||||
|
let (key, value) = header.split_once(": ")?;
|
||||||
|
|
||||||
|
headers.push((key.to_string(), value.to_string()));
|
||||||
|
|
||||||
|
match key.to_lowercase().as_str() {
|
||||||
|
"transfer-encoding" => {
|
||||||
|
if value.contains("chunked") {
|
||||||
|
is_chunked = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"host" => {
|
||||||
|
host = Some(value.to_string());
|
||||||
|
},
|
||||||
|
"connection" => {
|
||||||
|
keep_alive = value.to_lowercase().contains("keep-alive");
|
||||||
|
},
|
||||||
|
"content-length" => {
|
||||||
|
content_length = value.parse::<usize>().ok()?;
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
if let IpForwarding::Header(header) = &self.config.incoming_ip_forwarding {
|
||||||
|
if key.to_lowercase() == header.to_lowercase() {
|
||||||
|
addr = SocketAddr::from_str(value).ok()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("{} {} read headers", addr, status[1]);
|
||||||
|
|
||||||
|
let mut conn: Connection = if conn.is_none() {
|
||||||
|
let host = host?;
|
||||||
|
let site = self.config.get_site(&host)?.clone();
|
||||||
|
|
||||||
|
Connection {
|
||||||
|
stream: BufReader::new(site.connect()?),
|
||||||
|
config: site,
|
||||||
|
keep_alive,
|
||||||
|
host
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
conn?
|
||||||
|
};
|
||||||
|
|
||||||
|
debug!("{} {} got connection", addr, status[1]);
|
||||||
|
|
||||||
|
|
||||||
|
match &conn.config.ip_forwarding {
|
||||||
|
IpForwarding::Simple => {
|
||||||
|
request.append(&mut addr.to_string().as_bytes().to_vec());
|
||||||
|
request.push(b'\n');
|
||||||
|
},
|
||||||
|
IpForwarding::Modern => {
|
||||||
|
match addr.ip() {
|
||||||
|
IpAddr::V4(ip) => {
|
||||||
|
request.push(0x01);
|
||||||
|
request.append(&mut ip.octets().to_vec());
|
||||||
|
}, IpAddr::V6(ip) => {
|
||||||
|
request.push(0x02);
|
||||||
|
request.append(&mut ip.octets().to_vec());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
request.append(&mut addr.port().to_be_bytes().to_vec());
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (key, value) in headers {
|
||||||
|
let mut value = value.to_string();
|
||||||
|
|
||||||
|
match key.to_lowercase().as_str() {
|
||||||
|
"host" => {
|
||||||
|
if let Some(replace_host) = conn.config.replace_host.clone() {
|
||||||
|
value = replace_host;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let IpForwarding::Header(header) = &conn.config.ip_forwarding {
|
||||||
|
if key.to_lowercase() == header.to_lowercase() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
request.append(&mut key.as_bytes().to_vec());
|
||||||
|
request.append(&mut b": ".to_vec());
|
||||||
|
request.append(&mut value.as_bytes().to_vec());
|
||||||
|
request.append(&mut b"\r\n".to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let IpForwarding::Header(header) = &conn.config.ip_forwarding {
|
||||||
|
request.append(&mut header.as_bytes().to_vec());
|
||||||
|
request.append(&mut b": ".to_vec());
|
||||||
|
request.append(&mut addr.to_string().as_bytes().to_vec());
|
||||||
|
request.append(&mut b"\r\n".to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
request.append(&mut b"\r\n".to_vec());
|
||||||
|
|
||||||
|
debug!("{:?}", String::from_utf8_lossy(&request));
|
||||||
|
|
||||||
|
conn.stream.get_mut().write_all(&request).ok()?;
|
||||||
|
|
||||||
|
debug!("{} {} sent request to server", addr, status[1]);
|
||||||
|
|
||||||
|
if content_length > 0 {
|
||||||
|
let buffer = stream.buffer().to_vec();
|
||||||
|
|
||||||
|
conn.stream.get_mut().write_all(&buffer).ok()?;
|
||||||
|
stream.consume(buffer.len());
|
||||||
|
|
||||||
|
let mut read = buffer.len();
|
||||||
|
|
||||||
|
debug!("{} {} send part of body to server", addr, status[1]);
|
||||||
|
|
||||||
|
while read < content_length {
|
||||||
|
let mut buf = vec![0; 4096];
|
||||||
|
let size = conn.stream.get_mut().read(&mut buf).ok()?;
|
||||||
|
|
||||||
|
if size == 0 { break }
|
||||||
|
|
||||||
|
buf.truncate(size);
|
||||||
|
read += size;
|
||||||
|
|
||||||
|
debug!("{} {} send response body part {} to clientr", addr, status[1], size);
|
||||||
|
|
||||||
|
stream.get_mut().write_all(&buf).ok()?;
|
||||||
|
}
|
||||||
|
} else if is_chunked {
|
||||||
|
transfer_chunked(&mut stream, conn.stream.get_mut())?;
|
||||||
|
} else {
|
||||||
|
let buffer = stream.buffer().to_vec();
|
||||||
|
|
||||||
|
conn.stream.get_mut().write_all(&buffer).ok()?;
|
||||||
|
stream.consume(buffer.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("{} {} send body to server", addr, status[1]);
|
||||||
|
|
||||||
|
if conn.config.support_keep_alive {
|
||||||
|
let mut response = Vec::new();
|
||||||
|
|
||||||
|
let raw_status = read_until(&mut conn.stream, b"\r\n")?;
|
||||||
|
|
||||||
|
response.append(&mut raw_status.clone());
|
||||||
|
|
||||||
|
let mut content_length = 0;
|
||||||
|
let mut is_chunked = false;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut header = read_until(&mut conn.stream, b"\r\n")?;
|
||||||
|
|
||||||
|
response.append(&mut header.clone());
|
||||||
|
|
||||||
|
if header.len() == 2 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.truncate(header.len() - 2);
|
||||||
|
|
||||||
|
let header = String::from_utf8(header).ok()?;
|
||||||
|
let (key, value) = header.split_once(": ")?;
|
||||||
|
|
||||||
|
match key.to_lowercase().as_str() {
|
||||||
|
"transfer-encoding" => {
|
||||||
|
if value.contains("chunked") {
|
||||||
|
is_chunked = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"content-length" => {
|
||||||
|
content_length = value.parse::<usize>().ok()?;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.get_mut().write_all(&response).ok()?;
|
||||||
|
|
||||||
|
debug!("{} {} send response header to clientr", addr, status[1]);
|
||||||
|
|
||||||
|
if content_length > 0 {
|
||||||
|
let buffer = conn.stream.buffer().to_vec();
|
||||||
|
|
||||||
|
stream.get_mut().write_all(&buffer).ok()?;
|
||||||
|
conn.stream.consume(buffer.len());
|
||||||
|
|
||||||
|
debug!("{} {} send response body part {} to clientr", addr, status[1], buffer.len());
|
||||||
|
|
||||||
|
let mut read = buffer.len();
|
||||||
|
|
||||||
|
while read < content_length {
|
||||||
|
let mut buf = vec![0; 4096];
|
||||||
|
let size = conn.stream.get_mut().read(&mut buf).ok()?;
|
||||||
|
|
||||||
|
if size == 0 { break }
|
||||||
|
|
||||||
|
buf.truncate(size);
|
||||||
|
read += size;
|
||||||
|
|
||||||
|
debug!("{} {} send response body part {} to clientr", addr, status[1], size);
|
||||||
|
|
||||||
|
stream.get_mut().write_all(&buf).ok()?;
|
||||||
|
}
|
||||||
|
} else if is_chunked {
|
||||||
|
transfer_chunked(&mut conn.stream, stream.get_mut())?;
|
||||||
|
} else {
|
||||||
|
let buffer = conn.stream.buffer().to_vec();
|
||||||
|
|
||||||
|
stream.get_mut().write_all(&buffer).ok()?;
|
||||||
|
conn.stream.consume(buffer.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("{} {} send response body to clientr", addr, status[1]);
|
||||||
|
} else {
|
||||||
|
let buffer = conn.stream.buffer();
|
||||||
|
|
||||||
|
stream.get_mut().write_all(buffer).ok()?;
|
||||||
|
conn.stream.consume(buffer.len());
|
||||||
|
|
||||||
|
let mut buf = vec![0;4096];
|
||||||
|
while let Ok(n) = conn.stream.get_mut().read(&mut buf) {
|
||||||
|
if n == 0 { break }
|
||||||
|
buf.truncate(n);
|
||||||
|
stream.get_mut().write_all(&buf).ok()?;
|
||||||
|
buf = vec![0;4096];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info!("{addr} > {} {}://{}{}", status[0], if https { "https" } else { "http" }, conn.host, status[1]);
|
||||||
|
|
||||||
|
Some(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_until(stream: &mut impl BufRead, delimiter: &[u8]) -> Option<Vec<u8>> {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
|
||||||
|
let last_byte = *delimiter.last()?;
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
let buf_len = stream.read_until(last_byte, &mut buf).ok()?;
|
||||||
|
debug!("read buf len until {} {:?}", buf_len, String::from_utf8_lossy(&buf));
|
||||||
|
if buf_len == 0 {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
data.append(&mut buf);
|
||||||
|
if data.ends_with(delimiter) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn transfer_chunked(src: &mut impl BufRead, dest: &mut impl Write) -> Option<()> {
|
||||||
|
loop {
|
||||||
|
let mut length = read_until(src, b"\r\n")?;
|
||||||
|
dest.write_all(&length).ok()?;
|
||||||
|
length.truncate(length.len()-2);
|
||||||
|
let length = String::from_utf8(length).ok()?;
|
||||||
|
let length = usize::from_str_radix(length.as_str(), 16).ok()?;
|
||||||
|
|
||||||
|
let mut data = vec![0u8; length+2];
|
||||||
|
src.read_exact(&mut data).ok()?;
|
||||||
|
dest.write_all(&data).ok()?;
|
||||||
|
|
||||||
|
if length == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Shutdown {
|
||||||
|
fn shutdown(&self);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Shutdown for TcpStream {
|
||||||
|
fn shutdown(&self) {
|
||||||
|
TcpStream::shutdown(self, std::net::Shutdown::Both).ignore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <T: Shutdown> Shutdown for BufReader<T> {
|
||||||
|
fn shutdown(&self) {
|
||||||
|
self.get_ref().shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <C, T: Read + Write + Shutdown> Shutdown for StreamOwned<C, T> {
|
||||||
|
fn shutdown(&self) {
|
||||||
|
self.sock.shutdown();
|
||||||
|
}
|
||||||
|
}
|
@ -39,7 +39,7 @@ struct ResolvesServerCertWildcard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ResolvesServerCertWildcard {
|
impl ResolvesServerCertWildcard {
|
||||||
pub async fn new(config: Arc<Config>) -> Self {
|
pub fn new(config: Arc<Config>) -> Self {
|
||||||
Self { config }
|
Self { config }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,8 +56,8 @@ impl ResolvesServerCert for ResolvesServerCertWildcard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn create_server_config(config: Arc<Config>) -> ServerConfig {
|
pub fn create_server_config(config: Arc<Config>) -> ServerConfig {
|
||||||
ServerConfig::builder()
|
ServerConfig::builder()
|
||||||
.with_no_client_auth()
|
.with_no_client_auth()
|
||||||
.with_cert_resolver(Arc::new(ResolvesServerCertWildcard::new(config).await))
|
.with_cert_resolver(Arc::new(ResolvesServerCertWildcard::new(config)))
|
||||||
}
|
}
|
32
tests/half_request.py
Executable file
32
tests/half_request.py
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = '172.16.1.32'
|
||||||
|
PORT = 80
|
||||||
|
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect((HOST, PORT))
|
||||||
|
|
||||||
|
s.send(b"""GET / HTTP/1.1\r
|
||||||
|
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r
|
||||||
|
Accept-Encoding: gzip, deflate, br, zstd\r
|
||||||
|
Accept-Language: en-US,en;q=0.9\r
|
||||||
|
Cache-Control: no-cache\r
|
||||||
|
Connection: keep-alive\r
|
||||||
|
Host: git.meex.lol\r
|
||||||
|
Pragma: no-cache\r
|
||||||
|
Sec-Fetch-Dest: document\r
|
||||||
|
Sec-Fetch-Mode: navigate\r
|
||||||
|
Sec-Fetch-Site: none\r
|
||||||
|
Sec-Fetch-User: ?1\r
|
||||||
|
Upgrade-Insecure-Requests: 1\r
|
||||||
|
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36\r
|
||||||
|
sec-ch-ua: \"Chromium\";v=\"135\", \"Not-A.Brand\";v=\"8\"\r
|
||||||
|
sec-ch-ua-mobile: ?0\r
|
||||||
|
sec-ch-ua-platform: \"Linux\"\r
|
||||||
|
\r
|
||||||
|
""")
|
||||||
|
|
||||||
|
content_length = 0
|
||||||
|
while True:
|
||||||
|
data = s.recv(1024)
|
||||||
|
print(data)
|
40
tests/http_client.py
Executable file
40
tests/http_client.py
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
import socket
|
||||||
|
|
||||||
|
HOST = '172.16.1.32'
|
||||||
|
PORT = 80
|
||||||
|
|
||||||
|
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||||
|
s.connect((HOST, PORT))
|
||||||
|
i = 0
|
||||||
|
while True:
|
||||||
|
s.send(b"""GET / HTTP/1.1\r
|
||||||
|
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7\r
|
||||||
|
Accept-Encoding: gzip, deflate, br, zstd\r
|
||||||
|
Accept-Language: en-US,en;q=0.9\r
|
||||||
|
Cache-Control: no-cache\r
|
||||||
|
Connection: keep-alive\r
|
||||||
|
Host: git.meex.lol\r
|
||||||
|
Pragma: no-cache\r
|
||||||
|
Sec-Fetch-Dest: document\r
|
||||||
|
Sec-Fetch-Mode: navigate\r
|
||||||
|
Sec-Fetch-Site: none\r
|
||||||
|
Sec-Fetch-User: ?1\r
|
||||||
|
Upgrade-Insecure-Requests: 1\r
|
||||||
|
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36\r
|
||||||
|
sec-ch-ua: \"Chromium\";v=\"135\", \"Not-A.Brand\";v=\"8\"\r
|
||||||
|
sec-ch-ua-mobile: ?0\r
|
||||||
|
sec-ch-ua-platform: \"Linux\"\r
|
||||||
|
\r
|
||||||
|
""")
|
||||||
|
|
||||||
|
content_length = 0
|
||||||
|
while content_length < 9392:
|
||||||
|
data = s.recv(1024)
|
||||||
|
if data:
|
||||||
|
content_length += len(data)
|
||||||
|
# print(data.decode("utf8", errors="ignore"), end="")
|
||||||
|
else:
|
||||||
|
print("sdfsdf")
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
print(i)
|
Loading…
Reference in New Issue
Block a user