Compare commits

...

3 commits

7 changed files with 564 additions and 541 deletions

592
Cargo.lock generated
View file

@ -2,6 +2,21 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "async-compression"
version = "0.3.12"
@ -15,6 +30,17 @@ dependencies = [
"tokio",
]
[[package]]
name = "async-trait"
version = "0.1.74"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
]
[[package]]
name = "atty"
version = "0.2.14"
@ -33,10 +59,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
[[package]]
name = "base64"
version = "0.13.0"
name = "axum"
version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
dependencies = [
"async-trait",
"axum-core",
"bitflags",
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"serde_json",
"serde_path_to_error",
"serde_urlencoded",
"sync_wrapper",
"tokio",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"mime",
"rustversion",
"tower-layer",
"tower-service",
]
[[package]]
name = "backtrace"
version = "0.3.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "binascii"
@ -59,15 +143,6 @@ version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]]
name = "bytes"
version = "1.1.0"
@ -144,24 +219,6 @@ dependencies = [
"os_str_bytes",
]
[[package]]
name = "cpufeatures"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469"
dependencies = [
"libc",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "fern"
version = "0.6.1"
@ -194,7 +251,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b"
dependencies = [
"futures-core",
"futures-sink",
]
[[package]]
@ -203,12 +259,6 @@ version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7"
[[package]]
name = "futures-sink"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508"
[[package]]
name = "futures-task"
version = "0.3.19"
@ -222,40 +272,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164"
dependencies = [
"futures-core",
"futures-sink",
"futures-task",
"pin-project-lite",
"pin-utils",
]
[[package]]
name = "generic-array"
version = "0.14.5"
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803"
dependencies = [
"typenum",
"version_check",
]
[[package]]
name = "h2"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9f1f717ddc7b2ba36df7e871fd88db79326551d3d6f1fc406fbfd28b582ff8e"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap",
"slab",
"tokio",
"tokio-util",
"tracing",
]
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
name = "hashbrown"
@ -263,31 +289,6 @@ version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
[[package]]
name = "headers"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c84c647447a07ca16f5fbd05b633e535cc41a08d2d74ab1e08648df53be9cb89"
dependencies = [
"base64",
"bitflags",
"bytes",
"headers-core",
"http",
"httpdate",
"mime",
"sha-1",
]
[[package]]
name = "headers-core"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
dependencies = [
"http",
]
[[package]]
name = "hermit-abi"
version = "0.1.19"
@ -299,20 +300,20 @@ dependencies = [
[[package]]
name = "http"
version = "0.2.6"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31f4c6746584866f0feabcc69893c5b51beef3831656a968ed7ae254cdc4fd03"
checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb"
dependencies = [
"bytes",
"fnv",
"itoa 1.0.1",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.4"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
@ -321,9 +322,9 @@ dependencies = [
[[package]]
name = "httparse"
version = "1.5.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
@ -333,22 +334,21 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "hyper"
version = "0.14.16"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa 0.4.8",
"itoa",
"pin-project-lite",
"socket2",
"socket2 0.4.10",
"tokio",
"tower-service",
"tracing",
@ -367,36 +367,21 @@ dependencies = [
[[package]]
name = "itoa"
version = "0.4.8"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
[[package]]
name = "itoa"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]]
name = "libc"
version = "0.2.126"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
[[package]]
name = "log"
version = "0.4.14"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if",
]
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "matches"
@ -404,6 +389,36 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "matchit"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
[[package]]
name = "maud"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0bab19cef8a7fe1c18a43e881793bfc9d4ea984befec3ae5bd0415abf3ecf00"
dependencies = [
"axum-core",
"http",
"itoa",
"maud_macros",
]
[[package]]
name = "maud_macros"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0be95d66c3024ffce639216058e5bae17a83ecaf266ffc6e4d060ad447c9eed2"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn 1.0.86",
]
[[package]]
name = "memchr"
version = "2.4.1"
@ -417,23 +432,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
[[package]]
name = "mime_guess"
version = "2.0.3"
name = "miniz_oxide"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212"
checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
dependencies = [
"mime",
"unicase",
"adler",
]
[[package]]
name = "mio"
version = "0.8.3"
version = "0.8.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys",
]
@ -468,16 +481,19 @@ dependencies = [
]
[[package]]
name = "once_cell"
version = "1.9.0"
name = "object"
version = "0.32.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0"
dependencies = [
"memchr",
]
[[package]]
name = "opaque-debug"
version = "0.3.0"
name = "once_cell"
version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]]
name = "os_str_bytes"
@ -508,14 +524,14 @@ checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 1.0.86",
]
[[package]]
name = "pin-project-lite"
version = "0.2.8"
version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e280fbe77cc62c91527259e9442153f4688736748d24660126286329742b4c6c"
checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
[[package]]
name = "pin-utils"
@ -530,53 +546,83 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
[[package]]
name = "proc-macro2"
version = "1.0.36"
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"unicode-xid",
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn 1.0.86",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.15"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145"
checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
[[package]]
name = "scoped-tls"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2"
[[package]]
name = "serde"
version = "1.0.136"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.136"
version = "1.0.193"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9"
checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
dependencies = [
"proc-macro2",
"quote",
"syn",
"syn 2.0.39",
]
[[package]]
@ -585,11 +631,21 @@ version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d23c1ba4cf0efd44be32017709280b32d1cea5c3f1275c3b6d9e8bc54f758085"
dependencies = [
"itoa 1.0.1",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "serde_path_to_error"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4beec8bce849d58d06238cb50db2e1c417cfeafa4c63f692b15c82b7c80f8335"
dependencies = [
"itoa",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.1"
@ -597,24 +653,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
dependencies = [
"form_urlencoded",
"itoa 1.0.1",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "sha-1"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6"
dependencies = [
"block-buffer",
"cfg-if",
"cpufeatures",
"digest",
"opaque-debug",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.0"
@ -624,22 +667,26 @@ dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5"
[[package]]
name = "socket2"
version = "0.4.4"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d"
dependencies = [
"libc",
"winapi",
]
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "strsim"
version = "0.10.0"
@ -657,6 +704,23 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "syn"
version = "2.0.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "termcolor"
version = "1.1.2"
@ -685,57 +749,31 @@ dependencies = [
[[package]]
name = "tokio"
version = "1.19.2"
version = "1.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439"
checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9"
dependencies = [
"backtrace",
"bytes",
"libc",
"memchr",
"mio",
"num_cpus",
"once_cell",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"socket2 0.5.5",
"tokio-macros",
"winapi",
"windows-sys",
]
[[package]]
name = "tokio-macros"
version = "1.7.0"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7"
checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-stream"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50145484efff8818b5ccd256697f36863f587da82cf8b409c53adf1e840798e3"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.6.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e99e1983e5d376cd8eb4b66604d2e99e79f5bd988c3055891dcd8c9e2604cc0"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"log",
"pin-project-lite",
"tokio",
"syn 2.0.39",
]
[[package]]
@ -747,6 +785,28 @@ dependencies = [
"serde",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"pin-project",
"pin-project-lite",
"tokio",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]]
name = "tower-service"
version = "0.3.1"
@ -755,11 +815,10 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
[[package]]
name = "tracing"
version = "0.1.29"
version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105"
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [
"cfg-if",
"log",
"pin-project-lite",
"tracing-core",
@ -767,11 +826,11 @@ dependencies = [
[[package]]
name = "tracing-core"
version = "0.1.21"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"lazy_static",
"once_cell",
]
[[package]]
@ -780,38 +839,30 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
[[package]]
name = "typenum"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
[[package]]
name = "udpt-rs"
version = "3.1.2"
dependencies = [
"async-compression",
"axum",
"binascii",
"bincode",
"chrono",
"clap",
"fern",
"log",
"maud",
"serde",
"serde_json",
"tokio",
"toml",
"warp",
]
[[package]]
name = "unicase"
version = "2.6.0"
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
dependencies = [
"version_check",
]
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-xid"
@ -835,34 +886,6 @@ dependencies = [
"try-lock",
]
[[package]]
name = "warp"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cef4e1e9114a4b7f1ac799f16ce71c14de5778500c5450ec6b7b920c55b587e"
dependencies = [
"bytes",
"futures-channel",
"futures-util",
"headers",
"http",
"hyper",
"log",
"mime",
"mime_guess",
"percent-encoding",
"pin-project",
"scoped-tls",
"serde",
"serde_json",
"serde_urlencoded",
"tokio",
"tokio-stream",
"tokio-util",
"tower-service",
"tracing",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
@ -908,43 +931,66 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.36.1"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"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",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"

View file

@ -11,7 +11,6 @@ lto = "fat"
[dependencies]
serde = {version = "1.0", features = ["derive"]}
bincode = "1.3"
warp = {version = "0.3", default-features = false}
tokio = {version = "1.19", features = ["macros", "io-util", "net", "time", "rt-multi-thread", "fs", "sync", "signal"]}
binascii = "0.1"
toml = "0.5"
@ -21,3 +20,5 @@ fern = "0.6"
serde_json = "1.0"
async-compression = {version = "^0.3.8", features = ["bzip2", "tokio"]}
chrono = "0.4"
maud = { version = "*", features = ["axum"] }
axum = { version = "0.6.18", features = ["json"] }

View file

@ -68,12 +68,10 @@ impl Configuration {
pub fn load_file(path: &str) -> Result<Configuration, ConfigError> {
match std::fs::read(path) {
Err(e) => Err(ConfigError::IOError(e)),
Ok(data) => {
match Self::load(data.as_slice()) {
Ok(data) => match Self::load(data.as_slice()) {
Ok(cfg) => Ok(cfg),
Err(e) => Err(ConfigError::ParseError(e)),
}
}
},
}
}

View file

@ -12,8 +12,7 @@ use std::process::exit;
fn setup_logging(cfg: &Configuration) {
let log_level = match cfg.get_log_level() {
None => log::LevelFilter::Info,
Some(level) => {
match level.as_str() {
Some(level) => match level.as_str() {
"off" => log::LevelFilter::Off,
"trace" => log::LevelFilter::Trace,
"debug" => log::LevelFilter::Debug,
@ -24,8 +23,7 @@ fn setup_logging(cfg: &Configuration) {
eprintln!("udpt: unknown log level encountered '{}'", level.as_str());
exit(-1);
}
}
}
},
};
if let Err(err) = fern::Dispatch::new()
@ -117,7 +115,9 @@ async fn main() {
let tokens = http_cfg.get_access_tokens();
let server = webserver::build_server(https_tracker, tokens.clone());
server.bind(bind_addr.parse::<std::net::SocketAddr>().unwrap()).await;
let _ = axum::Server::bind(&bind_addr.parse::<std::net::SocketAddr>().unwrap())
.serve(server.into_make_service())
.await;
});
}

View file

@ -240,7 +240,9 @@ impl UDPTracker {
let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
let mut payload = StackVec::from(&mut payload_buffer);
match pack_into(&mut payload, &UDPAnnounceResponse {
match pack_into(
&mut payload,
&UDPAnnounceResponse {
header: UDPResponseHeader {
action: Actions::Announce,
transaction_id: packet.header.transaction_id,
@ -248,7 +250,8 @@ impl UDPTracker {
seeders,
interval: self.config.get_udp_config().get_announce_interval(),
leechers,
}) {
},
) {
Ok(_) => {}
Err(_) => {
return;
@ -290,10 +293,13 @@ impl UDPTracker {
let mut response_buffer = [0u8; 8 + MAX_SCRAPE * 12];
let mut response = StackVec::from(&mut response_buffer);
if pack_into(&mut response, &UDPResponseHeader {
if pack_into(
&mut response,
&UDPResponseHeader {
action: Actions::Scrape,
transaction_id: header.transaction_id,
})
},
)
.is_err()
{
// not much we can do...
@ -331,13 +337,11 @@ impl UDPTracker {
leechers,
}
}
None => {
UDPScrapeResponseEntry {
None => UDPScrapeResponseEntry {
seeders: 0,
completed: 0,
leechers: 0,
}
}
},
};
if pack_into(&mut response, &result).is_err() {
@ -363,7 +367,7 @@ impl UDPTracker {
Err(err) => {
debug!("failed to send a packet: {}", err);
Err(err)
},
}
Ok(sz) => Ok(sz),
}
}
@ -372,10 +376,15 @@ impl UDPTracker {
let mut payload_buffer = vec![0u8; MAX_PACKET_SIZE];
let mut payload = StackVec::from(&mut payload_buffer);
if pack_into(&mut payload, &UDPResponseHeader {
if pack_into(
&mut payload,
&UDPResponseHeader {
transaction_id: header.transaction_id,
action: Actions::Error,
}).is_ok() {
},
)
.is_ok()
{
let msg_bytes = Vec::from(error_msg.as_bytes());
payload.extend(msg_bytes);
@ -414,7 +423,10 @@ mod tests {
assert!(pack_into(&mut payload, &mystruct).is_ok());
assert_eq!(payload.as_slice().len(), 16);
assert_eq!(payload.as_slice(), &[0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 0, 0, 1, 47, 203]);
assert_eq!(
payload.as_slice(),
&[0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0, 0, 0, 0, 0, 1, 47, 203]
);
}
#[test]

View file

@ -75,9 +75,7 @@ impl std::convert::From<&[u8]> for InfoHash {
impl From<[u8; 20]> for InfoHash {
fn from(info_hash: [u8; 20]) -> Self {
InfoHash {
info_hash,
}
InfoHash { info_hash }
}
}
@ -219,7 +217,8 @@ impl PeerId {
impl Serialize for PeerId {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer, {
S: serde::Serializer,
{
let mut tmp = [0u8; 40];
binascii::bin2hex(&self.0, &mut tmp).unwrap();
let id = std::str::from_utf8(&tmp).ok();
@ -272,14 +271,17 @@ impl TorrentEntry {
let is_seeder = left == 0 && uploaded > 0;
let mut was_seeder = false;
let mut is_completed = left == 0 && (event as u32) == (Events::Complete as u32);
if let Some(prev) = self.peers.insert(*peer_id, TorrentPeer {
if let Some(prev) = self.peers.insert(
*peer_id,
TorrentPeer {
updated: std::time::Instant::now(),
left,
downloaded,
uploaded,
ip: *remote_address,
event,
}) {
},
) {
was_seeder = prev.left == 0 && prev.uploaded > 0;
if is_completed && (prev.event as u32) == (Events::Complete as u32) {
@ -383,7 +385,7 @@ impl TorrentTracker {
Err(ref err) => {
error!("failed to read lines! {}", err);
continue;
},
}
};
let row: DatabaseRow = match serde_json::from_str(&line) {
Ok(v) => v,
@ -411,7 +413,7 @@ impl TorrentTracker {
std::collections::btree_map::Entry::Vacant(ve) => {
ve.insert(TorrentEntry::new());
Ok(())
},
}
std::collections::btree_map::Entry::Occupied(_entry) => Err(()),
}
}
@ -453,9 +455,7 @@ impl TorrentTracker {
&self, info_hash: &InfoHash, remote_addr: &std::net::SocketAddr,
) -> Option<Vec<std::net::SocketAddr>> {
let read_lock = self.database.torrent_peers.read().await;
read_lock
.get(info_hash)
.map(|entry| entry.get_peers(remote_addr))
read_lock.get(info_hash).map(|entry| entry.get_peers(remote_addr))
}
pub async fn update_torrent_and_get_stats(
@ -465,14 +465,12 @@ impl TorrentTracker {
use std::collections::btree_map::Entry;
let mut torrent_peers = self.database.torrent_peers.write().await;
let torrent_entry = match torrent_peers.entry(info_hash.clone()) {
Entry::Vacant(vacant) => {
match self.mode {
Entry::Vacant(vacant) => match self.mode {
TrackerMode::Dynamic => vacant.insert(TorrentEntry::new()),
_ => {
return TorrentStats::TorrentNotRegistered;
}
}
}
},
Entry::Occupied(entry) => {
if entry.get().is_flagged() {
return TorrentStats::TorrentFlagged;

View file

@ -1,19 +1,23 @@
use crate::tracker::{InfoHash, TorrentTracker};
use axum::extract::{Path, Query, State};
use axum::http::{Request, StatusCode};
use axum::middleware::{self, Next};
use axum::response::{IntoResponse, Redirect, Response};
use axum::Json;
use maud::{html, Markup, DOCTYPE};
use serde::{Deserialize, Serialize};
use std::cmp::min;
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use warp::{filters, reply, reply::Reply, serve, Filter, Server};
fn view_root() -> impl Reply {
warp::http::Response::builder()
.header("Content-Type", "text/html; charset=utf-8")
.header("Server", concat!("udpt/", env!("CARGO_PKG_VERSION"), "; https://abda.nl/"))
.body(concat!(r#"<html>
<head>
<title>udpt server</title>
<style>
body {
async fn view_root() -> Markup {
html! {
(DOCTYPE)
head {
meta charset="utf-8";
meta name="viewport" content="width=device-width, initial-scale=1";
title { "udpt server" }
style { "body {
background-color: #222;
color: #eee;
margin-left: auto;
@ -23,20 +27,29 @@ fn view_root() -> impl Reply {
}
a, a:active, a:visited {
color: lightpink;
}"}
}
body {
p {
"This server is running "
a href="https://github.com/naim94a/udpt"
style="font-weight: bold; font-size: large" { code { "udpt" } }
" a "
a
href="https://en.wikipedia.org/wiki/BitTorrent_tracker"
rel="nofollow"
target="_blank" { "BitTorrent tracker" }
" based on the "
a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol"
rel="nofollow" target="_blank" { "UDP" } " protocol."
}
div style="color: grey; font-size: small; border-top: 1px solid grey; width: 75%; max-width: 300px; margin-left: auto; margin-right: auto; text-align: center; padding-top: 5px" {
"udpt/" (env!("CARGO_PKG_VERSION")) br;
a href="https://naim94a.github.com/udpt/" { "docs" } " · "
a href="https://github.com/naim94a/udpt/issues" { "issues & PRs" }
}
}
}
</style>
</head>
<body>
<p>
This server is running <a style="font-weight: bold; font-size: large" href="https://github.com/naim94a/udpt"><code>udpt</code></a>, a <a href="https://en.wikipedia.org/wiki/BitTorrent_tracker" rel="nofollow" target="_blank">BitTorrent tracker</a> based on the <a href="https://en.wikipedia.org/wiki/User_Datagram_Protocol" rel="nofollow" target="_blank">UDP</a> protocol.
</p>
<div style="color: grey; font-size: small; border-top: 1px solid grey; width: 75%; max-width: 300px; margin-left: auto; margin-right: auto; text-align: center; padding-top: 5px">
udpt/"#, env!("CARGO_PKG_VERSION"), r#"<br />
<a href="https://naim94a.github.com/udpt/">docs</a> &middot; <a href="https://github.com/naim94a/udpt/issues">issues &amp; PRs</a> &middot; <a href="https://paypal.me/naim94a">donate</a>
</div>
</body>
</html>"#))
.unwrap()
}
#[derive(Deserialize, Debug)]
@ -46,10 +59,10 @@ struct TorrentInfoQuery {
}
#[derive(Serialize)]
struct TorrentEntry<'a> {
info_hash: &'a InfoHash,
struct TorrentEntry {
info_hash: InfoHash,
#[serde(flatten)]
data: &'a crate::tracker::TorrentEntry,
data: crate::tracker::TorrentEntry,
seeders: u32,
leechers: u32,
@ -62,6 +75,12 @@ struct TorrentFlag {
is_flagged: bool,
}
#[derive(Clone)]
struct AppState {
tracker: Arc<TorrentTracker>,
tokens: HashMap<String, String>,
}
#[derive(Serialize, Debug)]
#[serde(tag = "status", rename_all = "snake_case")]
enum ActionStatus<'a> {
@ -69,62 +88,18 @@ enum ActionStatus<'a> {
Err { reason: std::borrow::Cow<'a, str> },
}
impl warp::reject::Reject for ActionStatus<'static> {}
fn authenticate(tokens: HashMap<String, String>) -> impl Filter<Extract = (), Error = warp::reject::Rejection> + Clone {
#[derive(Deserialize)]
struct AuthToken {
token: Option<String>,
}
let tokens: HashSet<String> = tokens.into_iter().map(|(_, v)| v).collect();
let tokens = Arc::new(tokens);
warp::filters::any::any()
.map(move || tokens.clone())
.and(filters::query::query::<AuthToken>())
.and_then(|tokens: Arc<HashSet<String>>, token: AuthToken| {
async move {
if let Some(token) = token.token {
if tokens.contains(&token) {
return Ok(());
}
}
Err(warp::reject::custom(ActionStatus::Err {
reason: "Access Denied".into(),
}))
}
})
.untuple_one()
}
pub fn build_server(
tracker: Arc<TorrentTracker>, tokens: HashMap<String, String>,
) -> Server<impl Filter<Extract = impl Reply> + Clone + Send + Sync + 'static> {
let root = filters::path::end().map(view_root);
let t1 = tracker.clone();
// view_torrent_list -> GET /t/?offset=:u32&limit=:u32 HTTP/1.1
let view_torrent_list = filters::path::end()
.and(filters::method::get())
.and(filters::query::query())
.map(move |limits| {
let tracker = t1.clone();
(limits, tracker)
})
.and_then(|(limits, tracker): (TorrentInfoQuery, Arc<TorrentTracker>)| {
async move {
async fn json_torrent_list(State(state): State<AppState>, limits: Query<TorrentInfoQuery>) -> Json<Vec<TorrentEntry>> {
let offset = limits.offset.unwrap_or(0);
let limit = min(limits.limit.unwrap_or(1000), 4000);
let db = tracker.get_database().await;
let db = state.tracker.get_database().await;
let results: Vec<_> = db
.iter()
.map(|(k, v)| {
let (seeders, _, leechers) = v.get_stats();
TorrentEntry {
info_hash: k,
data: v,
info_hash: k.clone(),
data: v.clone(),
seeders,
leechers,
peers: None,
@ -134,25 +109,16 @@ pub fn build_server(
.take(limit as usize)
.collect();
Result::<_, warp::reject::Rejection>::Ok(reply::json(&results))
}
});
return axum::Json(results);
}
let t2 = tracker.clone();
// view_torrent_info -> GET /t/:infohash HTTP/*
let view_torrent_info = filters::method::get()
.and(filters::path::param())
.and(filters::path::end())
.map(move |info_hash: InfoHash| {
let tracker = t2.clone();
(info_hash, tracker)
})
.and_then(|(info_hash, tracker): (InfoHash, Arc<TorrentTracker>)| {
async move {
let db = tracker.get_database().await;
async fn json_torrent_info(
State(state): State<AppState>, Path(info_hash): Path<InfoHash>,
) -> Result<Json<TorrentEntry>, StatusCode> {
let db = state.tracker.get_database().await;
let info = match db.get(&info_hash) {
Some(v) => v,
None => return Err(warp::reject::reject()),
None => return Err(StatusCode::NOT_FOUND),
};
let (seeders, _, leechers) = info.get_stats();
@ -162,78 +128,80 @@ pub fn build_server(
.map(|(&peer_id, peer_info)| (peer_id, peer_info.clone()))
.collect();
Ok(reply::json(&TorrentEntry {
info_hash: &info_hash,
data: info,
return Ok(axum::Json(TorrentEntry {
info_hash,
data: info.clone(),
seeders,
leechers,
peers: Some(peers),
}))
}
});
}));
}
// DELETE /t/:info_hash
let t3 = tracker.clone();
let delete_torrent = filters::method::delete()
.and(filters::path::param())
.and(filters::path::end())
.map(move |info_hash: InfoHash| {
let tracker = t3.clone();
(info_hash, tracker)
})
.and_then(|(info_hash, tracker): (InfoHash, Arc<TorrentTracker>)| {
async move {
let resp = match tracker.remove_torrent(&info_hash, true).await.is_ok() {
async fn delete_torrent(State(state): State<AppState>, Path(info_hash): Path<InfoHash>) -> Json<ActionStatus<'static>> {
let resp = match state.tracker.remove_torrent(&info_hash, true).await.is_ok() {
true => ActionStatus::Ok,
false => {
ActionStatus::Err {
false => ActionStatus::Err {
reason: "failed to delete torrent".into(),
}
}
},
};
Result::<_, warp::Rejection>::Ok(reply::json(&resp))
}
});
axum::Json(resp)
}
let t4 = tracker;
// add_torrent/alter: POST /t/:info_hash
// (optional) BODY: json: {"is_flagged": boolean}
let change_torrent = filters::method::post()
.and(filters::path::param())
.and(filters::path::end())
.and(filters::body::content_length_limit(4096))
.and(filters::body::json())
.map(move |info_hash: InfoHash, body: Option<TorrentFlag>| {
let tracker = t4.clone();
(info_hash, tracker, body)
})
.and_then(
|(info_hash, tracker, body): (InfoHash, Arc<TorrentTracker>, Option<TorrentFlag>)| {
async move {
let is_flagged = body.map(|e| e.is_flagged).unwrap_or(false);
#[derive(Deserialize, Debug)]
struct ModifyTorrent {
flag: Option<bool>,
}
async fn modify_torrent(
State(state): State<AppState>, Path(info_hash): Path<InfoHash>, Json(payload): Json<ModifyTorrent>,
) -> Json<ActionStatus<'static>> {
let is_flagged = payload.flag.unwrap_or_default();
let tracker = state.tracker;
if !tracker.set_torrent_flag(&info_hash, is_flagged).await {
// torrent doesn't exist, add it...
if is_flagged {
if tracker.add_torrent(&info_hash).await.is_ok() {
tracker.set_torrent_flag(&info_hash, is_flagged).await;
} else {
return Err(warp::reject::custom(ActionStatus::Err {
return axum::Json(ActionStatus::Err {
reason: "failed to flag torrent".into(),
}));
});
}
}
}
Result::<_, warp::Rejection>::Ok(reply::json(&ActionStatus::Ok))
}
},
);
let torrent_mgmt =
filters::path::path("t").and(view_torrent_list.or(delete_torrent).or(view_torrent_info).or(change_torrent));
let server = root.or(authenticate(tokens).and(torrent_mgmt));
serve(server)
axum::Json(ActionStatus::Ok)
}
async fn token_auth<B>(State(state): State<AppState>, request: Request<B>, next: Next<B>) -> Response {
let mut is_authed = false;
let tokens: HashSet<String> = state.tokens.into_iter().map(|(_, v)| v).collect();
if request.uri().query().is_some() {
let query_params: Vec<&str> = request.uri().query().unwrap().split("&").collect();
for query_param in query_params {
let split: Vec<&str> = query_param.split("=").collect();
let (key, value) = (split[0], split[1]);
if key == "token" && tokens.contains(value) {
is_authed = true;
}
}
}
if is_authed {
let response = next.run(request).await;
return response;
}
Redirect::to("/").into_response()
}
pub fn build_server(tracker: Arc<TorrentTracker>, tokens: HashMap<String, String>) -> axum::Router {
let state = AppState { tracker, tokens };
axum::Router::new()
.route("/t", axum::routing::get(json_torrent_list))
.route("/t/", axum::routing::get(json_torrent_list))
.route("/t/:info_hash", axum::routing::get(json_torrent_info))
.route("/t/:info_hash", axum::routing::delete(delete_torrent))
.route("/t/:info_hash", axum::routing::post(modify_torrent))
.layer(middleware::from_fn_with_state(state.clone(), token_auth))
.route("/", axum::routing::get(view_root))
.with_state(state)
}