diff --git a/Cargo.lock b/Cargo.lock index fd16366..5860a56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -226,9 +226,9 @@ dependencies = [ [[package]] name = "actix-web-httpauth" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c25a48b4684f90520183cd1a688e5f4f7e9905835fa75d02c0fe4f60fcdbe6" +checksum = "a6dc1123f18b3548b9fe90c15e9bd77819701b047c6b62c152230aa39243d40d" dependencies = [ "actix-service", "actix-utils", @@ -280,12 +280,65 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "askama" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb98f10f371286b177db5eeb9a6e5396609555686a35e1d4f7b9a9c6d8af0139" +dependencies = [ + "askama_derive", + "askama_escape", + "askama_shared", +] + +[[package]] +name = "askama_actix" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c52f74f8382a142ecfc052100b21abc33f2c069e20fe345808e7ed914b179449" +dependencies = [ + "actix-web", + "askama", + "askama_shared", +] + +[[package]] +name = "askama_derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87bf87e6e8b47264efa9bde63d6225c6276a52e05e91bf37eaa8afd0032d6b71" +dependencies = [ + "askama_shared", + "proc-macro2", + "syn", +] + [[package]] name = "askama_escape" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" +[[package]] +name = "askama_shared" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf722b94118a07fcbc6640190f247334027685d4e218b794dbfe17c32bf38ed0" +dependencies = [ + "askama_escape", + "humansize", + "mime", + "mime_guess", + "nom", + "num-traits", + "percent-encoding", + "proc-macro2", + "quote", + "serde", + "syn", + "toml", +] + [[package]] name = "atty" version = "0.2.14" @@ -315,34 +368,13 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - [[package]] name = "block-buffer" version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] @@ -366,38 +398,17 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "memchr", -] - [[package]] name = "bumpalo" version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" [[package]] name = "bytestring" @@ -423,40 +434,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "winapi", -] - -[[package]] -name = "chrono-tz" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58549f1842da3080ce63002102d5bc954c7bc843d4f47818e642abdc36253552" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf", -] - -[[package]] -name = "chrono-tz-build" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db058d493fb2f65f41861bfed7e3fe6335264a9f0f92710cab5bdf01fef09069" -dependencies = [ - "parse-zoneinfo", - "phf", - "phf_codegen", -] - [[package]] name = "clap" version = "3.2.12" @@ -518,23 +495,13 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "crossbeam-utils" -version = "0.8.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" -dependencies = [ - "cfg-if", - "once_cell", -] - [[package]] name = "crypto-common" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] @@ -551,28 +518,13 @@ dependencies = [ "syn", ] -[[package]] -name = "deunicode" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "850878694b7933ca4c9569d30a34b55031b9b139ee1fc7b94a527c4ef960d690" - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - [[package]] name = "digest" version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" dependencies = [ - "block-buffer 0.10.2", + "block-buffer", "crypto-common", ] @@ -598,12 +550,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - [[package]] name = "firestorm" version = "0.5.1" @@ -666,15 +612,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - [[package]] name = "generic-array" version = "0.14.5" @@ -696,30 +633,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "globset" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" -dependencies = [ - "aho-corasick", - "bstr", - "fnv", - "log", - "regex", -] - -[[package]] -name = "globwalk" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" -dependencies = [ - "bitflags", - "ignore", - "walkdir", -] - [[package]] name = "h2" version = "0.3.13" @@ -806,24 +719,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "ignore" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713f1b139373f96a2e0ce3ac931cd01ee973c3c5dd7c40c0c2efe96ad2b6751d" -dependencies = [ - "crossbeam-utils", - "globset", - "lazy_static", - "log", - "memchr", - "regex", - "same-file", - "thread_local", - "walkdir", - "winapi-util", -] - [[package]] name = "indexmap" version = "1.9.1" @@ -913,12 +808,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "maplit" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" - [[package]] name = "matches" version = "0.1.9" @@ -947,6 +836,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.5.3" @@ -969,13 +864,13 @@ dependencies = [ ] [[package]] -name = "num-integer" -version = "0.1.45" +name = "nom" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ - "autocfg", - "num-traits", + "memchr", + "minimal-lexical", ] [[package]] @@ -1012,12 +907,6 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "os_str_bytes" version = "6.2.0" @@ -1047,15 +936,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "parse-zoneinfo" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c705f256449c60da65e11ff6626e0c16a0a0b96aaa348de61376b249bc340f41" -dependencies = [ - "regex", -] - [[package]] name = "paste" version = "1.0.7" @@ -1068,88 +948,6 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -[[package]] -name = "pest" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -dependencies = [ - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -dependencies = [ - "maplit", - "pest", - "sha-1", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator", - "phf_shared", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared", - "rand", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", - "uncased", -] - [[package]] name = "pin-project-lite" version = "0.2.9" @@ -1293,15 +1091,6 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - [[package]] name = "scopeguard" version = "1.1.0" @@ -1367,18 +1156,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha-1" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug", -] - [[package]] name = "sha1" version = "0.10.1" @@ -1387,7 +1164,7 @@ checksum = "c77f4e7f65455545c2153c1253d25056825e77ee2533f0e41deb65a93a34852f" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest", ] [[package]] @@ -1398,7 +1175,7 @@ checksum = "55deaec60f81eefe3cce0dc50bda92d6d8e88f2a27df7c5033b42afeb1ed2676" dependencies = [ "cfg-if", "cpufeatures", - "digest 0.10.3", + "digest", ] [[package]] @@ -1410,25 +1187,13 @@ dependencies = [ "libc", ] -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" - -[[package]] -name = "slug" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bc762e6a4b6c6fcaade73e77f9ebc6991b676f88bb2358bddb56560f073373" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ - "deunicode", + "autocfg", ] [[package]] @@ -1455,11 +1220,13 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "srv" -version = "1.0.2" +version = "1.0.3" dependencies = [ "actix-files", "actix-web", "actix-web-httpauth", + "askama", + "askama_actix", "clap", "env_logger", "lazy_static", @@ -1469,7 +1236,6 @@ dependencies = [ "rustls-pemfile", "serde", "sha2", - "tera", "time", "toml", "urlencoding", @@ -1492,28 +1258,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "tera" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9783d6ff395ae80cf17ed9a25360e7ba37742a79fa8fddabb073c5c7c8856d" -dependencies = [ - "chrono", - "chrono-tz", - "globwalk", - "humansize", - "lazy_static", - "percent-encoding", - "pest", - "pest_derive", - "rand", - "regex", - "serde", - "serde_json", - "slug", - "unic-segment", -] - [[package]] name = "termcolor" version = "1.1.3" @@ -1542,15 +1286,6 @@ dependencies = [ "terminal_size", ] -[[package]] -name = "thread_local" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" -dependencies = [ - "once_cell", -] - [[package]] name = "time" version = "0.3.11" @@ -1664,71 +1399,6 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" -[[package]] -name = "ucd-trie" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89570599c4fe5585de2b388aab47e99f7fa4e9238a1399f707a02e356058141c" - -[[package]] -name = "uncased" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b01702b0fd0b3fadcf98e098780badda8742d4f4a7676615cad90e8ac73622" -dependencies = [ - "version_check", -] - -[[package]] -name = "unic-char-property" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8c57a407d9b6fa02b4795eb81c5b6652060a15a7903ea981f3d723e6c0be221" -dependencies = [ - "unic-char-range", -] - -[[package]] -name = "unic-char-range" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0398022d5f700414f6b899e10b8348231abf9173fa93144cbc1a43b9793c1fbc" - -[[package]] -name = "unic-common" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" - -[[package]] -name = "unic-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ed5d26be57f84f176157270c112ef57b86debac9cd21daaabbe56db0f88f23" -dependencies = [ - "unic-ucd-segment", -] - -[[package]] -name = "unic-ucd-segment" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2079c122a62205b421f499da10f3ee0f7697f012f55b675e002483c73ea34700" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - -[[package]] -name = "unic-ucd-version" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96bd2f2237fe450fcd0a1d2f5f4e91711124f7857ba2e964247776ebeeb7b0c4" -dependencies = [ - "unic-common", -] - [[package]] name = "unicase" version = "2.6.0" @@ -1789,17 +1459,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/Cargo.toml b/Cargo.toml index a0c81e4..0f0d088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,12 +3,14 @@ authors = ["Tim_Paik "] description = "simple http server written in rust" edition = "2018" name = "srv" -version = "1.0.2" +version = "1.0.3" [dependencies] actix-files = "0.6" actix-web = {version = "4.1", features = ["rustls"]} -actix-web-httpauth = "0.6" +actix-web-httpauth = "0.7" +askama = "0.11" +askama_actix = "0.13" clap = {version = "3.2", features = ["wrap_help", "color", "cargo"]} env_logger = "0.9" lazy_static = "1.4" @@ -18,7 +20,6 @@ rustls = "0.20" rustls-pemfile = "1.0" serde = {version = "1.0", features = ["derive"]} sha2 = "0.10" -tera = "1.16" time = { version = "0.3", features = ["formatting", "parsing"] } toml = "0.5" urlencoding = "2.1" diff --git a/README.md b/README.md index f17912d..18515db 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ This is a simple HTTP Server for use in a development environment, inspired by [ ### Built With - [clap](https://github.com/clap-rs/clap) Provide command line parameter analysis -- [tera](https://github.com/Keats/tera) Provide template support +- [askama](https://github.com/djc/askama) Provide template support - [actix-web](https://github.com/actix/actix-web) Main frame - [actix-files](https://github.com/actix/actix-web/tree/master/actix-files) Provide static resources - [actix-web-httpauth](https://github.com/actix/actix-extras/tree/master/actix-web-httpauth) Provide authentication diff --git a/src/filetype.rs b/src/filetype.rs new file mode 100644 index 0000000..1ee7bad --- /dev/null +++ b/src/filetype.rs @@ -0,0 +1,120 @@ +#[inline] +pub fn get_file_type(from: &std::path::Path) -> String { + match from.extension() { + Some(os_str) => match os_str.to_str().unwrap_or("") { + "7z" => "archive", + "bz" => "archive", + "bz2" => "archive", + "cab" => "archive", + "gz" => "archive", + "iso" => "archive", + "rar" => "archive", + "xz" => "archive", + "zip" => "archive", + "zst" => "archive", + "zstd" => "archive", + "doc" => "word", + "docx" => "word", + "ppt" => "powerpoint", + "pptx" => "powerpoint", + "xls" => "excel", + "xlsx" => "excel", + "heic" => "image", + "pdf" => "pdf", + // JavaScript / TypeScript + "js" => "code", + "cjs" => "code", + "mjs" => "code", + "jsx" => "code", + "ts" => "code", + "tsx" => "code", + "json" => "code", + "coffee" => "code", + // HTML / CSS + "html" => "code", + "htm" => "code", + "xml" => "code", + "xhtml" => "code", + "vue" => "code", + "ejs" => "code", + "template" => "code", + "tmpl" => "code", + "pug" => "code", + "art" => "code", + "hbs" => "code", + "css" => "code", + "scss" => "code", + "sass" => "code", + "less" => "code", + // Python + "py" => "code", + "pyc" => "code", + // JVM + "java" => "code", + "kt" => "code", + "kts" => "code", + "gradle" => "code", + "groovy" => "code", + "scala" => "code", + "jsp" => "code", + // Shell + "sh" => "code", + // Php + "php" => "code", + // C / C++ + "c" => "code", + "cc" => "code", + "cpp" => "code", + "h" => "code", + "cmake" => "code", + // C# + "cs" => "code", + "xaml" => "code", + "sln" => "code", + "csproj" => "code", + // Golang + "go" => "code", + "mod" => "code", + "sum" => "code", + // Swift + "swift" => "code", + "plist" => "code", + "xib" => "code", + "xcconfig" => "code", + "entitlements" => "code", + "xcworkspacedata" => "code", + "pbxproj" => "code", + // Ruby + "rb" => "code", + // Rust + "rs" => "code", + // Objective-C + "m" => "code", + // Dart + "dart" => "code", + // Microsoft + "manifest" => "code", + "rc" => "code", + "cmd" => "code", + "bat" => "code", + "ps1" => "code", + // Config + "ini" => "code", + "yaml" => "code", + "toml" => "code", + "conf" => "code", + "properties" => "code", + "lock" => "alt", + _ => match mime_guess::from_path(from).first_or_octet_stream().type_() { + mime_guess::mime::AUDIO => "audio", + mime_guess::mime::IMAGE => "image", + mime_guess::mime::PDF => "pdf", + mime_guess::mime::VIDEO => "video", + mime_guess::mime::TEXT => "alt", + _ => "file", + }, + }, + None => "file", + } + .to_string() +} diff --git a/src/main.rs b/src/main.rs index 14668e2..0d8d125 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,158 +2,34 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -#[macro_use] -extern crate lazy_static; +mod filetype; -use actix_files as fs; use actix_web::{ - dev::{self, Service, ServiceResponse}, - http, middleware, App, HttpResponse, HttpServer, + dev::{Response, Service, ServiceRequest, ServiceResponse}, + http, middleware, App, HttpRequest, HttpResponse, HttpServer, }; +use actix_web_httpauth::{ + extractors::{basic::BasicAuth, AuthenticationError}, + headers::www_authenticate::basic::Basic, + middleware::HttpAuthentication, +}; +use askama_actix::TemplateToResponse; use clap::Arg; use env_logger::fmt::Color; use log::{error, info}; use serde::{Deserialize, Serialize}; use sha2::Digest; use std::{ + borrow::Cow, env::{set_var, var}, - fs::read_dir, - io::{BufReader, Error, ErrorKind, Read, Write}, + fs::{self, metadata, read_dir}, + io::{self, BufReader, Read, Write}, net::IpAddr, path::{Path, PathBuf}, + process::Command, str::FromStr, }; - -lazy_static! { - pub static ref TEMPLATE: tera::Tera = { - let mut tera = tera::Tera::default(); - tera.add_raw_template("index", include_str!("../templates/index.html.tera")) - .unwrap(); - tera - }; -} - -#[inline] -fn get_file_type(from: &Path) -> String { - match from.extension() { - Some(os_str) => match os_str.to_str().unwrap_or("") { - "7z" => "archive", - "bz" => "archive", - "bz2" => "archive", - "cab" => "archive", - "gz" => "archive", - "iso" => "archive", - "rar" => "archive", - "xz" => "archive", - "zip" => "archive", - "zst" => "archive", - "zstd" => "archive", - "doc" => "word", - "docx" => "word", - "ppt" => "powerpoint", - "pptx" => "powerpoint", - "xls" => "excel", - "xlsx" => "excel", - "heic" => "image", - "pdf" => "pdf", - // JavaScript / TypeScript - "js" => "code", - "cjs" => "code", - "mjs" => "code", - "jsx" => "code", - "ts" => "code", - "tsx" => "code", - "json" => "code", - "coffee" => "code", - // HTML / CSS - "html" => "code", - "htm" => "code", - "xml" => "code", - "xhtml" => "code", - "vue" => "code", - "ejs" => "code", - "template" => "code", - "tmpl" => "code", - "pug" => "code", - "art" => "code", - "hbs" => "code", - "tera" => "code", - "css" => "code", - "scss" => "code", - "sass" => "code", - "less" => "code", - // Python - "py" => "code", - "pyc" => "code", - // JVM - "java" => "code", - "kt" => "code", - "kts" => "code", - "gradle" => "code", - "groovy" => "code", - "scala" => "code", - "jsp" => "code", - // Shell - "sh" => "code", - // Php - "php" => "code", - // C / C++ - "c" => "code", - "cc" => "code", - "cpp" => "code", - "h" => "code", - "cmake" => "code", - // C# - "cs" => "code", - "xaml" => "code", - "sln" => "code", - "csproj" => "code", - // Golang - "go" => "code", - "mod" => "code", - "sum" => "code", - // Swift - "swift" => "code", - "plist" => "code", - "xib" => "code", - "xcconfig" => "code", - "entitlements" => "code", - "xcworkspacedata" => "code", - "pbxproj" => "code", - // Ruby - "rb" => "code", - // Rust - "rs" => "code", - // Objective-C - "m" => "code", - // Dart - "dart" => "code", - // Microsoft - "manifest" => "code", - "rc" => "code", - "cmd" => "code", - "bat" => "code", - "ps1" => "code", - // Config - "ini" => "code", - "yaml" => "code", - "toml" => "code", - "conf" => "code", - "properties" => "code", - "lock" => "alt", - _ => match mime_guess::from_path(from).first_or_octet_stream().type_() { - mime_guess::mime::AUDIO => "audio", - mime_guess::mime::IMAGE => "image", - mime_guess::mime::PDF => "pdf", - mime_guess::mime::VIDEO => "video", - mime_guess::mime::TEXT => "alt", - _ => "file", - }, - }, - None => "file", - } - .to_string() -} +use time::OffsetDateTime; #[derive(Deserialize)] struct Package { @@ -179,6 +55,8 @@ struct File { modified: String, } +#[derive(askama_actix::Template)] +#[template(path = "index.html")] #[derive(Serialize)] struct IndexContext { title: String, @@ -189,8 +67,8 @@ struct IndexContext { fn render_index( dir: &actix_files::Directory, - req: &actix_web::HttpRequest, -) -> Result { + req: &HttpRequest, +) -> Result { let mut index = dir.path.clone(); index.push("index.html"); if index.exists() && index.is_file() { @@ -216,8 +94,7 @@ fn render_index( if path.is_empty() { continue; } - let path = - urlencoding::decode(path).unwrap_or(std::borrow::Cow::Borrowed("[Parse URL Error]")); + let path = urlencoding::decode(path).unwrap_or(Cow::Borrowed("[Parse URL Error]")); let path = path.into_owned(); context.paths.push(path); } @@ -252,7 +129,7 @@ fn render_index( } }; let modified = match metadata.modified() { - Ok(time) => time::OffsetDateTime::from(time) + Ok(time) => OffsetDateTime::from(time) .format(time::macros::format_description!( "[year]/[month]/[day] [hour]:[minute]:[second]" )) @@ -266,7 +143,7 @@ fn render_index( context.dirs.push(Dir { name, modified }); } else if metadata.is_file() { let size = metadata.len(); - let filetype = get_file_type(&path.path()); + let filetype = filetype::get_file_type(&path.path()); context.files.push(File { name, size, @@ -280,21 +157,7 @@ fn render_index( context.title = context.paths.last().unwrap_or(&"/".to_string()).to_string(); context.dirs.sort(); context.files.sort(); - let content = tera::Context::from_serialize(&context); - let content = match content { - Ok(ctx) => ctx, - Err(e) => { - error!(target: "tera::Context::from_serialize", "[ERROR] Read modified time error: {}", e.to_string()); - return Err(Error::new(ErrorKind::Other, e.to_string())); - } - }; - let index = TEMPLATE - .render("index", &content) - .unwrap_or_else(|_| "TEMPLATE RENDER ERROR".to_string()); - let res = HttpResponse::Ok() - .content_type("text/html; charset=utf-8") - .body(index); - Ok(ServiceResponse::new(req.to_owned(), res)) + Ok(ServiceResponse::new(req.to_owned(), context.to_response())) } #[inline] @@ -316,31 +179,27 @@ fn hash(from: &str) -> String { #[inline] async fn validator( - req: dev::ServiceRequest, - auth: actix_web_httpauth::extractors::basic::BasicAuth, -) -> Result { + req: ServiceRequest, + auth: BasicAuth, +) -> Result { if auth.user_id() == var("AUTH_USERNAME") .unwrap_or_else(|_| "".to_string()) .as_str() - && hash(auth.password().unwrap_or(&std::borrow::Cow::from(""))) + && hash(auth.password().unwrap_or(&Cow::from(""))) == var("AUTH_PASSWORD") .unwrap_or_else(|_| "".to_string()) .as_str() { return Ok(req); } - let err = actix_web_httpauth::extractors::AuthenticationError::new( - actix_web_httpauth::headers::www_authenticate::basic::Basic::with_realm( - "Incorrect username or password", - ), - ); - Err(actix_web::Error::from(err)) + let err = AuthenticationError::new(Basic::with_realm("Incorrect username or password")); + Err((actix_web::Error::from(err), req)) } #[actix_web::main] -async fn main() -> std::io::Result<()> { - let check_does_dir_exits = |path: &str| match std::fs::metadata(path) { +async fn main() -> io::Result<()> { + let check_does_dir_exits = |path: &str| match metadata(path) { Ok(meta) => { if meta.is_dir() { Ok(()) @@ -350,7 +209,7 @@ async fn main() -> std::io::Result<()> { } Err(e) => Err(e.to_string()), }; - let check_does_file_exits = |path: &str| match std::fs::metadata(path) { + let check_does_file_exits = |path: &str| match metadata(path) { Ok(metadata) => { if metadata.is_file() { Ok(()) @@ -463,9 +322,9 @@ async fn main() -> std::io::Result<()> { let open_in_browser = |url: &str| { if cfg!(target_os = "windows") { - std::process::Command::new("explorer").arg(url).spawn().ok(); + Command::new("explorer").arg(url).spawn().ok(); } else if cfg!(target_os = "macos") { - std::process::Command::new("open").arg(url).spawn().ok(); + Command::new("open").arg(url).spawn().ok(); } else if cfg!(target_os = "linux") || cfg!(target_os = "android") || cfg!(target_os = "freebsd") @@ -473,7 +332,7 @@ async fn main() -> std::io::Result<()> { || cfg!(target_os = "openbsd") || cfg!(target_os = "netbsd") { - std::process::Command::new("xdg-open").arg(url).spawn().ok(); + Command::new("xdg-open").arg(url).spawn().ok(); } }; @@ -505,15 +364,12 @@ async fn main() -> std::io::Result<()> { if record.target() == "actix_web::middleware::logger" { let data: Vec<&str> = data.splitn(5, '^').collect(); let time = blue.value( - time::OffsetDateTime::parse( - data[0], - &time::format_description::well_known::Rfc3339, - ) - .unwrap_or(time::OffsetDateTime::UNIX_EPOCH) - .format(time::macros::format_description!( - "[year]/[month]/[day] [hour]:[minute]:[second]" - )) - .unwrap_or_else(|_| "".to_string()), + OffsetDateTime::parse(data[0], &time::format_description::well_known::Rfc3339) + .unwrap_or(OffsetDateTime::UNIX_EPOCH) + .format(time::macros::format_description!( + "[year]/[month]/[day] [hour]:[minute]:[second]" + )) + .unwrap_or_else(|_| "".to_string()), ); let ipaddr = blue.value(data[1]); let status_code = data[2].parse().unwrap_or(500); @@ -533,7 +389,7 @@ async fn main() -> std::io::Result<()> { }); let content = blue.value( urlencoding::decode(data[4]) - .unwrap_or(std::borrow::Cow::Borrowed("[Parse URL Error]")) + .unwrap_or(Cow::Borrowed("[Parse URL Error]")) .into_owned(), ); return writeln!( @@ -580,7 +436,7 @@ async fn main() -> std::io::Result<()> { .init(); let addr = if let Some(matches) = matches.subcommand_matches("doc") { - let mut cargo_toml = match std::fs::File::open("./Cargo.toml") { + let mut cargo_toml = match fs::File::open("./Cargo.toml") { Ok(file) => file, Err(e) => { error!("[ERROR] {}", e.to_string()); @@ -604,7 +460,7 @@ async fn main() -> std::io::Result<()> { }; let crate_name = contents.package.name; info!("[INFO] Generating document (may take a while)"); - match std::process::Command::new("cargo").arg("doc").output() { + match Command::new("cargo").arg("doc").output() { Ok(output) => { let output = std::str::from_utf8(&output.stderr).unwrap_or(""); if output.starts_with("error: could not find `Cargo.toml` in") { @@ -680,7 +536,7 @@ async fn main() -> std::io::Result<()> { if isdotfile && var("DOTFILES").unwrap_or_else(|_| "false".to_string()) != "true" { - return dev::Response::new(http::StatusCode::FORBIDDEN).into_body(); + return Response::new(http::StatusCode::FORBIDDEN).into_body(); } body })) @@ -689,15 +545,15 @@ async fn main() -> std::io::Result<()> { .wrap(middleware::Compress::default()) .wrap(middleware::Condition::new( var("ENABLE_AUTH").unwrap_or_else(|_| "false".to_string()) == "true", - actix_web_httpauth::middleware::HttpAuthentication::basic(validator), + HttpAuthentication::basic(validator), )) .wrap(middleware::Logger::new("%t^%a^%s^%D^%r")); - let files = fs::Files::new("/", var("ROOT").unwrap_or_else(|_| ".".to_string())) + let files = actix_files::Files::new("/", var("ROOT").unwrap_or_else(|_| ".".to_string())) .use_hidden_files() .prefer_utf8(true) .show_files_listing() .files_listing_renderer(render_index) - .default_handler(|req: dev::ServiceRequest| { + .default_handler(|req: ServiceRequest| { let (http_req, _payload) = req.into_parts(); async { let path = var("ROOT").unwrap_or_else(|_| ".".to_string()); @@ -707,7 +563,7 @@ async fn main() -> std::io::Result<()> { && path.is_file() && var("SPA").unwrap_or_else(|_| "false".to_string()) == "true" { - let res = fs::NamedFile::open(path)?.into_response(&http_req); + let res = actix_files::NamedFile::open(path)?.into_response(&http_req); return Ok(ServiceResponse::new(http_req, res)); } Ok(ServiceResponse::new( @@ -720,10 +576,10 @@ async fn main() -> std::io::Result<()> { }); let server = if enable_tls { let cert = &mut BufReader::new( - std::fs::File::open(Path::new(matches.value_of("cert").unwrap())).unwrap(), + fs::File::open(Path::new(matches.value_of("cert").unwrap())).unwrap(), ); let key = &mut BufReader::new( - std::fs::File::open(Path::new(matches.value_of("key").unwrap())).unwrap(), + fs::File::open(Path::new(matches.value_of("key").unwrap())).unwrap(), ); let cert = rustls_pemfile::certs(cert) .unwrap() diff --git a/templates/index.html.tera b/templates/index.html similarity index 80% rename from templates/index.html.tera rename to templates/index.html index b9c030a..643f651 100644 --- a/templates/index.html.tera +++ b/templates/index.html @@ -1,6 +1,6 @@ {# This Source Code Form is subject to the terms of the Mozilla Public - # License, v. 2.0. If a copy of the MPL was not distributed with this - # file, You can obtain one at https://mozilla.org/MPL/2.0/. #} +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. #} @@ -12,9 +12,12 @@ {{ title }} - +