Added Percent Encoding Support

This commit is contained in:
spikecodes 2020-11-29 18:50:29 -08:00
parent 8f157c0b40
commit 9a6430656d
11 changed files with 63 additions and 16570 deletions

3
Cargo.lock generated
View File

@ -1394,11 +1394,12 @@ dependencies = [
[[package]]
name = "libreddit"
version = "0.1.7"
version = "0.1.8"
dependencies = [
"actix-web",
"askama",
"chrono",
"percent-encoding",
"pulldown-cmark",
"serde",
"serde_json",

View File

@ -3,15 +3,16 @@ name = "libreddit"
description = " Alternative private front-end to Reddit"
license = "AGPL-3.0"
repository = "https://github.com/spikecodes/libreddit"
version = "0.1.7"
version = "0.1.8"
authors = ["spikecodes <19519553+spikecodes@users.noreply.github.com>"]
edition = "2018"
[features]
default = ["proxy"]
proxy = ["actix-web/rustls"]
proxy = ["actix-web/rustls", "percent-encoding"]
[dependencies]
percent-encoding = { version = "2.1.0", optional = true }
actix-web = "3.2.0"
surf = "2.1.0"
askama = "0.8.0"

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
edition = "2018"
tab_spaces = 2
hard_tabs = true
max_width = 200
max_width = 175

View File

@ -4,9 +4,9 @@ use actix_web::{get, App, HttpResponse, HttpServer};
// Reference local files
mod popular;
mod post;
mod proxy;
mod subreddit;
mod user;
mod proxy;
mod utils;
// Create Services

View File

@ -1,7 +1,7 @@
// CRATES
use actix_web::{get, web, HttpResponse, Result, http::StatusCode};
use askama::Template;
use crate::utils::{fetch_posts, ErrorTemplate, Params, Post};
use actix_web::{get, http::StatusCode, web, HttpResponse, Result};
use askama::Template;
// STRUCTS
#[derive(Template)]

View File

@ -1,9 +1,12 @@
// CRATES
use actix_web::{get, web, HttpResponse, Result, http::StatusCode};
use crate::utils::{request, val, Comment, ErrorTemplate, Flair, Params, Post};
use actix_web::{get, http::StatusCode, web, HttpResponse, Result};
use askama::Template;
use chrono::{TimeZone, Utc};
use pulldown_cmark::{html, Options, Parser};
use crate::utils::{request, val, Comment, ErrorTemplate, Flair, Params, Post};
#[cfg(feature = "proxy")]
use percent_encoding::{utf8_percent_encode, NON_ALPHANUMERIC};
// STRUCTS
#[derive(Template)]
@ -66,6 +69,14 @@ async fn page(web::Path((_sub, id)): web::Path<(String, String)>, params: web::Q
}
}
async fn format_url(url: &str) -> String {
#[cfg(feature = "proxy")]
return utf8_percent_encode(url, NON_ALPHANUMERIC).to_string();
#[cfg(not(feature = "proxy"))]
return url.to_string();
}
// UTILITIES
async fn media(data: &serde_json::Value) -> String {
let post_hint: &str = data["data"]["post_hint"].as_str().unwrap_or("");
@ -76,15 +87,20 @@ async fn media(data: &serde_json::Value) -> String {
let media: String = if !has_media {
format!(r#"<h4 class="post_body"><a href="{u}">{u}</a></h4>"#, u = data["data"]["url"].as_str().unwrap())
} else {
format!(r#"<img class="post_image" src="{}{}.png"/>"#, prefix, data["data"]["url"].as_str().unwrap())
format!(
r#"<img class="post_image" src="{}{}.png"/>"#,
prefix,
format_url(data["data"]["url"].as_str().unwrap()).await
)
};
match post_hint {
"hosted:video" => format!(
r#"<video class="post_image" src="{}{}" controls/>"#,
prefix, data["data"]["media"]["reddit_video"]["fallback_url"].as_str().unwrap()
prefix,
format_url(data["data"]["media"]["reddit_video"]["fallback_url"].as_str().unwrap()).await
),
"image" => format!(r#"<img class="post_image" src="{}{}"/>"#, prefix, data["data"]["url"].as_str().unwrap()),
"image" => format!(r#"<img class="post_image" src="{}{}"/>"#, prefix, format_url(data["data"]["url"].as_str().unwrap()).await),
"self" => String::from(""),
_ => media,
}

View File

@ -1,18 +1,27 @@
use actix_web::{get, web, HttpResponse, Result, client::Client, Error};
use actix_web::{client::Client, get, web, Error, HttpResponse, Result};
#[cfg(feature = "proxy")]
use percent_encoding::percent_decode_str;
#[get("/imageproxy/{url:.*}")]
async fn handler(web::Path(url): web::Path<String>) -> Result<HttpResponse> {
if cfg!(feature = "proxy") {
dbg!(&url);
#[cfg(feature = "proxy")]
let media: String = percent_decode_str(url.as_str()).decode_utf8()?.to_string();
#[cfg(not(feature = "proxy"))]
let media: String = url;
dbg!(&media);
let client = Client::default();
client.get(url)
client
.get(media)
.send()
.await
.map_err(Error::from)
.and_then(|res| {
Ok(HttpResponse::build(res.status()).streaming(res))
})
.and_then(|res| Ok(HttpResponse::build(res.status()).streaming(res)))
} else {
Ok(HttpResponse::Ok().body(""))
}
}
}

View File

@ -1,7 +1,7 @@
// CRATES
use actix_web::{get, web, HttpResponse, Result, http::StatusCode};
use crate::utils::{fetch_posts, request, val, ErrorTemplate, Params, Post, Subreddit};
use actix_web::{get, http::StatusCode, web, HttpResponse, Result};
use askama::Template;
use crate::utils::{request, val, fetch_posts, ErrorTemplate, Params, Post, Subreddit};
// STRUCTS
#[derive(Template)]
@ -10,7 +10,7 @@ struct SubredditTemplate {
sub: Subreddit,
posts: Vec<Post>,
sort: String,
ends: (String, String)
ends: (String, String),
}
// SERVICES
@ -57,7 +57,7 @@ pub async fn render(sub_name: String, sort: Option<String>, ends: (Option<String
sub: sub,
posts: items.0,
sort: sorting,
ends: (before, items.1)
ends: (before, items.1),
}
.render()
.unwrap();
@ -82,7 +82,7 @@ async fn subreddit(sub: &String) -> Result<Subreddit, &'static str> {
let res = req.unwrap();
let members = res["data"]["subscribers"].as_u64().unwrap_or(0);
let active = res["data"]["accounts_active"].as_u64().unwrap_or(0);
let active = res["data"]["accounts_active"].as_u64().unwrap_or(0);
let sub = Subreddit {
name: val(&res, "display_name").await,
@ -94,4 +94,4 @@ async fn subreddit(sub: &String) -> Result<Subreddit, &'static str> {
};
Ok(sub)
}
}

View File

@ -1,7 +1,7 @@
// CRATES
use actix_web::{get, web, HttpResponse, Result, http::StatusCode};
use crate::utils::{fetch_posts, nested_val, request, ErrorTemplate, Params, Post, User};
use actix_web::{get, http::StatusCode, web, HttpResponse, Result};
use askama::Template;
use crate::utils::{nested_val, request, fetch_posts, ErrorTemplate, Params, Post, User};
// STRUCTS
#[derive(Template)]
@ -71,4 +71,4 @@ async fn user(name: &String) -> Result<User, &'static str> {
banner: nested_val(&res, "subreddit", "banner_img").await,
description: nested_val(&res, "subreddit", "public_description").await,
})
}
}

View File

@ -2,8 +2,8 @@
// CRATES
//
use chrono::{TimeZone, Utc};
use surf::{get, client, middleware::Redirect};
use serde_json::{Value, from_str};
use serde_json::{from_str, Value};
use surf::{client, get, middleware::Redirect};
//
// STRUCTS
@ -23,7 +23,7 @@ pub struct Post {
pub score: String,
pub media: String,
pub time: String,
pub flair: Flair
pub flair: Flair,
}
#[allow(dead_code)]
@ -32,7 +32,7 @@ pub struct Comment {
pub body: String,
pub author: String,
pub score: String,
pub time: String
pub time: String,
}
#[allow(dead_code)]
@ -42,7 +42,7 @@ pub struct User {
pub icon: String,
pub karma: i64,
pub banner: String,
pub description: String
pub description: String,
}
#[allow(dead_code)]
@ -53,7 +53,7 @@ pub struct Subreddit {
pub description: String,
pub icon: String,
pub members: String,
pub active: String
pub active: String,
}
// Parser for query params, used in sorting (eg. /r/rust/?sort=hot)
@ -61,14 +61,14 @@ pub struct Subreddit {
pub struct Params {
pub sort: Option<String>,
pub after: Option<String>,
pub before: Option<String>
pub before: Option<String>,
}
// Error template
#[derive(askama::Template)]
#[template(path = "error.html", escape = "none")]
pub struct ErrorTemplate {
pub message: String
pub message: String,
}
//