From ebbdd7185f309304ea4bad0ef6ad0496451646fb Mon Sep 17 00:00:00 2001 From: Spike <19519553+spikecodes@users.noreply.github.com> Date: Tue, 9 Feb 2021 09:38:52 -0800 Subject: [PATCH] Move from Actix Web to Tide (#99) * Initial commit * Port posts * Pinpoint Tide Bug * Revert testing * Add basic sub support * Unwrap nested routes * Front page & sync templates * Port remaining functions * Log request errors * Clean main and settings * Handle /w/ requests * Create template() util * Reduce caching time to 30s * Fix subscription redirects * Handle frontpage sorting --- Cargo.lock | 1744 ++++++++++++++++++++------------------ Cargo.toml | 14 +- rustfmt.toml | 2 +- src/main.rs | 295 ++++--- src/post.rs | 22 +- src/proxy.rs | 35 +- src/search.rs | 42 +- src/settings.rs | 36 +- src/subreddit.rs | 104 +-- src/user.rs | 19 +- src/utils.rs | 115 +-- static/manifest.json | 28 +- templates/base.html | 8 +- templates/settings.html | 4 +- templates/subreddit.html | 4 +- 15 files changed, 1283 insertions(+), 1189 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba72f38..d2da38c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,290 +1,59 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "actix-codec" -version = "0.3.0" +name = "aead" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78d1833b3838dbe990df0f1f87baf640cf6146e898166afe401839d1b001e570" +checksum = "7fc95d1bdb8e6666b2b217308eeeb09f2d6728d104be3e31916cc74d15420331" dependencies = [ - "bitflags", - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project 0.4.27", - "tokio", - "tokio-util", + "generic-array", ] [[package]] -name = "actix-connect" -version = "2.0.0" +name = "aes" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177837a10863f15ba8d3ae3ec12fac1099099529ed20083a27fdfe247381d0dc" +checksum = "884391ef1066acaa41e766ba8f596341b96e93ce34f9a43e7d24bf0a0eaf0561" dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "derive_more", - "either", - "futures-util", - "http", - "log", - "rustls 0.18.1", - "tokio-rustls", - "trust-dns-proto", - "trust-dns-resolver", - "webpki", + "aes-soft", + "aesni", + "cipher", ] [[package]] -name = "actix-http" -version = "2.2.0" +name = "aes-gcm" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "452299e87817ae5673910e53c243484ca38be3828db819b6011736fc6982e874" +checksum = "5278b5fabbb9bd46e24aa69b2fdea62c99088e0a950a9be40e3e0101298f88da" dependencies = [ - "actix-codec", - "actix-connect", - "actix-rt", - "actix-service", - "actix-threadpool", - "actix-tls", - "actix-utils", - "base64 0.13.0", - "bitflags", - "brotli2", - "bytes 0.5.6", - "cookie", - "copyless", - "derive_more", - "either", - "encoding_rs", - "flate2", - "futures-channel", - "futures-core", - "futures-util", - "fxhash", - "h2", - "http", - "httparse", - "indexmap", - "itoa", - "language-tags", - "lazy_static", - "log", - "mime", - "percent-encoding", - "pin-project 1.0.5", - "rand", - "regex", - "serde", - "serde_json", - "serde_urlencoded", - "sha-1", - "slab", - "time", + "aead", + "aes", + "cipher", + "ctr", + "ghash", + "subtle", ] [[package]] -name = "actix-macros" -version = "0.1.3" +name = "aes-soft" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655" +checksum = "be14c7498ea50828a38d0e24a765ed2effe92a705885b57d029cd67d45744072" dependencies = [ - "quote", - "syn", + "cipher", + "opaque-debug", ] [[package]] -name = "actix-router" -version = "0.2.6" +name = "aesni" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8be584b3b6c705a18eabc11c4059cf83b255bdd8511673d1d569f4ce40c69de" +checksum = "ea2e11f5e94c2f7d386164cc2aa1f97823fed6f259e486940a71c174dd01b0ce" dependencies = [ - "bytestring", - "http", - "log", - "regex", - "serde", + "cipher", + "opaque-debug", ] -[[package]] -name = "actix-rt" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143fcc2912e0d1de2bcf4e2f720d2a60c28652ab4179685a1ee159e0fb3db227" -dependencies = [ - "actix-macros", - "actix-threadpool", - "copyless", - "futures-channel", - "futures-util", - "smallvec", - "tokio", -] - -[[package]] -name = "actix-server" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45407e6e672ca24784baa667c5d32ef109ccdd8d5e0b5ebb9ef8a67f4dfb708e" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "actix-utils", - "futures-channel", - "futures-util", - "log", - "mio", - "mio-uds", - "num_cpus", - "slab", - "socket2", -] - -[[package]] -name = "actix-service" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0052435d581b5be835d11f4eb3bce417c8af18d87ddf8ace99f8e67e595882bb" -dependencies = [ - "futures-util", - "pin-project 0.4.27", -] - -[[package]] -name = "actix-testing" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47239ca38799ab74ee6a8a94d1ce857014b2ac36f242f70f3f75a66f691e791c" -dependencies = [ - "actix-macros", - "actix-rt", - "actix-server", - "actix-service", - "log", - "socket2", -] - -[[package]] -name = "actix-threadpool" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d209f04d002854b9afd3743032a27b066158817965bf5d036824d19ac2cc0e30" -dependencies = [ - "derive_more", - "futures-channel", - "lazy_static", - "log", - "num_cpus", - "parking_lot", - "threadpool", -] - -[[package]] -name = "actix-tls" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24789b7d7361cf5503a504ebe1c10806896f61e96eca9a7350e23001aca715fb" -dependencies = [ - "actix-codec", - "actix-service", - "actix-utils", - "futures-util", - "rustls 0.18.1", - "tokio-rustls", - "webpki", - "webpki-roots 0.20.0", -] - -[[package]] -name = "actix-utils" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9022dec56632d1d7979e59af14f0597a28a830a9c1c7fec8b2327eb9f16b5a" -dependencies = [ - "actix-codec", - "actix-rt", - "actix-service", - "bitflags", - "bytes 0.5.6", - "either", - "futures-channel", - "futures-sink", - "futures-util", - "log", - "pin-project 0.4.27", - "slab", -] - -[[package]] -name = "actix-web" -version = "3.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e641d4a172e7faa0862241a20ff4f1f5ab0ab7c279f00c2d4587b77483477b86" -dependencies = [ - "actix-codec", - "actix-http", - "actix-macros", - "actix-router", - "actix-rt", - "actix-server", - "actix-service", - "actix-testing", - "actix-threadpool", - "actix-tls", - "actix-utils", - "actix-web-codegen", - "awc", - "bytes 0.5.6", - "derive_more", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "fxhash", - "log", - "mime", - "pin-project 1.0.5", - "regex", - "rustls 0.18.1", - "serde", - "serde_json", - "serde_urlencoded", - "socket2", - "time", - "tinyvec", - "url", -] - -[[package]] -name = "actix-web-codegen" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "addr2line" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" - [[package]] name = "aho-corasick" version = "0.7.15" @@ -294,6 +63,18 @@ dependencies = [ "memchr", ] +[[package]] +name = "anyhow" +version = "1.0.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" + +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + [[package]] name = "arrayvec" version = "0.5.2" @@ -346,6 +127,114 @@ dependencies = [ "toml", ] +[[package]] +name = "async-attributes" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3203e79f4dd9bdda415ed03cf14dae5a2bf775c683a00f94e9cd1faf0f596e5" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "async-channel" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59740d83946db6a5af71ae25ddf9562c2b176b2ca42cf99a455f09f4a220d6b9" +dependencies = [ + "concurrent-queue", + "event-listener", + "futures-core", +] + +[[package]] +name = "async-dup" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7427a12b8dc09291528cfb1da2447059adb4a257388c2acd6497a79d55cf6f7c" +dependencies = [ + "futures-io", + "simple-mutex", +] + +[[package]] +name = "async-executor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb877970c7b440ead138f6321a3b5395d6061183af779340b65e20c0fede9146" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "once_cell", + "vec-arena", +] + +[[package]] +name = "async-global-executor" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9586ec52317f36de58453159d48351bc244bc24ced3effc1fce22f3d48664af6" +dependencies = [ + "async-channel", + "async-executor", + "async-io", + "async-mutex", + "blocking", + "futures-lite", + "num_cpus", + "once_cell", +] + +[[package]] +name = "async-h1" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e9e2a9745d9cd0d92ed7641ce4d07568985762f92633260f0afe8ac7917d9d7" +dependencies = [ + "async-channel", + "async-dup", + "async-std", + "byte-pool", + "futures-core", + "http-types", + "httparse", + "lazy_static", + "log", + "pin-project 1.0.5", +] + +[[package]] +name = "async-io" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9315f8f07556761c3e48fec2e6b276004acf426e6dc068b2c2251854d65ee0fd" +dependencies = [ + "concurrent-queue", + "fastrand", + "futures-lite", + "libc", + "log", + "nb-connect", + "once_cell", + "parking", + "polling", + "vec-arena", + "waker-fn", + "winapi", +] + +[[package]] +name = "async-lock" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1996609732bde4a9988bc42125f55f2af5f3c36370e27c778d5191a4a1b63bfb" +dependencies = [ + "event-listener", +] + [[package]] name = "async-mutex" version = "1.4.0" @@ -355,6 +244,22 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-process" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef37b86e2fa961bae5a4d212708ea0154f904ce31d1a4a7f47e1bbc33a0c040b" +dependencies = [ + "async-io", + "blocking", + "cfg-if 1.0.0", + "event-listener", + "futures-lite", + "once_cell", + "signal-hook", + "winapi", +] + [[package]] name = "async-recursion" version = "0.3.2" @@ -366,6 +271,76 @@ dependencies = [ "syn", ] +[[package]] +name = "async-session" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "345022a2eed092cd105cc1b26fd61c341e100bd5fcbbd792df4baf31c2cc631f" +dependencies = [ + "anyhow", + "async-std", + "async-trait", + "base64 0.12.3", + "bincode", + "blake3", + "chrono", + "hmac 0.8.1", + "kv-log-macro", + "rand", + "serde", + "serde_json", + "sha2", +] + +[[package]] +name = "async-sse" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53bba003996b8fd22245cd0c59b869ba764188ed435392cf2796d03b805ade10" +dependencies = [ + "async-channel", + "async-std", + "http-types", + "log", + "memchr", + "pin-project-lite 0.1.11", +] + +[[package]] +name = "async-std" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f06685bad74e0570f5213741bea82158279a4103d988e57bfada11ad230341" +dependencies = [ + "async-attributes", + "async-channel", + "async-global-executor", + "async-io", + "async-lock", + "async-process", + "crossbeam-utils 0.8.1", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "num_cpus", + "once_cell", + "pin-project-lite 0.2.4", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91831deabf0d6d7ec49552e489aed63b7456a7a3c46cff62adad428110b0af0" + [[package]] name = "async-trait" version = "0.1.42" @@ -377,51 +352,18 @@ dependencies = [ "syn", ] +[[package]] +name = "atomic-waker" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" + [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "awc" -version = "2.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b381e490e7b0cfc37ebc54079b0413d8093ef43d14a4e4747083f7fa47a9e691" -dependencies = [ - "actix-codec", - "actix-http", - "actix-rt", - "actix-service", - "base64 0.13.0", - "bytes 0.5.6", - "cfg-if 1.0.0", - "derive_more", - "futures-core", - "log", - "mime", - "percent-encoding", - "rand", - "rustls 0.18.1", - "serde", - "serde_json", - "serde_urlencoded", -] - -[[package]] -name = "backtrace" -version = "0.3.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" -dependencies = [ - "addr2line", - "cfg-if 1.0.0", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "base-x" version = "0.2.8" @@ -440,6 +382,16 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +[[package]] +name = "bincode" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" +dependencies = [ + "byteorder", + "serde", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -458,6 +410,21 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake3" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9ff35b701f3914bdb8fad3368d822c766ef2858b2583198e41639b936f09d3f" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac 0.8.0", + "digest", +] + [[package]] name = "block-buffer" version = "0.9.0" @@ -468,23 +435,17 @@ dependencies = [ ] [[package]] -name = "brotli-sys" -version = "0.3.2" +name = "blocking" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +checksum = "c5e170dbede1f740736619b776d7251cb1b9095c435c34d8ca9f57fcd2f335e9" dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "brotli2" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" -dependencies = [ - "brotli-sys", - "libc", + "async-channel", + "async-task", + "atomic-waker", + "fastrand", + "futures-lite", + "once_cell", ] [[package]] @@ -493,6 +454,16 @@ version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9" +[[package]] +name = "byte-pool" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38e98299d518ec351ca016363e0cbfc77059dcd08dfa9700d15e405536097a" +dependencies = [ + "crossbeam-queue", + "stable_deref_trait", +] + [[package]] name = "byteorder" version = "1.4.2" @@ -512,13 +483,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" [[package]] -name = "bytestring" -version = "1.0.0" +name = "cache-padded" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90706ba19e97b90786e19dc0d5e2abd80008d99d4c0c5d1ad0b5e72cec7c494d" -dependencies = [ - "bytes 1.0.1", -] +checksum = "631ae5198c9be5e753e5cc215e1bd73c2b466a3565173db433f52bb9d3e66dba" [[package]] name = "cached" @@ -573,10 +541,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "chunked_transfer" -version = "1.4.0" +name = "chrono" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff857943da45f546682664a79488be82e69e43c1a7a2307679ab9afb3a66d2e" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "serde", + "time 0.1.44", + "winapi", +] + +[[package]] +name = "cipher" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f8e7987cbd042a63249497f41aed09f8e65add917ea6566effbc56578d6801" +dependencies = [ + "generic-array", +] + +[[package]] +name = "concurrent-queue" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ed07550be01594c6026cff2a1d7fe9c8f683caa798e12b68694ac9e88286a3" +dependencies = [ + "cache-padded", +] [[package]] name = "const_fn" @@ -584,23 +578,29 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "cookie" version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784ad0fbab4f3e9cef09f20e0aea6000ae08d2cb98ac4c0abc53df18803d702f" dependencies = [ + "aes-gcm", + "base64 0.12.3", + "hkdf", + "hmac 0.10.1", "percent-encoding", - "time", + "rand", + "sha2", + "time 0.2.25", "version_check", ] -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - [[package]] name = "cpuid-bool" version = "0.1.2" @@ -608,12 +608,112 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634" [[package]] -name = "crc32fast" -version = "1.2.1" +name = "cpuid-bool" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "dcb25d077389e53838a8158c8e99174c5a9d902dee4904320db714f3c653ffba" + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +dependencies = [ + "autocfg", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" +dependencies = [ + "autocfg", "cfg-if 1.0.0", + "lazy_static", +] + +[[package]] +name = "crypto-mac" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "crypto-mac" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" +dependencies = [ + "generic-array", + "subtle", +] + +[[package]] +name = "ctor" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "ctr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a30d54f7443bf3d6191dcd486aca19e67cb3c49fa7a06a319966346707e7f" +dependencies = [ + "cipher", +] + +[[package]] +name = "curl" +version = "0.4.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e268162af1a5fe89917ae25ba3b0a77c8da752bdc58e7dbb4f15b91fbd33756e" +dependencies = [ + "curl-sys", + "libc", + "openssl-probe", + "openssl-sys", + "schannel", + "socket2", + "winapi", +] + +[[package]] +name = "curl-sys" +version = "0.4.40+curl-7.75.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffafc1c35958318bd7fdd0582995ce4c72f4f461a8e70499ccee83a619fd562" +dependencies = [ + "cc", + "libc", + "libnghttp2-sys", + "libz-sys", + "openssl-sys", + "pkg-config", + "vcpkg", + "winapi", ] [[package]] @@ -652,15 +752,10 @@ dependencies = [ ] [[package]] -name = "derive_more" -version = "0.99.11" +name = "data-encoding" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] +checksum = "3ee2393c4a91429dffb4bedf19f4d6abf27d8a732c8ce4980305d782e5426d57" [[package]] name = "digest" @@ -677,33 +772,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" -[[package]] -name = "either" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" - [[package]] name = "encoding_rs" -version = "0.8.26" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "enum-as-inner" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "event-listener" version = "2.5.1" @@ -711,15 +788,39 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7531096570974c3a9dcf9e4b8e1cede1ec26cf5046219fb3b9d897503b9be59" [[package]] -name = "flate2" -version = "1.0.20" +name = "fastrand" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "ca5faf057445ce5c9d4329e382b2ce7ca38550ef3b73a5348362d5f24e0c7fe3" dependencies = [ - "cfg-if 1.0.0", - "crc32fast", - "libc", - "miniz_oxide", + "instant", +] + +[[package]] +name = "femme" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af1a24f391a5a94d756db5092c6576aad494b88a71a5a36b20c67b63e0df034" +dependencies = [ + "cfg-if 0.1.10", + "js-sys", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "flume" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bebadab126f8120d410b677ed95eee4ba6eb7c6dd8e34a5ec88a08050e26132" +dependencies = [ + "futures-core", + "futures-sink", + "spinning_top", ] [[package]] @@ -738,22 +839,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "funty" version = "1.1.0" @@ -808,6 +893,21 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28be053525281ad8259d47e4de5de657b25e7bac113458555bb4b70bc6870500" +[[package]] +name = "futures-lite" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4481d0cd0de1d204a4fa55e7d45f07b1d958abcb06714b3446438e2eff695fb" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite 0.2.4", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.12" @@ -855,15 +955,6 @@ dependencies = [ "slab", ] -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - [[package]] name = "generic-array" version = "0.14.4" @@ -882,33 +973,30 @@ checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] -name = "gimli" -version = "0.23.0" +name = "ghash" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" +checksum = "97304e4cd182c3846f7575ced3890c53012ce534ad9114046b0a9e00bb30a375" +dependencies = [ + "opaque-debug", + "polyval", +] [[package]] -name = "h2" -version = "0.2.7" +name = "gloo-timers" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e4728fd124914ad25e99e3d15a9361a879f6620f63cb56bbb08f95abb97a535" +checksum = "47204a46aaff920a1ea58b11d03dec6f704287d27561724a4631e450654a891f" dependencies = [ - "bytes 0.5.6", - "fnv", + "futures-channel", "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", - "tracing-futures", + "js-sys", + "wasm-bindgen", + "web-sys", ] [[package]] @@ -917,15 +1005,6 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" -[[package]] -name = "heck" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "hermit-abi" version = "0.1.18" @@ -936,14 +1015,33 @@ dependencies = [ ] [[package]] -name = "hostname" -version = "0.3.1" +name = "hkdf" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +checksum = "51ab2f639c231793c5f6114bdb9bbe50a7dbbfcd7c7c6bd8475dec2d991e964f" dependencies = [ - "libc", - "match_cfg", - "winapi 0.3.9", + "digest", + "hmac 0.10.1", +] + +[[package]] +name = "hmac" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" +dependencies = [ + "crypto-mac 0.8.0", + "digest", +] + +[[package]] +name = "hmac" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1441c6b1e930e2817404b5046f1f989899143a12bf92de603b69f4e0aee1e15" +dependencies = [ + "crypto-mac 0.10.0", + "digest", ] [[package]] @@ -957,6 +1055,41 @@ dependencies = [ "itoa", ] +[[package]] +name = "http-client" +version = "6.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010092b71b94ee49293995625ce7a607778b8b4099c8088fa84fd66bd3e0f21c" +dependencies = [ + "async-std", + "async-trait", + "http-types", + "isahc", + "log", +] + +[[package]] +name = "http-types" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32613ebb139d1d430ef5783676f84abfa06fc5f2b4b5a25220cdeeff7e16ef5c" +dependencies = [ + "anyhow", + "async-channel", + "async-std", + "base64 0.13.0", + "cookie", + "futures-lite", + "infer", + "pin-project-lite 0.2.4", + "rand", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "url", +] + [[package]] name = "httparse" version = "1.3.5" @@ -977,9 +1110,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094" dependencies = [ "matches", "unicode-bidi", @@ -987,14 +1120,10 @@ dependencies = [ ] [[package]] -name = "indexmap" -version = "1.6.1" +name = "infer" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" -dependencies = [ - "autocfg", - "hashbrown", -] +checksum = "64e9829a50b42bb782c1df523f78d332fe371b10c661e78b7a3c34b0198e9fac" [[package]] name = "instant" @@ -1006,24 +1135,26 @@ dependencies = [ ] [[package]] -name = "iovec" -version = "0.1.4" +name = "isahc" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +checksum = "e2948a0ce43e2c2ef11d7edf6816508998d99e13badd1150be0914205df9388a" dependencies = [ - "libc", -] - -[[package]] -name = "ipconfig" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e2f18aece9709094573a9f24f483c4f65caa4298e2f7ae1b71cc65d853fad7" -dependencies = [ - "socket2", - "widestring", - "winapi 0.3.9", - "winreg", + "bytes 0.5.6", + "crossbeam-utils 0.8.1", + "curl", + "curl-sys", + "flume", + "futures-lite", + "http", + "log", + "once_cell", + "slab", + "sluice", + "tracing", + "tracing-futures", + "url", + "waker-fn", ] [[package]] @@ -1042,21 +1173,14 @@ dependencies = [ ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "kv-log-macro" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "log", ] -[[package]] -name = "language-tags" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" - [[package]] name = "lazy_static" version = "1.4.0" @@ -1078,33 +1202,49 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.85" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" + +[[package]] +name = "libnghttp2-sys" +version = "0.1.6+1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0af55541a8827e138d59ec9e5877fb6095ece63fb6f4da45e7491b4fbd262855" +dependencies = [ + "cc", + "libc", +] [[package]] name = "libreddit" version = "0.2.9" dependencies = [ - "actix-web", "askama", "async-recursion", + "async-std", "base64 0.13.0", "cached", "futures", "regex", "serde", "serde_json", - "time", - "ureq", - "url", + "surf", + "tide", + "time 0.2.25", ] [[package]] -name = "linked-hash-map" -version = "0.5.4" +name = "libz-sys" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] [[package]] name = "lock_api" @@ -1122,29 +1262,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ "cfg-if 1.0.0", + "value-bag", ] -[[package]] -name = "lru-cache" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" -dependencies = [ - "linked-hash-map", -] - -[[package]] -name = "match_cfg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" - [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + [[package]] name = "memchr" version = "2.3.4" @@ -1158,66 +1290,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] -name = "miniz_oxide" -version = "0.4.3" +name = "mime_guess" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "adler", - "autocfg", + "mime", + "unicase", ] [[package]] -name = "mio" -version = "0.6.23" +name = "nb-connect" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +checksum = "8123a81538e457d44b933a02faf885d3fe8408806b23fa700e8f01c6c3a98998" dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - -[[package]] -name = "net2" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1232,6 +1321,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.14" @@ -1251,12 +1350,6 @@ dependencies = [ "libc", ] -[[package]] -name = "object" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" - [[package]] name = "once_cell" version = "1.5.2" @@ -1270,29 +1363,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] -name = "parking_lot" -version = "0.11.1" +name = "openssl-probe" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" + +[[package]] +name = "openssl-sys" +version = "0.9.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" dependencies = [ - "instant", - "lock_api", - "parking_lot_core", + "autocfg", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] -name = "parking_lot_core" -version = "0.8.2" +name = "parking" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ccb628cad4f84851442432c60ad8e1f607e29752d0bf072cbd0baf28aa34272" -dependencies = [ - "cfg-if 1.0.0", - "instant", - "libc", - "redox_syscall", - "smallvec", - "winapi 0.3.9", -] +checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" [[package]] name = "percent-encoding" @@ -1358,6 +1451,36 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" + +[[package]] +name = "polling" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a7bc6b2a29e632e45451c941832803a18cce6781db04de8a04696cdca8bde4" +dependencies = [ + "cfg-if 0.1.10", + "libc", + "log", + "wepoll-sys", + "winapi", +] + +[[package]] +name = "polyval" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eebcc4aa140b9abd2bc40d9c3f7ccec842679cd79045ac3a7ac698c1a064b7cd" +dependencies = [ + "cpuid-bool 0.2.0", + "opaque-debug", + "universal-hash", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1385,12 +1508,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.8" @@ -1447,12 +1564,6 @@ dependencies = [ "rand_core", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "regex" version = "1.4.3" @@ -1472,35 +1583,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] -name = "resolv-conf" -version = "0.7.0" +name = "route-recognizer" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" -dependencies = [ - "hostname", - "quick-error", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi 0.3.9", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" +checksum = "56770675ebc04927ded3e60633437841581c285dc6236109ea25fbf3beb7b59e" [[package]] name = "rustc_version" @@ -1511,54 +1597,28 @@ dependencies = [ "semver", ] -[[package]] -name = "rustls" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d1126dcf58e93cee7d098dbda643b5f92ed724f1f6a63007c1116eed6700c81" -dependencies = [ - "base64 0.12.3", - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "064fd21ff87c6e87ed4506e68beb42459caa4a0e2eb144932e6776768556980b" -dependencies = [ - "base64 0.13.0", - "log", - "ring", - "sct", - "webpki", -] - [[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +[[package]] +name = "schannel" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +dependencies = [ + "lazy_static", + "winapi", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -[[package]] -name = "sct" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3042af939fca8c3453b7af0f1c66e533a15a86169e39de2657310ade8f98d3c" -dependencies = [ - "ring", - "untrusted", -] - [[package]] name = "semver" version = "0.9.0" @@ -1596,15 +1656,27 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a" +checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" dependencies = [ "itoa", "ryu", "serde", ] +[[package]] +name = "serde_qs" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5af82de3c6549b001bec34961ff2d6a54339a87bab37ce901b693401f27de6cb" +dependencies = [ + "data-encoding", + "percent-encoding", + "serde", + "thiserror", +] + [[package]] name = "serde_urlencoded" version = "0.7.0" @@ -1618,23 +1690,33 @@ dependencies = [ ] [[package]] -name = "sha-1" +name = "sha1" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" + +[[package]] +name = "sha2" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b312c3731e3fe78a185e6b9b911a7aa715b8e31cce117975219aab2acf285d" +checksum = "fa827a14b29ab7f44778d14a88d3cb76e949c45083f7dbfa507d0cb699dc12de" dependencies = [ "block-buffer", "cfg-if 1.0.0", - "cpuid-bool", + "cpuid-bool 0.1.2", "digest", "opaque-debug", ] [[package]] -name = "sha1" -version = "0.6.0" +name = "signal-hook" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" +checksum = "780f5e3fe0c66f67197236097d89de1e86216f1f6fdeaf47c442f854ab46c240" +dependencies = [ + "libc", + "signal-hook-registry", +] [[package]] name = "signal-hook-registry" @@ -1645,6 +1727,15 @@ dependencies = [ "libc", ] +[[package]] +name = "simple-mutex" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38aabbeafa6f6dead8cebf246fe9fae1f9215c8d29b3a69f93bd62a9e4a3dcd6" +dependencies = [ + "event-listener", +] + [[package]] name = "slab" version = "0.4.2" @@ -1652,10 +1743,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] -name = "smallvec" -version = "1.6.1" +name = "sluice" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e" +checksum = "8fa0333a60ff2e3474a6775cc611840c2a55610c831dd366503474c02f1a28f5" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", +] [[package]] name = "socket2" @@ -1665,20 +1761,29 @@ checksum = "122e570113d28d773067fab24266b66753f6ea915758651696b6e35e49f88d6e" dependencies = [ "cfg-if 1.0.0", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] -name = "spin" -version = "0.5.2" +name = "spinning_top" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "7e529d73e80d64b5f2631f9035113347c578a1c9c7774b83a2b880788459ab36" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] name = "standback" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66a8cff4fa24853fdf6b51f75c6d7f8206d7c75cab4e467bcd7f25c2b1febe0" +checksum = "a2beb4d1860a61f571530b3f855a1b538d0200f7871c63331ecd6f17b1f014f8" dependencies = [ "version_check", ] @@ -1744,6 +1849,40 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +[[package]] +name = "subtle" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" + +[[package]] +name = "surf" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7189c787d96fe18fef704950de76d590022d9d70858a4a201e1f07a0666882ea" +dependencies = [ + "async-std", + "async-trait", + "cfg-if 0.1.10", + "encoding_rs", + "futures-util", + "http-client", + "http-types", + "log", + "mime_guess", + "once_cell", + "pin-project-lite 0.1.11", + "serde", + "serde_json", + "web-sys", +] + +[[package]] +name = "sval" +version = "1.0.0-alpha.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45f6ee7c7b87caf59549e9fe45d6a69c75c8019e79e212a835c5da0e92f0ba08" + [[package]] name = "syn" version = "1.0.60" @@ -1783,20 +1922,45 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8208a331e1cb318dd5bd76951d2b8fc48ca38a69f5f4e4af1b6a9f8c6236915" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" dependencies = [ "once_cell", ] [[package]] -name = "threadpool" -version = "1.8.1" +name = "tide" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "c459573f0dd2cc734b539047f57489ea875af8ee950860ded20cf93a79a1dee0" dependencies = [ - "num_cpus", + "async-h1", + "async-session", + "async-sse", + "async-std", + "async-trait", + "femme", + "futures-util", + "http-client", + "http-types", + "kv-log-macro", + "log", + "pin-project-lite 0.2.4", + "route-recognizer", + "serde", + "serde_json", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi", ] [[package]] @@ -1811,7 +1975,7 @@ dependencies = [ "stdweb", "time-macros", "version_check", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1852,52 +2016,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" -[[package]] -name = "tokio" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6703a273949a90131b290be1fe7b039d0fc884aa1935860dfcbe056f28cd8092" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "iovec", - "lazy_static", - "libc", - "memchr", - "mio", - "mio-uds", - "pin-project-lite 0.1.11", - "signal-hook-registry", - "slab", - "winapi 0.3.9", -] - -[[package]] -name = "tokio-rustls" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" -dependencies = [ - "futures-core", - "rustls 0.18.1", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-util" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be8242891f2b6cbef26a2d7e8605133c2c554cd35b3e4948ea892d6d68436499" -dependencies = [ - "bytes 0.5.6", - "futures-core", - "futures-sink", - "log", - "pin-project-lite 0.1.11", - "tokio", -] - [[package]] name = "toml" version = "0.5.8" @@ -1909,16 +2027,28 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f47026cdc4080c07e49b37087de021820269d996f581aac150ef9e5583eefe3" +checksum = "f7d40a22fd029e33300d8d89a5cc8ffce18bb7c587662f54629e94c9de5487f3" dependencies = [ "cfg-if 1.0.0", "log", "pin-project-lite 0.2.4", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43f080ea7e4107844ef4766459426fa2d5c1ada2e47edba05dc7fa99d9629f47" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.17" @@ -1938,52 +2068,21 @@ dependencies = [ "tracing", ] -[[package]] -name = "trust-dns-proto" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53861fcb288a166aae4c508ae558ed18b53838db728d4d310aad08270a7d4c2b" -dependencies = [ - "async-trait", - "backtrace", - "enum-as-inner", - "futures", - "idna", - "lazy_static", - "log", - "rand", - "smallvec", - "thiserror", - "tokio", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.19.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6759e8efc40465547b0dfce9500d733c65f969a4cbbfbe3ccf68daaa46ef179e" -dependencies = [ - "backtrace", - "cfg-if 0.1.10", - "futures", - "ipconfig", - "lazy_static", - "log", - "lru-cache", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "trust-dns-proto", -] - [[package]] name = "typenum" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1995,19 +2094,13 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" - [[package]] name = "unicode-xid" version = "0.2.1" @@ -2015,25 +2108,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] -name = "untrusted" -version = "0.7.1" +name = "universal-hash" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "ureq" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96014ded8c85822677daee4f909d18acccca744810fd4f8ffc492c284f2324bc" +checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ - "base64 0.13.0", - "chunked_transfer", - "log", - "once_cell", - "rustls 0.19.0", - "url", - "webpki", - "webpki-roots 0.21.0", + "generic-array", + "subtle", ] [[package]] @@ -2046,20 +2127,55 @@ dependencies = [ "idna", "matches", "percent-encoding", + "serde", ] +[[package]] +name = "value-bag" +version = "1.0.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b676010e055c99033117c2343b33a40a30b91fecd6c49055ac9cd2d6c305ab1" +dependencies = [ + "ctor", + "sval", +] + +[[package]] +name = "vcpkg" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" + +[[package]] +name = "vec-arena" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eafc1b9b2dfc6f5529177b62cf806484db55b32dc7c9658a118e11bbeb33061d" + [[package]] name = "version_check" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + [[package]] name = "wasm-bindgen" version = "0.2.70" @@ -2067,6 +2183,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" dependencies = [ "cfg-if 1.0.0", + "serde", + "serde_json", "wasm-bindgen-macro", ] @@ -2085,6 +2203,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3de431a2910c86679c34283a33f66f4e4abd7e0aec27b6669060148872aadf94" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.70" @@ -2125,45 +2255,14 @@ dependencies = [ ] [[package]] -name = "webpki" -version = "0.21.4" +name = "wepoll-sys" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8e38c0608262c46d4a56202ebabdeb094cef7e560ca7a226c6bf055188aa4ea" +checksum = "0fcb14dea929042224824779fbc82d9fab8d2e6d3cbc0ac404de8edf489e77ff" dependencies = [ - "ring", - "untrusted", + "cc", ] -[[package]] -name = "webpki-roots" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f20dea7535251981a9670857150d571846545088359b28e4951d350bdaf179f" -dependencies = [ - "webpki", -] - -[[package]] -name = "webpki-roots" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82015b7e0b8bad8185994674a13a93306bea76cf5a16c5a181382fd3a5ec2376" -dependencies = [ - "webpki", -] - -[[package]] -name = "widestring" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2174,12 +2273,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2192,27 +2285,8 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -dependencies = [ - "winapi 0.3.9", -] - -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "wyz" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" +checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214" \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 6d08408..2caac3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,15 +8,15 @@ authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"] edition = "2018" [dependencies] +tide = "0.16" +async-std = { version = "1", features = ["attributes"] } +surf = "2" base64 = "0.13" -actix-web = { version = "3.3", features = ["rustls"] } +cached = "0.23" futures = "0.3" askama = "0.10" -ureq = "2" -serde = { version = "1.0", default_features = false, features = ["derive"] } -serde_json = "1.0" +serde = { version = "1", features = ["derive"] } +serde_json = "1" async-recursion = "0.3" -url = "2.2" -regex = "1.4" +regex = "1" time = "0.2" -cached = "0.23" \ No newline at end of file diff --git a/rustfmt.toml b/rustfmt.toml index 3477693..f5f51de 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,4 +1,4 @@ edition = "2018" tab_spaces = 2 hard_tabs = true -max_width = 175 \ No newline at end of file +max_width = 150 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 15b6d2e..9292f10 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,7 @@ // Import Crates -use actix_web::{ - dev::{Service, ServiceResponse}, - middleware, web, App, HttpResponse, HttpServer, -}; -use futures::future::FutureExt; +// use askama::filters::format; +use surf::utils::async_trait; +use tide::{utils::After, Middleware, Next, Request, Response}; // Reference local files mod post; @@ -14,43 +12,103 @@ mod subreddit; mod user; mod utils; +// Build middleware +struct HttpsRedirect(HttpsOnly); +struct NormalizePath; + +#[async_trait] +impl Middleware for HttpsRedirect +where + State: Clone + Send + Sync + 'static, + HttpsOnly: Into + Copy + Send + Sync + 'static, +{ + async fn handle(&self, request: Request, next: Next<'_, State>) -> tide::Result { + let secure = request.url().scheme() == "https"; + + if self.0.into() && !secure { + let mut secured = request.url().to_owned(); + secured.set_scheme("https").unwrap_or_default(); + + Ok(Response::builder(302).header("Location", secured.to_string()).build()) + } else { + Ok(next.run(request).await) + } + } +} + +#[async_trait] +impl Middleware for NormalizePath { + async fn handle(&self, request: Request, next: Next<'_, State>) -> tide::Result { + if !request.url().path().ends_with('/') { + Ok(Response::builder(301).header("Location", format!("{}/", request.url().path())).build()) + } else { + Ok(next.run(request).await) + } + } +} + // Create Services -async fn style() -> HttpResponse { - HttpResponse::Ok().content_type("text/css").body(include_str!("../static/style.css")) +async fn style(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("text/css") + .body(include_str!("../static/style.css")) + .build(), + ) } // Required for creating a PWA -async fn manifest() -> HttpResponse { - HttpResponse::Ok().content_type("application/json").body(include_str!("../static/manifest.json")) +async fn manifest(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("application/json") + .body(include_str!("../static/manifest.json")) + .build(), + ) } // Required for the manifest to be valid -async fn pwa_logo() -> HttpResponse { - HttpResponse::Ok().content_type("image/png").body(include_bytes!("../static/logo.png").as_ref()) +async fn pwa_logo(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("image/png") + .body(include_bytes!("../static/logo.png").as_ref()) + .build(), + ) } // Required for iOS App Icons -async fn iphone_logo() -> HttpResponse { - HttpResponse::Ok() - .content_type("image/png") - .body(include_bytes!("../static/touch-icon-iphone.png").as_ref()) +async fn iphone_logo(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("image/png") + .body(include_bytes!("../static/touch-icon-iphone.png").as_ref()) + .build(), + ) } -async fn robots() -> HttpResponse { - HttpResponse::Ok() - .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") - .body("User-agent: *\nAllow: /") +async fn robots(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("text/plain") + .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") + .body("User-agent: *\nAllow: /") + .build(), + ) } -async fn favicon() -> HttpResponse { - HttpResponse::Ok() - .content_type("image/x-icon") - .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") - .body(include_bytes!("../static/favicon.ico").as_ref()) +async fn favicon(_req: Request<()>) -> tide::Result { + Ok( + Response::builder(200) + .content_type("image/vnd.microsoft.icon") + .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") + .body(include_bytes!("../static/favicon.ico").as_ref()) + .build(), + ) } -#[actix_web::main] -async fn main() -> std::io::Result<()> { +#[async_std::main] +async fn main() -> tide::Result<()> { let mut address = "0.0.0.0:8080".to_string(); let mut force_https = false; @@ -62,101 +120,96 @@ async fn main() -> std::io::Result<()> { } } - // start http server + // Start HTTP server println!("Running Libreddit v{} on {}!", env!("CARGO_PKG_VERSION"), &address); - HttpServer::new(move || { - App::new() - // Redirect to HTTPS if "--redirect-https" enabled - .wrap_fn(move |req, srv| { - let secure = req.connection_info().scheme() == "https"; - let https_url = format!("https://{}{}", req.connection_info().host(), req.uri().to_string()); - srv.call(req).map(move |res: Result| { - if force_https && !secure { - Ok(ServiceResponse::new( - res.unwrap().request().to_owned(), - HttpResponse::Found().header("Location", https_url).finish(), - )) - } else { - res - } - }) - }) - // Append trailing slash and remove double slashes - .wrap(middleware::NormalizePath::default()) - // Apply default headers for security - .wrap( - middleware::DefaultHeaders::new() - .header("Referrer-Policy", "no-referrer") - .header("X-Content-Type-Options", "nosniff") - .header("X-Frame-Options", "DENY") - .header( - "Content-Security-Policy", - "default-src 'none'; manifest-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'none'; img-src 'self' data:; form-action 'self'; frame-ancestors 'none';", - ), - ) - // Default service in case no routes match - .default_service(web::get().to(|| utils::error("Nothing here".to_string()))) - // Read static files - .route("/style.css/", web::get().to(style)) - .route("/favicon.ico/", web::get().to(favicon)) - .route("/robots.txt/", web::get().to(robots)) - .route("/manifest.json/", web::get().to(manifest)) - .route("/logo.png/", web::get().to(pwa_logo)) - .route("/touch-icon-iphone.png/", web::get().to(iphone_logo)) - // Proxy media through Libreddit - .route("/proxy/{url:.*}/", web::get().to(proxy::handler)) - // Browse user profile - .service( - web::scope("/{scope:user|u}").service( - web::scope("/{username}").route("/", web::get().to(user::profile)).service( - web::scope("/comments/{id}/{title}") - .route("/", web::get().to(post::item)) - .route("/{comment_id}/", web::get().to(post::item)), - ), - ), - ) - // Configure settings - .service(web::resource("/settings/").route(web::get().to(settings::get)).route(web::post().to(settings::set))) - // Subreddit services - .service( - web::scope("/r/{sub}") - // See posts and info about subreddit - .route("/", web::get().to(subreddit::page)) - .route("/{sort:hot|new|top|rising|controversial}/", web::get().to(subreddit::page)) - // Handle subscribe/unsubscribe - .route("/{action:subscribe|unsubscribe}/", web::post().to(subreddit::subscriptions)) - // View post on subreddit - .service( - web::scope("/comments/{id}/{title}") - .route("/", web::get().to(post::item)) - .route("/{comment_id}/", web::get().to(post::item)), - ) - // Search inside subreddit - .route("/search/", web::get().to(search::find)) - // View wiki of subreddit - .service( - web::scope("/{scope:wiki|w}") - .route("/", web::get().to(subreddit::wiki)) - .route("/{page}/", web::get().to(subreddit::wiki)), - ), - ) - // Front page - .route("/", web::get().to(subreddit::page)) - .route("/{sort:best|hot|new|top|rising|controversial}/", web::get().to(subreddit::page)) - // View Reddit wiki - .service( - web::scope("/wiki") - .route("/", web::get().to(subreddit::wiki)) - .route("/{page}/", web::get().to(subreddit::wiki)), - ) - // Search all of Reddit - .route("/search/", web::get().to(search::find)) - // Short link for post - .route("/{id:.{5,6}}/", web::get().to(post::item)) - }) - .bind(&address) - .unwrap_or_else(|e| panic!("Cannot bind to the address {}: {}", address, e)) - .run() - .await + let mut app = tide::new(); + + // Redirect to HTTPS if "--redirect-https" enabled + app.with(HttpsRedirect(force_https)); + + // Append trailing slash and remove double slashes + app.with(NormalizePath); + + // Apply default headers for security + app.with(After(|mut res: Response| async move { + res.insert_header("Referrer-Policy", "no-referrer"); + res.insert_header("X-Content-Type-Options", "nosniff"); + res.insert_header("X-Frame-Options", "DENY"); + res.insert_header( + "Content-Security-Policy", + "default-src 'none'; manifest-src 'self'; media-src 'self'; style-src 'self' 'unsafe-inline'; base-uri 'none'; img-src 'self' data:; form-action 'self'; frame-ancestors 'none';", + ); + Ok(res) + })); + + // Read static files + app.at("/style.css/").get(style); + app.at("/favicon.ico/").get(favicon); + app.at("/robots.txt/").get(robots); + app.at("/manifest.json/").get(manifest); + app.at("/logo.png/").get(pwa_logo); + app.at("/touch-icon-iphone.png/").get(iphone_logo); + + // Proxy media through Libreddit + app.at("/proxy/*url/").get(proxy::handler); + + // Browse user profile + app.at("/u/:name/").get(user::profile); + app.at("/u/:name/comments/:id/:title/").get(post::item); + app.at("/u/:name/comments/:id/:title/:comment/").get(post::item); + + app.at("/user/:name/").get(user::profile); + app.at("/user/:name/comments/:id/:title/").get(post::item); + app.at("/user/:name/comments/:id/:title/:comment/").get(post::item); + + // Configure settings + app.at("/settings/").get(settings::get).post(settings::set); + + // Subreddit services + // See posts and info about subreddit + app.at("/r/:sub/").get(subreddit::page); + // Handle subscribe/unsubscribe + app.at("/r/:sub/subscribe/").post(subreddit::subscriptions); + app.at("/r/:sub/unsubscribe/").post(subreddit::subscriptions); + // View post on subreddit + app.at("/r/:sub/comments/:id/:title/").get(post::item); + app.at("/r/:sub/comments/:id/:title/:comment_id/").get(post::item); + // Search inside subreddit + app.at("/r/:sub/search/").get(search::find); + // View wiki of subreddit + app.at("/r/:sub/w/").get(subreddit::wiki); + app.at("/r/:sub/w/:page/").get(subreddit::wiki); + app.at("/r/:sub/wiki/").get(subreddit::wiki); + app.at("/r/:sub/wiki/:page/").get(subreddit::wiki); + // Sort subreddit posts + app.at("/r/:sub/:sort/").get(subreddit::page); + + // Front page + app.at("/").get(subreddit::page); + + // View Reddit wiki + app.at("/w/").get(subreddit::wiki); + app.at("/w/:page/").get(subreddit::wiki); + app.at("/wiki/").get(subreddit::wiki); + app.at("/wiki/:page/").get(subreddit::wiki); + + // Search all of Reddit + app.at("/search/").get(search::find); + + // Short link for post + // .route("/{sort:best|hot|new|top|rising|controversial}/", web::get().to(subreddit::page)) + // .route("/{id:.{5,6}}/", web::get().to(post::item)) + app.at("/:id/").get(|req: Request<()>| async { + match req.param("id").unwrap_or_default() { + "best" | "hot" | "new" | "top" | "rising" | "controversial" => subreddit::page(req).await, + _ => post::item(req).await, + } + }); + + // Default service in case no routes match + app.at("*").get(|_| utils::error("Nothing here".to_string())); + + app.listen("127.0.0.1:8080").await?; + Ok(()) } diff --git a/src/post.rs b/src/post.rs index 1374087..31d3be7 100644 --- a/src/post.rs +++ b/src/post.rs @@ -1,6 +1,6 @@ // CRATES use crate::utils::*; -use actix_web::{HttpRequest, HttpResponse}; +use tide::Request; use async_recursion::async_recursion; @@ -16,9 +16,9 @@ struct PostTemplate { prefs: Preferences, } -pub async fn item(req: HttpRequest) -> HttpResponse { +pub async fn item(req: Request<()>) -> tide::Result { // Build Reddit API path - let mut path: String = format!("{}.json?{}&raw_json=1", req.path(), req.query_string()); + let mut path: String = format!("{}.json?{}&raw_json=1", req.url().path(), req.url().query().unwrap_or_default()); // Set sort to sort query parameter let mut sort: String = param(&path, "sort"); @@ -29,12 +29,17 @@ pub async fn item(req: HttpRequest) -> HttpResponse { // If there's no sort query but there's a default sort, set sort to default_sort if sort.is_empty() && !default_sort.is_empty() { sort = default_sort; - path = format!("{}.json?{}&sort={}&raw_json=1", req.path(), req.query_string(), sort); + path = format!( + "{}.json?{}&sort={}&raw_json=1", + req.url().path(), + req.url().query().unwrap_or_default(), + sort + ); } // Log the post ID being fetched in debug mode #[cfg(debug_assertions)] - dbg!(req.match_info().get("id").unwrap_or("")); + dbg!(req.param("id").unwrap_or("")); // Send a request to the url, receive JSON in response match request(path).await { @@ -45,15 +50,12 @@ pub async fn item(req: HttpRequest) -> HttpResponse { let comments = parse_comments(&res[1]).await; // Use the Post and Comment structs to generate a website to show users - let s = PostTemplate { + template(PostTemplate { comments, post, sort, prefs: prefs(req), - } - .render() - .unwrap(); - HttpResponse::Ok().content_type("text/html").body(s) + }) } // If the Reddit API returns an error, exit and send error page to user Err(msg) => error(msg).await, diff --git a/src/proxy.rs b/src/proxy.rs index fcd571d..31300de 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -1,9 +1,8 @@ -use actix_web::{client::Client, error, web, Error, HttpResponse, Result}; -use url::Url; - use base64::decode; +use surf::{Body, Url}; +use tide::{Request, Response}; -pub async fn handler(web::Path(b64): web::Path) -> Result { +pub async fn handler(req: Request<()>) -> tide::Result { let domains = vec![ // THUMBNAILS "a.thumbs.redditmedia.com", @@ -21,27 +20,31 @@ pub async fn handler(web::Path(b64): web::Path) -> Result "v.redd.it", ]; - let decoded = decode(b64).map(|bytes| String::from_utf8(bytes).unwrap_or_default()); + let decoded = decode(req.param("url").unwrap_or_default()).map(|bytes| String::from_utf8(bytes).unwrap_or_default()); match decoded { Ok(media) => match Url::parse(media.as_str()) { Ok(url) => { - let domain = url.domain().unwrap_or_default(); + if domains.contains(&url.domain().unwrap_or_default()) { + let http = surf::get(url).await.unwrap(); - if domains.contains(&domain) { - Client::default().get(media.replace("&", "&")).send().await.map_err(Error::from).map(|res| { - HttpResponse::build(res.status()) + let content_length = http.header("Content-Length").map(|v| v.to_string()).unwrap_or_default(); + let content_type = http.content_type().map(|m| m.to_string()).unwrap_or_default(); + + Ok( + Response::builder(http.status()) + .body(Body::from_reader(http, None)) .header("Cache-Control", "public, max-age=1209600, s-maxage=86400") - .header("Content-Length", res.headers().get("Content-Length").unwrap().to_owned()) - .header("Content-Type", res.headers().get("Content-Type").unwrap().to_owned()) - .streaming(res) - }) + .header("Content-Length", content_length) + .header("Content-Type", content_type) + .build(), + ) } else { - Err(error::ErrorForbidden("Resource must be from Reddit")) + Err(tide::Error::from_str(403, "Resource must be from Reddit")) } } - _ => Err(error::ErrorBadRequest("Can't parse base64 into URL")), + Err(_) => Err(tide::Error::from_str(400, "Can't parse base64 into URL")), }, - _ => Err(error::ErrorBadRequest("Can't decode base64")), + Err(_) => Err(tide::Error::from_str(400, "Can't decode base64")), } } diff --git a/src/search.rs b/src/search.rs index a789d49..247a1ac 100644 --- a/src/search.rs +++ b/src/search.rs @@ -1,7 +1,7 @@ // CRATES -use crate::utils::{cookie, error, fetch_posts, param, prefs, request, val, Post, Preferences}; -use actix_web::{HttpRequest, HttpResponse}; +use crate::utils::{cookie, error, fetch_posts, param, prefs, request, template, val, Post, Preferences}; use askama::Template; +use tide::Request; // STRUCTS struct SearchParams { @@ -32,10 +32,10 @@ struct SearchTemplate { } // SERVICES -pub async fn find(req: HttpRequest) -> HttpResponse { +pub async fn find(req: Request<()>) -> tide::Result { let nsfw_results = if cookie(&req, "show_nsfw") == "on" { "&include_over_18=on" } else { "" }; - let path = format!("{}.json?{}{}", req.path(), req.query_string(), nsfw_results); - let sub = req.match_info().get("sub").unwrap_or("").to_string(); + let path = format!("{}.json?{}{}", req.url().path(), req.url().query().unwrap_or_default(), nsfw_results); + let sub = req.param("sub").unwrap_or("").to_string(); let sort = if param(&path, "sort").is_empty() { "relevance".to_string() @@ -50,24 +50,20 @@ pub async fn find(req: HttpRequest) -> HttpResponse { }; match fetch_posts(&path, String::new()).await { - Ok((posts, after)) => HttpResponse::Ok().content_type("text/html").body( - SearchTemplate { - posts, - subreddits, - sub, - params: SearchParams { - q: param(&path, "q"), - sort, - t: param(&path, "t"), - before: param(&path, "after"), - after, - restrict_sr: param(&path, "restrict_sr"), - }, - prefs: prefs(req), - } - .render() - .unwrap(), - ), + Ok((posts, after)) => template(SearchTemplate { + posts, + subreddits, + sub, + params: SearchParams { + q: param(&path, "q"), + sort, + t: param(&path, "t"), + before: param(&path, "after"), + after, + restrict_sr: param(&path, "restrict_sr"), + }, + prefs: prefs(req), + }), Err(msg) => error(msg).await, } } diff --git a/src/settings.rs b/src/settings.rs index 6d7560f..0484973 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,7 +1,7 @@ // CRATES -use crate::utils::{prefs, Preferences}; -use actix_web::{cookie::Cookie, web::Form, HttpRequest, HttpResponse}; +use crate::utils::{prefs, template, Preferences}; use askama::Template; +use tide::{http::Cookie, Request, Response}; use time::{Duration, OffsetDateTime}; // STRUCTS @@ -11,7 +11,7 @@ struct SettingsTemplate { prefs: Preferences, } -#[derive(serde::Deserialize)] +#[derive(serde::Deserialize, Default)] pub struct SettingsForm { theme: Option, front_page: Option, @@ -24,33 +24,35 @@ pub struct SettingsForm { // FUNCTIONS // Retrieve cookies from request "Cookie" header -pub async fn get(req: HttpRequest) -> HttpResponse { - let s = SettingsTemplate { prefs: prefs(req) }.render().unwrap(); - HttpResponse::Ok().content_type("text/html").body(s) +pub async fn get(req: Request<()>) -> tide::Result { + template(SettingsTemplate { prefs: prefs(req) }) } // Set cookies using response "Set-Cookie" header -pub async fn set(_req: HttpRequest, form: Form) -> HttpResponse { - let mut res = HttpResponse::Found(); +pub async fn set(mut req: Request<()>) -> tide::Result { + let form: SettingsForm = req.body_form().await.unwrap_or_default(); + + let mut res = Response::builder(302) + .content_type("text/html") + .header("Location", "/settings") + .body(r#"Redirecting to settings..."#) + .build(); let names = vec!["theme", "front_page", "layout", "wide", "comment_sort", "show_nsfw"]; - let values = vec![&form.theme, &form.front_page, &form.layout, &form.wide, &form.comment_sort, &form.show_nsfw]; + let values = vec![form.theme, form.front_page, form.layout, form.wide, form.comment_sort, form.show_nsfw]; for (i, name) in names.iter().enumerate() { - match values[i] { - Some(value) => res.cookie( - Cookie::build(name.to_owned(), value) + match values.get(i) { + Some(value) => res.insert_cookie( + Cookie::build(name.to_owned(), value.to_owned().unwrap_or_default()) .path("/") .http_only(true) .expires(OffsetDateTime::now_utc() + Duration::weeks(52)) .finish(), ), - None => res.del_cookie(&Cookie::named(name.to_owned())), + None => res.remove_cookie(Cookie::named(name.to_owned())), }; } - res - .content_type("text/html") - .set_header("Location", "/settings") - .body(r#"Redirecting to settings..."#) + Ok(res) } diff --git a/src/subreddit.rs b/src/subreddit.rs index 8dd1096..7c07c0a 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -1,7 +1,7 @@ // CRATES use crate::utils::*; -use actix_web::{cookie::Cookie, HttpRequest, HttpResponse, Result}; use askama::Template; +use tide::{http::Cookie, Request, Response}; use time::{Duration, OffsetDateTime}; // STRUCTS @@ -25,14 +25,14 @@ struct WikiTemplate { } // SERVICES -pub async fn page(req: HttpRequest) -> HttpResponse { +pub async fn page(req: Request<()>) -> tide::Result { + // Build Reddit API path let subscribed = cookie(&req, "subscriptions"); let front_page = cookie(&req, "front_page"); - let sort = req.match_info().get("sort").unwrap_or("hot").to_string(); + let sort = req.param("sort").unwrap_or_else(|_| req.param("id").unwrap_or("hot")).to_string(); let sub = req - .match_info() - .get("sub") + .param("sub") .map(String::from) .unwrap_or(if front_page == "default" || front_page.is_empty() { if subscribed.is_empty() { @@ -44,7 +44,7 @@ pub async fn page(req: HttpRequest) -> HttpResponse { front_page.to_owned() }); - let path = format!("/r/{}/{}.json?{}", sub, sort, req.query_string()); + let path = format!("/r/{}/{}.json?{}&raw_json=1", sub, sort, req.url().query().unwrap_or_default()); match fetch_posts(&path, String::new()).await { Ok((posts, after)) => { @@ -54,7 +54,7 @@ pub async fn page(req: HttpRequest) -> HttpResponse { subreddit(&sub).await.unwrap_or_default() } else if sub == subscribed { // Subscription feed - if req.path().starts_with("/r/") { + if req.url().path().starts_with("/r/") { subreddit(&sub).await.unwrap_or_default() } else { Subreddit::default() @@ -69,42 +69,55 @@ pub async fn page(req: HttpRequest) -> HttpResponse { Subreddit::default() }; - let s = SubredditTemplate { + template(SubredditTemplate { sub, posts, sort: (sort, param(&path, "t")), ends: (param(&path, "after"), after), prefs: prefs(req), - } - .render() - .unwrap(); - HttpResponse::Ok().content_type("text/html").body(s) + }) } Err(msg) => error(msg).await, } } // Sub or unsub by setting subscription cookie using response "Set-Cookie" header -pub async fn subscriptions(req: HttpRequest) -> HttpResponse { - let mut res = HttpResponse::Found(); +pub async fn subscriptions(req: Request<()>) -> tide::Result { + let sub = req.param("sub").unwrap_or_default().to_string(); + let query = req.url().query().unwrap_or_default().to_string(); + let action: Vec = req.url().path().split('/').map(String::from).collect(); - let sub = req.match_info().get("sub").unwrap_or_default().to_string(); - let action = req.match_info().get("action").unwrap_or_default().to_string(); - let mut sub_list = prefs(req.to_owned()).subs; + let mut sub_list = prefs(req).subs; // Modify sub list based on action - if action == "subscribe" && !sub_list.contains(&sub) { + if action.contains(&"subscribe".to_string()) && !sub_list.contains(&sub) { sub_list.push(sub.to_owned()); - sub_list.sort_by_key(|a| a.to_lowercase()); - } else if action == "unsubscribe" { + sub_list.sort_by_key(|a| a.to_lowercase()) + } else if action.contains(&"unsubscribe".to_string()) { sub_list.retain(|s| s != &sub); } + // Redirect back to subreddit + // check for redirect parameter if unsubscribing from outside sidebar + let redirect_path = param(format!("/?{}", query).as_str(), "redirect"); + let path = if !redirect_path.is_empty() { + format!("/{}/", redirect_path) + } else { + format!("/r/{}", sub) + }; + + let mut res = Response::builder(302) + .content_type("text/html") + .header("Location", path.to_owned()) + .body(format!("Redirecting to {0}...", path)) + .build(); + // Delete cookie if empty, else set if sub_list.is_empty() { - res.del_cookie(&Cookie::build("subscriptions", "").path("/").finish()); + // res.del_cookie(&Cookie::build("subscriptions", "").path("/").finish()); + res.remove_cookie(Cookie::build("subscriptions", "").path("/").finish()); } else { - res.cookie( + res.insert_cookie( Cookie::build("subscriptions", sub_list.join("+")) .path("/") .http_only(true) @@ -113,38 +126,21 @@ pub async fn subscriptions(req: HttpRequest) -> HttpResponse { ); } - // Redirect back to subreddit - // check for redirect parameter if unsubscribing from outside sidebar - let redirect_path = param(&req.uri().to_string(), "redirect"); - let path = if !redirect_path.is_empty() && redirect_path.starts_with('/') { - redirect_path - } else { - format!("/r/{}", sub) - }; - - res - .content_type("text/html") - .set_header("Location", path.to_owned()) - .body(format!("Redirecting to {0}...", path)) + Ok(res) } -pub async fn wiki(req: HttpRequest) -> HttpResponse { - let sub = req.match_info().get("sub").unwrap_or("reddit.com").to_string(); - let page = req.match_info().get("page").unwrap_or("index").to_string(); +pub async fn wiki(req: Request<()>) -> tide::Result { + let sub = req.param("sub").unwrap_or("reddit.com").to_string(); + let page = req.param("page").unwrap_or("index").to_string(); let path: String = format!("/r/{}/wiki/{}.json?raw_json=1", sub, page); match request(path).await { - Ok(res) => { - let s = WikiTemplate { - sub, - wiki: rewrite_url(res["data"]["content_html"].as_str().unwrap_or_default()), - page, - prefs: prefs(req), - } - .render() - .unwrap(); - HttpResponse::Ok().content_type("text/html").body(s) - } + Ok(res) => template(WikiTemplate { + sub, + wiki: rewrite_url(res["data"]["content_html"].as_str().unwrap_or_default()), + page, + prefs: prefs(req), + }), Err(msg) => error(msg).await, } } @@ -163,8 +159,14 @@ async fn subreddit(sub: &str) -> Result { let active: i64 = res["data"]["accounts_active"].as_u64().unwrap_or_default() as i64; // Fetch subreddit icon either from the community_icon or icon_img value - let community_icon: &str = res["data"]["community_icon"].as_str().map_or("", |s| s.split('?').collect::>()[0]); - let icon = if community_icon.is_empty() { val(&res, "icon_img") } else { community_icon.to_string() }; + let community_icon: &str = res["data"]["community_icon"] + .as_str() + .map_or("", |s| s.split('?').collect::>()[0]); + let icon = if community_icon.is_empty() { + val(&res, "icon_img") + } else { + community_icon.to_string() + }; let sub = Subreddit { name: val(&res, "display_name"), diff --git a/src/user.rs b/src/user.rs index 96e3023..0e32013 100644 --- a/src/user.rs +++ b/src/user.rs @@ -1,7 +1,7 @@ // CRATES -use crate::utils::{error, fetch_posts, format_url, param, prefs, request, Post, Preferences, User}; -use actix_web::{HttpRequest, HttpResponse, Result}; +use crate::utils::*; use askama::Template; +use tide::Request; use time::OffsetDateTime; // STRUCTS @@ -16,13 +16,13 @@ struct UserTemplate { } // FUNCTIONS -pub async fn profile(req: HttpRequest) -> HttpResponse { +pub async fn profile(req: Request<()>) -> tide::Result { // Build the Reddit JSON API path - let path = format!("{}.json?{}&raw_json=1", req.path(), req.query_string()); + let path = format!("{}.json?{}&raw_json=1", req.url().path(), req.url().query().unwrap_or_default()); // Retrieve other variables from Libreddit request let sort = param(&path, "sort"); - let username = req.match_info().get("username").unwrap_or("").to_string(); + let username = req.param("name").unwrap_or("").to_string(); // Request user posts/comments from Reddit let posts = fetch_posts(&path, "Comment".to_string()).await; @@ -32,16 +32,13 @@ pub async fn profile(req: HttpRequest) -> HttpResponse { // If you can get user posts, also request user data let user = user(&username).await.unwrap_or_default(); - let s = UserTemplate { + template(UserTemplate { user, posts, sort: (sort, param(&path, "t")), ends: (param(&path, "after"), after), prefs: prefs(req), - } - .render() - .unwrap(); - HttpResponse::Ok().content_type("text/html").body(s) + }) } // If there is an error show error page Err(msg) => error(msg).await, @@ -51,7 +48,7 @@ pub async fn profile(req: HttpRequest) -> HttpResponse { // USER async fn user(name: &str) -> Result { // Build the Reddit JSON API path - let path: String = format!("/user/{}/about.json", name); + let path: String = format!("/user/{}/about.json?raw_json=1", name); // Send a request to the url match request(path).await { diff --git a/src/utils.rs b/src/utils.rs index 8a605a9..d4d6c8c 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,15 +1,14 @@ // // CRATES // -use actix_web::{cookie::Cookie, HttpRequest, HttpResponse, Result}; use askama::Template; use base64::encode; use cached::proc_macro::cached; use regex::Regex; use serde_json::{from_str, Value}; use std::collections::HashMap; +use tide::{http::url::Url, http::Cookie, Request, Response}; use time::{Duration, OffsetDateTime}; -use url::Url; // // STRUCTS @@ -147,7 +146,7 @@ pub struct Preferences { // // Build preferences from cookies -pub fn prefs(req: HttpRequest) -> Preferences { +pub fn prefs(req: Request<()>) -> Preferences { Preferences { theme: cookie(&req, "theme"), front_page: cookie(&req, "front_page"), @@ -155,21 +154,32 @@ pub fn prefs(req: HttpRequest) -> Preferences { wide: cookie(&req, "wide"), show_nsfw: cookie(&req, "show_nsfw"), comment_sort: cookie(&req, "comment_sort"), - subs: cookie(&req, "subscriptions").split('+').map(String::from).filter(|s| !s.is_empty()).collect(), + subs: cookie(&req, "subscriptions") + .split('+') + .map(String::from) + .filter(|s| !s.is_empty()) + .collect(), } } // Grab a query param from a url pub fn param(path: &str, value: &str) -> String { match Url::parse(format!("https://libredd.it/{}", path).as_str()) { - Ok(url) => url.query_pairs().into_owned().collect::>().get(value).unwrap_or(&String::new()).to_owned(), + Ok(url) => url + .query_pairs() + .into_owned() + .collect::>() + .get(value) + .unwrap_or(&String::new()) + .to_owned(), _ => String::new(), } } // Parse Cookie value from request -pub fn cookie(req: &HttpRequest, name: &str) -> String { - actix_web::HttpMessage::cookie(req, name).unwrap_or_else(|| Cookie::new(name, "")).value().to_string() +pub fn cookie(req: &Request<()>, name: &str) -> String { + let cookie = req.cookie(name).unwrap_or_else(|| Cookie::named(name)); + cookie.value().to_string() } // Direct urls to proxy if proxy is enabled @@ -177,7 +187,7 @@ pub fn format_url(url: &str) -> String { if url.is_empty() || url == "self" || url == "default" || url == "nsfw" || url == "spoiler" { String::new() } else { - format!("/proxy/{}", encode(url).as_str()) + format!("/proxy/{}/", encode(url).as_str()) } } @@ -420,102 +430,57 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec HttpResponse { +pub fn template(f: impl Template) -> tide::Result { + Ok( + Response::builder(200) + .content_type("text/html") + .body(f.render().unwrap_or_default()) + .build(), + ) +} + +pub async fn error(msg: String) -> tide::Result { let body = ErrorTemplate { msg, prefs: Preferences::default(), } .render() .unwrap_or_default(); - HttpResponse::NotFound().content_type("text/html").body(body) + + Ok(Response::builder(404).content_type("text/html").body(body).build()) } // Make a request to a Reddit API and parse the JSON response #[cached(size = 100, time = 30, result = true)] pub async fn request(path: String) -> Result { let url = format!("https://www.reddit.com{}", path); + // Build reddit-compliant user agent for Libreddit let user_agent = format!("web:libreddit:{}", env!("CARGO_PKG_VERSION")); - // Send request using awc - // async fn send(url: &str) -> Result { - // let client = actix_web::client::Client::default(); - // let response = client.get(url).header("User-Agent", format!("web:libreddit:{}", env!("CARGO_PKG_VERSION"))).send().await; + // Send request using surf + let req = surf::get(&url).header("User-Agent", user_agent.as_str()); + let client = surf::client().with(surf::middleware::Redirect::new(5)); - // match response { - // Ok(mut payload) => { - // // Get first number of response HTTP status code - // match payload.status().to_string().chars().next() { - // // If success - // Some('2') => Ok(String::from_utf8(payload.body().limit(20_000_000).await.unwrap_or_default().to_vec()).unwrap_or_default()), - // // If redirection - // Some('3') => match payload.headers().get("location") { - // Some(location) => Err((true, location.to_str().unwrap_or_default().to_string())), - // None => Err((false, "Page not found".to_string())), - // }, - // // Otherwise - // _ => Err((false, "Page not found".to_string())), - // } - // } - // Err(e) => { dbg!(e); Err((false, "Couldn't send request to Reddit, this instance may be being rate-limited. Try another.".to_string())) }, - // } - // } + let res = client.send(req).await; - // // Print error if debugging then return error based on error message - // fn err(url: String, msg: String) -> Result { - // // #[cfg(debug_assertions)] - // dbg!(format!("{} - {}", url, msg)); - // Err(msg) - // }; + let body = res.unwrap().take_body().into_string().await; - // // Parse JSON from body. If parsing fails, return error - // fn json(url: String, body: String) -> Result { - // match from_str(body.as_str()) { - // Ok(json) => Ok(json), - // Err(_) => err(url, "Failed to parse page JSON data".to_string()), - // } - // } - - // // Make request to Reddit using send function - // match send(&url).await { - // // If success, parse and return body - // Ok(body) => json(url, body), - // // Follow any redirects - // Err((true, location)) => match send(location.as_str()).await { - // // If success, parse and return body - // Ok(body) => json(url, body), - // // Follow any redirects again - // Err((true, location)) => err(url, location), - // // Return errors if request fails - // Err((_, msg)) => err(url, msg), - // }, - // // Return errors if request fails - // Err((_, msg)) => err(url, msg), - // } - - // Send request using ureq - match ureq::get(&url).set("User-Agent", user_agent.as_str()).call() { + match body { // If response is success Ok(response) => { // Parse the response from Reddit as JSON - let json_string = &response.into_string().unwrap_or_default(); - match from_str(json_string) { + match from_str(&response) { Ok(json) => Ok(json), Err(e) => { - println!("{} - Failed to parse page JSON data: {} - {}", url, e, json_string); + println!("{} - Failed to parse page JSON data: {}", url, e); Err("Failed to parse page JSON data".to_string()) } } } - // If response is error - Err(ureq::Error::Status(_, _)) => { - #[cfg(debug_assertions)] - dbg!(format!("{} - Page not found", url)); - Err("Page not found".to_string()) - } // If failed to send request Err(e) => { println!("{} - Couldn't send request to Reddit: {}", url, e); - Err("Couldn't send request to Reddit, this instance may be being rate-limited. Try another.".to_string()) + Err("Couldn't send request to Reddit".to_string()) } } } diff --git a/static/manifest.json b/static/manifest.json index c017876..1e9c567 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -1,15 +1,15 @@ { - "name": "Libreddit", - "short_name": "Libreddit", - "display": "standalone", - "background_color": "#1F1F1F", - "description": "An alternative private front-end to Reddit", - "theme_color": "#1F1F1F", - "icons": [ - { - "src": "./logo.png", - "sizes": "512x512", - "type": "image/png" - } - ] - } \ No newline at end of file + "name": "Libreddit", + "short_name": "Libreddit", + "display": "standalone", + "background_color": "#1F1F1F", + "description": "An alternative private front-end to Reddit", + "theme_color": "#1F1F1F", + "icons": [ + { + "src": "./logo.png", + "sizes": "512x512", + "type": "image/png" + } + ] +} \ No newline at end of file diff --git a/templates/base.html b/templates/base.html index 6caad37..d523df6 100644 --- a/templates/base.html +++ b/templates/base.html @@ -15,11 +15,11 @@ - + - - - + + + {% endblock %} -
+

Appearance

@@ -57,7 +57,7 @@ {% for sub in prefs.subs %}
  • {{ sub }} - +
  • diff --git a/templates/subreddit.html b/templates/subreddit.html index c2a8ce6..d6c5667 100644 --- a/templates/subreddit.html +++ b/templates/subreddit.html @@ -80,11 +80,11 @@
    {% if prefs.subs.contains(sub.name) %} -
    +
    {% else %} -
    +
    {% endif %}