Merge pull request #363 from philomena-dev/rust-refactor

Rust code refactor
This commit is contained in:
liamwhite 2024-11-09 00:05:30 -05:00 committed by GitHub
commit 78a9caf083
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 54 additions and 58 deletions

View file

@ -75,8 +75,7 @@ defmodule PhilomenaWeb.MarkdownRenderer do
defp render_representations(images, conn) do defp render_representations(images, conn) do
loaded_images = load_images(images) loaded_images = load_images(images)
images Map.new(images, fn group ->
|> Enum.map(fn group ->
img = loaded_images[Enum.at(group, 0)] img = loaded_images[Enum.at(group, 0)]
text = "#{Enum.at(group, 0)}#{Enum.at(group, 1)}" text = "#{Enum.at(group, 0)}#{Enum.at(group, 1)}"
@ -131,8 +130,7 @@ defmodule PhilomenaWeb.MarkdownRenderer do
|> Phoenix.HTML.Safe.to_iodata() |> Phoenix.HTML.Safe.to_iodata()
|> IO.iodata_to_binary() |> IO.iodata_to_binary()
[text, string_contents] {text, string_contents}
end) end)
|> Map.new(fn [id, html] -> {id, html} end)
end end
end end

View file

@ -260,7 +260,9 @@ version = "0.3.0"
dependencies = [ dependencies = [
"base64", "base64",
"comrak", "comrak",
"http",
"jemallocator", "jemallocator",
"regex",
"ring", "ring",
"rustler", "rustler",
"url", "url",

View file

@ -10,11 +10,13 @@ path = "src/lib.rs"
crate-type = ["dylib"] crate-type = ["dylib"]
[dependencies] [dependencies]
comrak = { git = "https://github.com/philomena-dev/comrak", branch = "main", default-features = false }
jemallocator = { version = "0.5.0", features = ["disable_initial_exec_tls"] }
rustler = "0.28"
ring = "0.16"
base64 = "0.21" base64 = "0.21"
comrak = { git = "https://github.com/philomena-dev/comrak", branch = "main", default-features = false }
http = "0.2"
jemallocator = { version = "0.5.0", features = ["disable_initial_exec_tls"] }
regex = "1"
ring = "0.16"
rustler = "0.28"
url = "2.3" url = "2.3"
[profile.release] [profile.release]

View file

@ -11,7 +11,7 @@ fn trusted_host(mut url: Url) -> Option<String> {
Some(url.to_string()) Some(url.to_string())
} }
fn untrusted_host(url: Url, camo_host: String, camo_key: String) -> Option<String> { fn untrusted_host(url: Url, camo_host: &str, camo_key: &str) -> Option<String> {
let camo_url = format!("https://{}", camo_host); let camo_url = format!("https://{}", camo_host);
let key = hmac::Key::new(hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, camo_key.as_ref()); let key = hmac::Key::new(hmac::HMAC_SHA1_FOR_LEGACY_USE_ONLY, camo_key.as_ref());
let tag = hmac::sign(&key, url.to_string().as_bytes()); let tag = hmac::sign(&key, url.to_string().as_bytes());
@ -27,20 +27,24 @@ fn untrusted_host(url: Url, camo_host: String, camo_key: String) -> Option<Strin
Some(camo_uri.to_string()) Some(camo_uri.to_string())
} }
pub fn image_url(uri: String) -> Option<String> { pub fn image_url(uri: &str) -> Option<String> {
let cdn_host = env::var("CDN_HOST").ok()?; let cdn_host = env::var("CDN_HOST").ok()?;
let camo_host = env::var("CAMO_HOST").unwrap_or_else(|_| String::from("")); let camo_host = env::var("CAMO_HOST").unwrap_or_else(|_| "".into());
let camo_key = env::var("CAMO_KEY").unwrap_or_else(|_| String::from("")); let camo_key = env::var("CAMO_KEY").unwrap_or_else(|_| "".into());
if camo_key.is_empty() { if camo_key.is_empty() {
return Some(uri); return Some(uri.into());
} }
let url = Url::parse(&uri).ok()?; let url = Url::parse(uri).ok()?;
match url.host_str() { match url.host_str() {
Some(hostname) if hostname == cdn_host || hostname == camo_host => trusted_host(url), Some(hostname) if hostname == cdn_host || hostname == camo_host => trusted_host(url),
Some(_) => untrusted_host(url, camo_host, camo_key), Some(_) => untrusted_host(url, &camo_host, &camo_key),
None => Some(String::from("")), None => Some("".into()),
} }
} }
pub fn image_url_careful(uri: &str) -> String {
image_url(uri).unwrap_or_else(|| "".into())
}

View file

@ -0,0 +1,14 @@
use std::env;
pub fn get() -> Option<Vec<String>> {
if let Ok(domains) = env::var("SITE_DOMAINS") {
return Some(
domains
.split(',')
.map(|s| s.to_string())
.collect::<Vec<String>>(),
);
}
None
}

View file

@ -1,7 +1,8 @@
use jemallocator::Jemalloc; use jemallocator::Jemalloc;
use rustler::Term; use std::collections::HashMap;
mod camo; mod camo;
mod domains;
mod markdown; mod markdown;
#[global_allocator] #[global_allocator]
@ -15,18 +16,18 @@ rustler::init! {
// Markdown NIF wrappers. // Markdown NIF wrappers.
#[rustler::nif(schedule = "DirtyCpu")] #[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html(input: String, reps: Term) -> String { fn markdown_to_html(input: &str, reps: HashMap<String, String>) -> String {
markdown::to_html(input, reps) markdown::to_html(input, reps)
} }
#[rustler::nif(schedule = "DirtyCpu")] #[rustler::nif(schedule = "DirtyCpu")]
fn markdown_to_html_unsafe(input: String, reps: Term) -> String { fn markdown_to_html_unsafe(input: &str, reps: HashMap<String, String>) -> String {
markdown::to_html_unsafe(input, reps) markdown::to_html_unsafe(input, reps)
} }
// Camo NIF wrappers. // Camo NIF wrappers.
#[rustler::nif] #[rustler::nif]
fn camo_image_url(input: String) -> String { fn camo_image_url(input: &str) -> String {
camo::image_url(input).unwrap_or_else(|| String::from("")) camo::image_url_careful(input)
} }

