diff --git a/Cargo.lock b/Cargo.lock index 3ddc89b..d041577 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,7 +31,7 @@ dependencies = [ "futures-util", "http", "log", - "rustls 0.18.1", + "rustls", "tokio-rustls", "trust-dns-proto", "trust-dns-resolver", @@ -193,10 +193,10 @@ dependencies = [ "actix-service", "actix-utils", "futures-util", - "rustls 0.18.1", + "rustls", "tokio-rustls", "webpki", - "webpki-roots 0.20.0", + "webpki-roots", ] [[package]] @@ -249,7 +249,7 @@ dependencies = [ "mime", "pin-project 1.0.4", "regex", - "rustls 0.18.1", + "rustls", "serde", "serde_json", "serde_urlencoded", @@ -393,7 +393,7 @@ dependencies = [ "mime", "percent-encoding", "rand", - "rustls 0.18.1", + "rustls", "serde", "serde_json", "serde_urlencoded", @@ -529,12 +529,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chunked_transfer" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7477065d45a8fe57167bf3cf8bcd3729b54cfcb81cca49bda2d038ea89ae82ca" - [[package]] name = "const_fn" version = "0.4.5" @@ -992,7 +986,6 @@ dependencies = [ "serde", "serde_json", "time", - "ureq", "url", ] @@ -1420,19 +1413,6 @@ dependencies = [ "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" @@ -1769,7 +1749,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e12831b255bcfa39dc0436b01e19fea231a37db570686c06ee72c423479f889a" dependencies = [ "futures-core", - "rustls 0.18.1", + "rustls", "tokio", "webpki", ] @@ -1910,22 +1890,6 @@ version = "0.7.1" 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" -dependencies = [ - "base64 0.13.0", - "chunked_transfer", - "log", - "once_cell", - "rustls 0.19.0", - "url", - "webpki", - "webpki-roots 0.21.0", -] - [[package]] name = "url" version = "2.2.0" @@ -2033,15 +1997,6 @@ 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" diff --git a/Cargo.toml b/Cargo.toml index cc75352..e35d9e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,6 @@ edition = "2018" [dependencies] base64 = "0.13.0" actix-web = { version = "3.3.2", features = ["rustls"] } -ureq = "2.0.1" askama = "0.10.5" serde = { version = "1.0.118", default_features = false, features = ["derive"] } serde_json = "1.0" diff --git a/src/main.rs b/src/main.rs index 474ab9f..d9d6a4a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,7 +50,7 @@ async fn main() -> std::io::Result<()> { // Append trailing slash and remove double slashes .wrap(middleware::NormalizePath::default()) // Default service in case no routes match - .default_service(web::get().to(|| utils::error("Nothing here"))) + .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)) @@ -95,10 +95,10 @@ async fn main() -> std::io::Result<()> { .route("/{page}/", web::get().to(subreddit::wiki)), ) // Search all of Reddit - .route("/search/", web::get().to(search::find)), + .route("/search/", web::get().to(search::find)) + // Short link for post + .route("/{id:.{5,6}}/", web::get().to(post::item)), ) - // 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)) diff --git a/src/subreddit.rs b/src/subreddit.rs index e9403b7..7e68f46 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -84,7 +84,7 @@ pub async fn wiki(req: HttpRequest) -> HttpResponse { } // SUBREDDIT -async fn subreddit(sub: &str) -> Result { +async fn subreddit(sub: &str) -> Result { // Build the Reddit JSON API url let path: String = format!("/r/{}/about.json?raw_json=1", sub); diff --git a/src/user.rs b/src/user.rs index d12c54c..9a7502f 100644 --- a/src/user.rs +++ b/src/user.rs @@ -47,7 +47,7 @@ pub async fn profile(req: HttpRequest) -> HttpResponse { } // USER -async fn user(name: &str) -> Result { +async fn user(name: &str) -> Result { // Build the Reddit JSON API path let path: String = format!("/user/{}/about.json", name); diff --git a/src/utils.rs b/src/utils.rs index ffcee5b..d6acf27 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -101,7 +101,7 @@ pub struct Params { #[derive(Template)] #[template(path = "error.html", escape = "none")] pub struct ErrorTemplate { - pub message: String, + pub msg: String, pub prefs: Preferences, } @@ -169,7 +169,7 @@ pub fn format_num(num: i64) -> String { } } -pub async fn media(data: &serde_json::Value) -> (String, String) { +pub async fn media(data: &Value) -> (String, String) { let post_type: &str; let url = if !data["preview"]["reddit_video_preview"]["fallback_url"].is_null() { post_type = "video"; @@ -249,12 +249,12 @@ pub fn time(unix_time: i64) -> String { // // val() function used to parse JSON from Reddit APIs -pub fn val(j: &serde_json::Value, k: &str) -> String { +pub fn val(j: &Value, k: &str) -> String { String::from(j["data"][k].as_str().unwrap_or_default()) } // Fetch posts of a user or subreddit and return a vector of posts and the "after" value -pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec, String), &'static str> { +pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec, String), String> { let res; let post_list; @@ -271,7 +271,7 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec post_list = list, - None => return Err("No posts found"), + None => return Err("No posts found".to_string()), } let mut posts: Vec = Vec::new(); @@ -336,9 +336,9 @@ pub async fn fetch_posts(path: &str, fallback_title: String) -> Result<(Vec HttpResponse { +pub async fn error(msg: String) -> HttpResponse { let body = ErrorTemplate { - message: msg.to_string(), + msg, prefs: Preferences::default(), } .render() @@ -347,34 +347,50 @@ pub async fn error(msg: &str) -> HttpResponse { } // Make a request to a Reddit API and parse the JSON response -pub async fn request(path: &str) -> Result { +pub async fn request(path: &str) -> Result { let url = format!("https://www.reddit.com{}", path); - // Send request using ureq - match ureq::get(&url).call() { - // If response is success - Ok(response) => { - // Parse the response from Reddit as JSON - match from_str(&response.into_string().unwrap()) { - Ok(json) => Ok(json), - Err(_) => { - #[cfg(debug_assertions)] - dbg!(format!("{} - Failed to parse page JSON data", url)); - Err("Failed to parse page JSON data") + // Send request using awc + async fn send(url: &str) -> Result { + let client = actix_web::client::Client::default(); + let response = client.get(url).send().await; + + 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().to_vec()).unwrap()), + // If redirection + Some('3') => Err((true, payload.headers().get("location").unwrap().to_str().unwrap().to_string())), + // Otherwise + _ => Err((false, "Page not found".to_string())), } } - } - // If response is error - Err(ureq::Error::Status(_, _)) => { - #[cfg(debug_assertions)] - dbg!(format!("{} - Page not found", url)); - Err("Page not found") - } - // If failed to send request - Err(e) => { - #[cfg(debug_assertions)] - dbg!(e); - Err("Couldn't send request to Reddit") + Err(_) => Err((false, "Couldn't send request to Reddit".to_string())), } } + + fn err(u: String, m: String) -> Result { + #[cfg(debug_assertions)] + dbg!(format!("{} - {}", u, m)); + Err(m) + }; + + 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()), + } + } + + match send(&url).await { + Ok(body) => json(url, body), + Err((true, location)) => match send(location.as_str()).await { + Ok(body) => json(url, body), + Err((true, location)) => err(url, location), + Err((_, msg)) => err(url, msg), + }, + Err((_, msg)) => err(url, msg), + } } diff --git a/templates/error.html b/templates/error.html index cf86271..42067a7 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,6 +1,6 @@ {% extends "base.html" %} -{% block title %}Error: {{ message }}{% endblock %} +{% block title %}Error: {{ msg }}{% endblock %} {% block sortstyle %}{% endblock %} {% block content %} -

{{ message }}

+

{{ msg }}

{% endblock %} \ No newline at end of file