massive code base refactor

main
Zynh0722 2023-04-11 03:29:21 -07:00
parent 92a8330cbf
commit c9dfe1588e
6 changed files with 189 additions and 410 deletions

339
Cargo.lock generated
View File

@ -9,15 +9,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]] [[package]]
name = "aes" name = "async-compression"
version = "0.7.5" version = "0.3.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" checksum = "942c7cd7ae39e91bde4820d74132e9862e62c2f386c3aa90ccf55949f5bad63a"
dependencies = [ dependencies = [
"cfg-if", "flate2",
"cipher", "futures-core",
"cpufeatures", "futures-io",
"opaque-debug", "memchr",
"pin-project-lite",
] ]
[[package]] [[package]]
@ -31,6 +32,22 @@ dependencies = [
"syn 2.0.13", "syn 2.0.13",
] ]
[[package]]
name = "async_zip"
version = "0.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79eaa2b44cfdce59cfff6cb013c96900635085fe7c28fbcbe926c9e5ad0ddfbc"
dependencies = [
"async-compression",
"crc32fast",
"futures-util",
"log",
"pin-project",
"thiserror",
"tokio",
"tokio-util",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -87,69 +104,18 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "base64ct"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.3.2" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
dependencies = [
"generic-array",
]
[[package]]
name = "byteorder"
version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.4.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "bzip2"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
dependencies = [
"bzip2-sys",
"libc",
]
[[package]]
name = "bzip2-sys"
version = "0.1.11+1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
dependencies = [
"jobserver",
]
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -157,27 +123,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cipher" name = "const_format"
version = "0.3.0" version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [ dependencies = [
"generic-array", "const_format_proc_macros",
] ]
[[package]] [[package]]
name = "constant_time_eq" name = "const_format_proc_macros"
version = "0.1.5" version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
[[package]]
name = "cpufeatures"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181"
dependencies = [ dependencies = [
"libc", "proc-macro2",
"quote",
"unicode-xid",
] ]
[[package]] [[package]]
@ -189,36 +151,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "crossbeam-utils"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
dependencies = [
"cfg-if",
]
[[package]]
name = "crypto-common"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"typenum",
]
[[package]]
name = "digest"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
dependencies = [
"block-buffer",
"crypto-common",
"subtle",
]
[[package]] [[package]]
name = "encoding_rs" name = "encoding_rs"
version = "0.8.32" version = "0.8.32"
@ -342,16 +274,6 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "generic-array"
version = "0.14.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
dependencies = [
"typenum",
"version_check",
]
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.9" version = "0.2.9"
@ -397,15 +319,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "hmac"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest",
]
[[package]] [[package]]
name = "http" name = "http"
version = "0.2.9" version = "0.2.9"
@ -486,15 +399,6 @@ version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "jobserver"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -626,17 +530,17 @@ dependencies = [
name = "nyazoom" name = "nyazoom"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"async_zip",
"axum", "axum",
"futures", "futures",
"rand", "rand",
"sanitize-filename-reader-friendly",
"tokio", "tokio",
"tokio-util", "tokio-util",
"tower", "tower",
"tower-http", "tower-http",
"tracing", "tracing",
"tracing-subscriber", "tracing-subscriber",
"urlencoding",
"zip",
] ]
[[package]] [[package]]
@ -645,12 +549,6 @@ version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]]
name = "opaque-debug"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -680,29 +578,6 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "password-hash"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700"
dependencies = [
"base64ct",
"rand_core",
"subtle",
]
[[package]]
name = "pbkdf2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
dependencies = [
"digest",
"hmac",
"password-hash",
"sha2",
]
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.2.0" version = "2.2.0"
@ -741,12 +616,6 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
version = "0.3.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -846,6 +715,15 @@ version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "sanitize-filename-reader-friendly"
version = "2.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b750e71aac86f4b238844ac9416e7339a8de1225eb1ebe5fba89890f634c46bf"
dependencies = [
"const_format",
]
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"
@ -890,28 +768,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sha1"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]]
name = "sha2"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "sharded-slab" name = "sharded-slab"
version = "0.1.4" version = "0.1.4"
@ -961,12 +817,6 @@ version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -995,6 +845,26 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "thiserror"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.13",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.7" version = "1.1.7"
@ -1005,22 +875,6 @@ dependencies = [
"once_cell", "once_cell",
] ]
[[package]]
name = "time"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
dependencies = [
"serde",
"time-core",
]
[[package]]
name = "time-core"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.27.0" version = "1.27.0"
@ -1059,6 +913,7 @@ checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-io",
"futures-sink", "futures-sink",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
@ -1187,12 +1042,6 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "typenum"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
[[package]] [[package]]
name = "unicase" name = "unicase"
version = "2.6.0" version = "2.6.0"
@ -1209,10 +1058,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "urlencoding" name = "unicode-xid"
version = "2.1.2" version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]] [[package]]
name = "valuable" name = "valuable"
@ -1329,53 +1178,3 @@ name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "zip"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0445d0fbc924bb93539b4316c11afb121ea39296f99a3c4c9edad09e3658cdef"
dependencies = [
"aes",
"byteorder",
"bzip2",
"constant_time_eq",
"crc32fast",
"crossbeam-utils",
"flate2",
"hmac",
"pbkdf2",
"sha1",
"time",
"zstd",
]
[[package]]
name = "zstd"
version = "0.11.2+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "5.0.2+zstd.1.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db"
dependencies = [
"libc",
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.8+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5556e6ee25d32df2586c098bbfa278803692a20d0ab9565e049480d52707ec8c"
dependencies = [
"cc",
"libc",
"pkg-config",
]

View File

@ -6,14 +6,14 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
async_zip = { version = "0.0.13", features = ["deflate", "tokio", "tokio-fs", "async-compression"] }
axum = { version = "0.6.12", features = ["multipart", "http2"] } axum = { version = "0.6.12", features = ["multipart", "http2"] }
futures = "0.3.28" futures = "0.3.28"
rand = { version = "0.8.5", features = ["small_rng"] } rand = { version = "0.8.5", features = ["small_rng"] }
sanitize-filename-reader-friendly = "2.2.1"
tokio = { version = "1.27.0", features = ["full"] } tokio = { version = "1.27.0", features = ["full"] }
tokio-util = { version = "0.7.7", features = ["io"] } tokio-util = { version = "0.7.7", features = ["io"] }
tower = { version = "0.4.13", features = ["util"] } tower = { version = "0.4.13", features = ["util"] }
tower-http = { version = "0.4.0", features = ["fs", "trace", "limit"] } tower-http = { version = "0.4.0", features = ["fs", "trace", "limit"] }
tracing = "0.1.37" tracing = "0.1.37"
tracing-subscriber = { version = "0.3.16", features = ["env-filter"] } tracing-subscriber = { version = "0.3.16", features = ["env-filter"] }
urlencoding = "2.1.2"
zip = "0.6.4"

31
dist/css/link.css vendored
View File

@ -0,0 +1,31 @@
body {
background-color: #FCB0B3;
color: #25283D;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
width: 100vw;
margin: 0;
gap: 1em;
}
.link-wrapper {
background-color: #49DCB1;
padding: 1.5em;
border-radius: 1em;
border: 1px solid #25283D;
}
.return-button {
all: unset;
background-color: #49DCB1;
padding: 1em;
border-radius: 1em;
cursor: pointer;
}
.return-button:hover {
filter: brightness(1.1);
}

1
dist/css/main.css vendored
View File

@ -40,6 +40,7 @@ body {
#cat-fact { #cat-fact {
max-width: 25em; max-width: 25em;
padding: 0 1em; padding: 0 1em;
text-align: center;
} }
[type="file"] { [type="file"] {

43
dist/link.html vendored
View File

@ -1,12 +1,37 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head>
<title></title> <head>
<meta charset="UTF-8"> <title></title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta charset="UTF-8">
<link href="css/link.css" rel="stylesheet"> <meta name="viewport" content="width=device-width, initial-scale=1">
</head> <link href="css/link.css" rel="stylesheet">
<body>
<script>
</body> document.addEventListener("DOMContentLoaded", () => {
const params = new Proxy(new URLSearchParams(window.location.search), {
get: (searchParams, prop) => searchParams.get(prop),
});
if (params.link !== null) {
let link = `${window.location.origin}/download/${params.link}`;
let link_el = document.getElementById("link");
link_el.href = link;
link_el.innerHTML = link;
}
});
</script>
</head>
<body>
<div class="link-wrapper">
<a id="link" href=""></a>
</div>
<a href="/" class="return-button">Return to home</a>
</body>
</html> </html>

View File

@ -1,30 +1,32 @@
use std::io; use async_zip::tokio::write::ZipFileWriter;
use std::net::SocketAddr; use async_zip::{Compression, ZipEntryBuilder};
use std::path::{Component, Path};
use std::sync::{Arc, Mutex};
use axum::body::Bytes;
use axum::http::StatusCode; use axum::http::StatusCode;
use axum::routing::post; use axum::routing::post;
use axum::BoxError;
use axum::{ use axum::{
extract::{DefaultBodyLimit, Multipart}, extract::{DefaultBodyLimit, Multipart},
response::Redirect, response::Redirect,
Router, Router,
}; };
use futures::future::join_all;
use futures::{Stream, TryStreamExt}; use futures::TryStreamExt;
use rand::distributions::{Alphanumeric, DistString}; use rand::distributions::{Alphanumeric, DistString};
use rand::rngs::SmallRng; use rand::rngs::SmallRng;
use rand::SeedableRng; use rand::SeedableRng;
use tokio::fs::File;
use tokio::io::BufWriter; use sanitize_filename_reader_friendly::sanitize;
use tokio::task::{spawn_blocking, JoinHandle};
use std::io;
use std::net::SocketAddr;
use std::path::Path;
use tokio_util::compat::FuturesAsyncWriteCompatExt;
use tokio_util::io::StreamReader; use tokio_util::io::StreamReader;
use tower_http::{limit::RequestBodyLimitLayer, services::ServeDir, trace::TraceLayer}; use tower_http::{limit::RequestBodyLimitLayer, services::ServeDir, trace::TraceLayer};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt}; use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
use zip::ZipWriter;
#[tokio::main] #[tokio::main]
async fn main() -> io::Result<()> { async fn main() -> io::Result<()> {
@ -42,7 +44,7 @@ async fn main() -> io::Result<()> {
// Router Setup // Router Setup
let with_big_body = Router::new() let with_big_body = Router::new()
.route("/upload", post(upload)) .route("/upload", post(upload_to_zip))
.layer(DefaultBodyLimit::disable()) .layer(DefaultBodyLimit::disable())
.layer(RequestBodyLimitLayer::new( .layer(RequestBodyLimitLayer::new(
10 * 1024 * 1024 * 1024, // 10GiB 10 * 1024 * 1024 * 1024, // 10GiB
@ -68,143 +70,55 @@ async fn main() -> io::Result<()> {
Ok(()) Ok(())
} }
async fn upload(mut body: Multipart) -> Result<Redirect, (StatusCode, String)> { async fn upload_to_zip(mut body: Multipart) -> Result<Redirect, (StatusCode, String)> {
let cache_name = get_random_name(10); let cache_name = get_random_name(10);
let cache_folder = Path::new(".cache/.temp").join(cache_name);
make_dir(&cache_folder) let archive_path = Path::new(".cache/serve").join(&format!("{}.zip", &cache_name));
tracing::debug!("Zipping: {:?}", &archive_path);
let mut archive = tokio::fs::File::create(archive_path)
.await .await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?; .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;
let mut writer = ZipFileWriter::new(&mut archive);
while let Some(field) = body.next_field().await.unwrap() { while let Some(field) = body.next_field().await.unwrap() {
let file_name = if let Some(file_name) = field.file_name() { let file_name = match field.file_name() {
file_name.to_owned() Some(file_name) => sanitize(file_name),
} else { _ => continue,
continue;
}; };
if !path_is_valid(&file_name) { if !path_is_valid(&file_name) {
return Err((StatusCode::BAD_REQUEST, "Invalid Filename >:(".to_owned())); return Err((StatusCode::BAD_REQUEST, "Invalid Filename >:(".to_owned()));
} }
let path = cache_folder.join(file_name); tracing::debug!("Downloading to Zip: {file_name:?}");
tracing::debug!("Caching: {path:?}"); let stream = field;
stream_to_file(&path, field).await?
}
tracing::debug!("Zipping: {:?}", &cache_folder);
zip_dir(&cache_folder)
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;
tracing::debug!("Cleaning up: {:?}", &cache_folder);
remove_dir(cache_folder)
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;
Ok(Redirect::to("/"))
}
async fn stream_to_file<S, E, P>(path: P, stream: S) -> Result<(), (StatusCode, String)>
where
P: AsRef<Path>,
S: Stream<Item = Result<Bytes, E>>,
E: Into<BoxError>,
{
async {
// Convert the stream into an `AsyncRead`.
let body_with_io_error = stream.map_err(|err| io::Error::new(io::ErrorKind::Other, err)); let body_with_io_error = stream.map_err(|err| io::Error::new(io::ErrorKind::Other, err));
let body_reader = StreamReader::new(body_with_io_error); let body_reader = StreamReader::new(body_with_io_error);
futures::pin_mut!(body_reader); futures::pin_mut!(body_reader);
// Create the file. `File` implements `AsyncWrite`. let builder = ZipEntryBuilder::new(file_name, Compression::Deflate);
let mut file = BufWriter::new(File::create(&path).await?); let mut entry_writer = writer
.write_entry_stream(builder)
.await
.unwrap()
.compat_write();
// Copy the body into the file. tokio::io::copy(&mut body_reader, &mut entry_writer)
tokio::io::copy(&mut body_reader, &mut file).await?; .await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;
io::Result::Ok(()) entry_writer
.into_inner()
.close()
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;
} }
.await
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))
}
async fn zip_dir<T>(folder: T) -> io::Result<()> writer.close().await.unwrap();
where
T: AsRef<Path> + Send,
{
let file_name =
if let Component::Normal(file_name) = folder.as_ref().components().last().unwrap() {
// This should be alphanumeric already
file_name.to_str().unwrap().to_owned()
} else {
return Err(io::Error::new(
io::ErrorKind::Other,
"Failed Creating Zip File",
));
};
let file_name = Path::new(".cache/serve").join(format!("{file_name}.zip")); Ok(Redirect::to(&format!("/link.html?link={}.zip", cache_name)))
let file = spawn_blocking(move || std::fs::File::create(&file_name)).await??;
let writer = Arc::new(Mutex::new(ZipWriter::new(file)));
let folder = folder.as_ref().to_owned();
let directories = spawn_blocking(move || std::fs::read_dir(folder)).await??;
let zip_handles: Vec<JoinHandle<_>> = directories
.map(|entry| entry.unwrap())
.map(|entry| {
let writer = writer.clone();
let path = entry.path();
spawn_blocking(move || {
let mut file = std::fs::File::open(path).unwrap();
let mut writer = writer.lock().unwrap();
let options = zip::write::FileOptions::default()
.compression_method(zip::CompressionMethod::DEFLATE);
writer.start_file(
entry.file_name().to_str().ok_or_else(|| {
io::Error::new(
io::ErrorKind::Other,
"Filename not valid unicode".to_owned(),
)
})?,
options,
)?;
std::io::copy(&mut file, &mut *writer)
})
})
.collect();
let bytes_written: u64 = join_all(zip_handles)
.await
.iter()
.map(|v| v.as_ref().unwrap().as_ref().unwrap().clone())
.sum();
let final_bytes = writer.lock().unwrap().finish()?.metadata()?.len();
tracing::debug!(
"File Zipped: {} -- {} saved",
bytes_to_human_readable(final_bytes),
bytes_to_human_readable(bytes_written - final_bytes)
);
Ok(())
}
async fn remove_dir<T>(folder: T) -> io::Result<()>
where
T: AsRef<Path>,
{
tokio::fs::remove_dir_all(&folder).await?;
Ok(())
} }
#[inline] #[inline]
@ -240,6 +154,7 @@ fn get_random_name(len: usize) -> String {
Alphanumeric.sample_string(&mut rng, len) Alphanumeric.sample_string(&mut rng, len)
} }
#[allow(dead_code)]
static UNITS: [&str; 6] = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB"]; static UNITS: [&str; 6] = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
// This function is actually rather interesting to me, I understand that rust is // This function is actually rather interesting to me, I understand that rust is
// very powerful, and its very safe, but i find it rather amusing that the [] operator // very powerful, and its very safe, but i find it rather amusing that the [] operator
@ -249,7 +164,7 @@ static UNITS: [&str; 6] = ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
// although this function shouldn't be able to panic at runtime due to known bounds // although this function shouldn't be able to panic at runtime due to known bounds
// being listened to // being listened to
#[inline] #[inline]
fn bytes_to_human_readable(bytes: u64) -> String { fn _bytes_to_human_readable(bytes: u64) -> String {
let mut running = bytes as f64; let mut running = bytes as f64;
let mut count = 0; let mut count = 0;
while running > 1024.0 && count <= 6 { while running > 1024.0 && count <= 6 {
@ -259,3 +174,11 @@ fn bytes_to_human_readable(bytes: u64) -> String {
format!("{:.2} {}", running, UNITS[count - 1]) format!("{:.2} {}", running, UNITS[count - 1])
} }
pub mod error {
use std::io::{Error, ErrorKind};
pub fn io_other(s: &str) -> Error {
Error::new(ErrorKind::Other, s)
}
}