View file

@ -1,11 +1,9 @@
use crate::camo; use crate::{camo, domains};
use comrak::ComrakOptions; use comrak::Options;
use rustler::{MapIterator, Term};
use std::collections::HashMap; use std::collections::HashMap;
use std::env;
fn common_options() -> ComrakOptions { fn common_options() -> Options {
let mut options = ComrakOptions::default(); let mut options = Options::default();
options.extension.autolink = true; options.extension.autolink = true;
options.extension.table = true; options.extension.table = true;
options.extension.description_lists = true; options.extension.description_lists = true;
@ -16,47 +14,24 @@ fn common_options() -> ComrakOptions {
options.render.hardbreaks = true; options.render.hardbreaks = true;
options.render.github_pre_lang = true; options.render.github_pre_lang = true;
options.extension.camoifier = Some(|s| camo::image_url(s).unwrap_or_else(|| String::from(""))); options.extension.camoifier = Some(|s| camo::image_url_careful(&s));
options.extension.philomena_domains = domains::get();
if let Ok(domains) = env::var("SITE_DOMAINS") {
options.extension.philomena_domains = Some(
domains
.split(',')
.map(|s| s.to_string())
.collect::<Vec<String>>(),
);
}
options options
} }
fn map_to_hashmap(map: Term) -> Option<HashMap<String, String>> { pub fn to_html(input: &str, reps: HashMap<String, String>) -> String {
Some(
MapIterator::new(map)?
.map(|(key, value)| {
let key: String = key.decode().unwrap_or_else(|_| String::from(""));
let value: String = value.decode().unwrap_or_else(|_| String::from(""));
(key, value)
})
.collect(),
)
}
pub fn to_html(input: String, reps: Term) -> String {
let mut options = common_options(); let mut options = common_options();
options.render.escape = true; options.render.escape = true;
options.extension.philomena_replacements = Some(reps);
options.extension.philomena_replacements = map_to_hashmap(reps); comrak::markdown_to_html(input, &options)
comrak::markdown_to_html(&input, &options)
} }
pub fn to_html_unsafe(input: String, reps: Term) -> String { pub fn to_html_unsafe(input: &str, reps: HashMap<String, String>) -> String {
let mut options = common_options(); let mut options = common_options();
options.render.unsafe_ = true; options.render.unsafe_ = true;
options.extension.philomena_replacements = Some(reps);
options.extension.philomena_replacements = map_to_hashmap(reps); comrak::markdown_to_html(input, &options)
comrak::markdown_to_html(&input, &options)
} }