diff --git a/Cargo.lock b/Cargo.lock index ef0ae92a..1878cfe3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1400,7 +1400,6 @@ dependencies = [ "libflate", "lipsum", "log", - "once_cell", "percent-encoding", "pretty_env_logger", "pulldown-cmark", diff --git a/Cargo.toml b/Cargo.toml index b17d442e..129784de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,7 +38,6 @@ rust-embed = { version = "8.1.0", features = ["include-exclude"] } libflate = "2.0.0" brotli = { version = "7.0.0", features = ["std"] } toml = "0.8.8" -once_cell = "1.19.0" serde_yaml = "0.9.29" build_html = "2.4.0" uuid = { version = "1.6.1", features = ["v4"] } diff --git a/src/client.rs b/src/client.rs index 1017b7d7..4d422155 100644 --- a/src/client.rs +++ b/src/client.rs @@ -8,12 +8,12 @@ use hyper::{body, body::Buf, header, Body, Client, Method, Request, Response, Ur use hyper_rustls::HttpsConnector; use libflate::gzip; use log::{error, trace, warn}; -use once_cell::sync::Lazy; use percent_encoding::{percent_encode, CONTROLS}; use serde_json::Value; use std::sync::atomic::Ordering; use std::sync::atomic::{AtomicBool, AtomicU16}; +use std::sync::LazyLock; use std::{io, result::Result}; use crate::dbg_msg; @@ -30,12 +30,12 @@ const REDDIT_SHORT_URL_BASE_HOST: &str = "redd.it"; const ALTERNATIVE_REDDIT_URL_BASE: &str = "https://www.reddit.com"; const ALTERNATIVE_REDDIT_URL_BASE_HOST: &str = "www.reddit.com"; -pub static HTTPS_CONNECTOR: Lazy> = - Lazy::new(|| hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http2().build()); +pub static HTTPS_CONNECTOR: LazyLock> = + LazyLock::new(|| hyper_rustls::HttpsConnectorBuilder::new().with_native_roots().https_only().enable_http2().build()); -pub static CLIENT: Lazy>> = Lazy::new(|| Client::builder().build::<_, Body>(HTTPS_CONNECTOR.clone())); +pub static CLIENT: LazyLock>> = LazyLock::new(|| Client::builder().build::<_, Body>(HTTPS_CONNECTOR.clone())); -pub static OAUTH_CLIENT: Lazy> = Lazy::new(|| { +pub static OAUTH_CLIENT: LazyLock> = LazyLock::new(|| { let client = block_on(Oauth::new()); tokio::spawn(token_daemon()); ArcSwap::new(client.into()) @@ -154,7 +154,7 @@ async fn stream(url: &str, req: &Request) -> Result, String let parsed_uri = url.parse::().map_err(|_| "Couldn't parse URL".to_string())?; // Build the hyper client from the HTTPS connector. - let client: &Lazy> = &CLIENT; + let client: &LazyLock> = &CLIENT; let mut builder = Request::get(parsed_uri); @@ -222,7 +222,7 @@ fn request(method: &'static Method, path: String, redirect: bool, quarantine: bo let url = format!("{base_path}{path}"); // Construct the hyper client from the HTTPS connector. - let client: &Lazy> = &CLIENT; + let client: &LazyLock> = &CLIENT; // Build request to Reddit. When making a GET, request gzip compression. // (Reddit doesn't do brotli yet.) diff --git a/src/config.rs b/src/config.rs index 69302ec4..b1a7cdb4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,12 +1,9 @@ -use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; -use std::{env::var, fs::read_to_string}; +use std::{env::var, fs::read_to_string, sync::LazyLock}; -// Waiting for https://github.com/rust-lang/rust/issues/74465 to land, so we -// can reduce reliance on once_cell. /// This is the local static that is initialized at runtime (technically at /// first request) and contains the instance settings. -pub static CONFIG: Lazy = Lazy::new(Config::load); +pub static CONFIG: LazyLock = LazyLock::new(Config::load); /// This serves as the frontend for an archival API - on removed comments, this URL /// will be the base of a link, to display removed content (on another site). diff --git a/src/instance_info.rs b/src/instance_info.rs index 66981897..8fc46a6a 100644 --- a/src/instance_info.rs +++ b/src/instance_info.rs @@ -6,14 +6,14 @@ use crate::{ use askama::Template; use build_html::{Container, Html, HtmlContainer, Table}; use hyper::{http::Error, Body, Request, Response}; -use once_cell::sync::Lazy; use serde::{Deserialize, Serialize}; +use std::sync::LazyLock; use time::OffsetDateTime; /// This is the local static that is initialized at runtime (technically at /// the first request to the info endpoint) and contains the data /// retrieved from the info endpoint. -pub static INSTANCE_INFO: Lazy = Lazy::new(InstanceInfo::new); +pub static INSTANCE_INFO: LazyLock = LazyLock::new(InstanceInfo::new); /// Handles instance info endpoint pub async fn instance_info(req: Request) -> Result, String> { diff --git a/src/main.rs b/src/main.rs index 00b86ae7..dc578187 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,12 +5,12 @@ use cached::proc_macro::cached; use clap::{Arg, ArgAction, Command}; use std::str::FromStr; +use std::sync::LazyLock; use futures_lite::FutureExt; use hyper::Uri; use hyper::{header::HeaderValue, Body, Request, Response}; use log::{info, warn}; -use once_cell::sync::Lazy; use redlib::client::{canonical_path, proxy, rate_limit_check, CLIENT}; use redlib::server::{self, RequestExt}; use redlib::utils::{error, redirect, ThemeAssets}; @@ -200,11 +200,11 @@ async fn main() { // at first request info!("Evaluating config."); - Lazy::force(&config::CONFIG); + LazyLock::force(&config::CONFIG); info!("Evaluating instance info."); - Lazy::force(&instance_info::INSTANCE_INFO); + LazyLock::force(&instance_info::INSTANCE_INFO); info!("Creating OAUTH client."); - Lazy::force(&OAUTH_CLIENT); + LazyLock::force(&OAUTH_CLIENT); // Define default headers (added to all responses) app.default_headers = headers! { diff --git a/src/oauth.rs b/src/oauth.rs index 9fb2fd5b..4f97cc5c 100644 --- a/src/oauth.rs +++ b/src/oauth.rs @@ -102,7 +102,7 @@ impl Oauth { trace!("Sending token request...\n\n{request:?}"); // Send request - let client: &once_cell::sync::Lazy> = &CLIENT; + let client: &std::sync::LazyLock> = &CLIENT; let resp = client.request(request).await?; trace!("Received response with status {} and length {:?}", resp.status(), resp.headers().get("content-length")); diff --git a/src/post.rs b/src/post.rs index dbad6293..78bcaf31 100644 --- a/src/post.rs +++ b/src/post.rs @@ -11,9 +11,9 @@ use crate::utils::{ use hyper::{Body, Request, Response}; use askama::Template; -use once_cell::sync::Lazy; use regex::Regex; use std::collections::{HashMap, HashSet}; +use std::sync::LazyLock; // STRUCTS #[derive(Template)] @@ -29,7 +29,7 @@ struct PostTemplate { comment_query: String, } -static COMMENT_SEARCH_CAPTURE: Lazy = Lazy::new(|| Regex::new(r"\?q=(.*)&type=comment").unwrap()); +static COMMENT_SEARCH_CAPTURE: LazyLock = LazyLock::new(|| Regex::new(r"\?q=(.*)&type=comment").unwrap()); pub async fn item(req: Request) -> Result, String> { // Build Reddit API path diff --git a/src/search.rs b/src/search.rs index 59afdb31..c7d6b003 100644 --- a/src/search.rs +++ b/src/search.rs @@ -9,8 +9,8 @@ use crate::{ }; use askama::Template; use hyper::{Body, Request, Response}; -use once_cell::sync::Lazy; use regex::Regex; +use std::sync::LazyLock; // STRUCTS struct SearchParams { @@ -52,7 +52,7 @@ struct SearchTemplate { } /// Regex matched against search queries to determine if they are reddit urls. -static REDDIT_URL_MATCH: Lazy = Lazy::new(|| Regex::new(r"^https?://([^\./]+\.)*reddit.com/").unwrap()); +static REDDIT_URL_MATCH: LazyLock = LazyLock::new(|| Regex::new(r"^https?://([^\./]+\.)*reddit.com/").unwrap()); // SERVICES pub async fn find(req: Request) -> Result, String> { diff --git a/src/subreddit.rs b/src/subreddit.rs index 687dc33e..4046be1c 100644 --- a/src/subreddit.rs +++ b/src/subreddit.rs @@ -13,8 +13,8 @@ use htmlescape::decode_html; use hyper::{Body, Request, Response}; use chrono::DateTime; -use once_cell::sync::Lazy; use regex::Regex; +use std::sync::LazyLock; use time::{Duration, OffsetDateTime}; // STRUCTS @@ -58,7 +58,7 @@ struct WallTemplate { url: String, } -static GEO_FILTER_MATCH: Lazy = Lazy::new(|| Regex::new(r"geo_filter=(?\w+)").unwrap()); +static GEO_FILTER_MATCH: LazyLock = LazyLock::new(|| Regex::new(r"geo_filter=(?\w+)").unwrap()); // SERVICES pub async fn community(req: Request) -> Result, String> { diff --git a/src/utils.rs b/src/utils.rs index e460da8c..cc191cdc 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -11,7 +11,6 @@ use cookie::Cookie; use hyper::{Body, Request, Response}; use libflate::deflate::{Decoder, Encoder}; use log::error; -use once_cell::sync::Lazy; use regex::Regex; use revision::revisioned; use rust_embed::RustEmbed; @@ -23,6 +22,7 @@ use std::env; use std::io::{Read, Write}; use std::str::FromStr; use std::string::ToString; +use std::sync::LazyLock; use time::{macros::format_description, Duration, OffsetDateTime}; use url::Url; @@ -1003,20 +1003,20 @@ pub async fn catch_random(sub: &str, additional: &str) -> Result, } } -static REGEX_URL_WWW: Lazy = Lazy::new(|| Regex::new(r"https?://www\.reddit\.com/(.*)").unwrap()); -static REGEX_URL_OLD: Lazy = Lazy::new(|| Regex::new(r"https?://old\.reddit\.com/(.*)").unwrap()); -static REGEX_URL_NP: Lazy = Lazy::new(|| Regex::new(r"https?://np\.reddit\.com/(.*)").unwrap()); -static REGEX_URL_PLAIN: Lazy = Lazy::new(|| Regex::new(r"https?://reddit\.com/(.*)").unwrap()); -static REGEX_URL_VIDEOS: Lazy = Lazy::new(|| Regex::new(r"https?://v\.redd\.it/(.*)/DASH_([0-9]{2,4}(\.mp4|$|\?source=fallback))").unwrap()); -static REGEX_URL_VIDEOS_HLS: Lazy = Lazy::new(|| Regex::new(r"https?://v\.redd\.it/(.+)/(HLSPlaylist\.m3u8.*)$").unwrap()); -static REGEX_URL_IMAGES: Lazy = Lazy::new(|| Regex::new(r"https?://i\.redd\.it/(.*)").unwrap()); -static REGEX_URL_THUMBS_A: Lazy = Lazy::new(|| Regex::new(r"https?://a\.thumbs\.redditmedia\.com/(.*)").unwrap()); -static REGEX_URL_THUMBS_B: Lazy = Lazy::new(|| Regex::new(r"https?://b\.thumbs\.redditmedia\.com/(.*)").unwrap()); -static REGEX_URL_EMOJI: Lazy = Lazy::new(|| Regex::new(r"https?://emoji\.redditmedia\.com/(.*)/(.*)").unwrap()); -static REGEX_URL_PREVIEW: Lazy = Lazy::new(|| Regex::new(r"https?://preview\.redd\.it/(.*)").unwrap()); -static REGEX_URL_EXTERNAL_PREVIEW: Lazy = Lazy::new(|| Regex::new(r"https?://external\-preview\.redd\.it/(.*)").unwrap()); -static REGEX_URL_STYLES: Lazy = Lazy::new(|| Regex::new(r"https?://styles\.redditmedia\.com/(.*)").unwrap()); -static REGEX_URL_STATIC_MEDIA: Lazy = Lazy::new(|| Regex::new(r"https?://www\.redditstatic\.com/(.*)").unwrap()); +static REGEX_URL_WWW: LazyLock = LazyLock::new(|| Regex::new(r"https?://www\.reddit\.com/(.*)").unwrap()); +static REGEX_URL_OLD: LazyLock = LazyLock::new(|| Regex::new(r"https?://old\.reddit\.com/(.*)").unwrap()); +static REGEX_URL_NP: LazyLock = LazyLock::new(|| Regex::new(r"https?://np\.reddit\.com/(.*)").unwrap()); +static REGEX_URL_PLAIN: LazyLock = LazyLock::new(|| Regex::new(r"https?://reddit\.com/(.*)").unwrap()); +static REGEX_URL_VIDEOS: LazyLock = LazyLock::new(|| Regex::new(r"https?://v\.redd\.it/(.*)/DASH_([0-9]{2,4}(\.mp4|$|\?source=fallback))").unwrap()); +static REGEX_URL_VIDEOS_HLS: LazyLock = LazyLock::new(|| Regex::new(r"https?://v\.redd\.it/(.+)/(HLSPlaylist\.m3u8.*)$").unwrap()); +static REGEX_URL_IMAGES: LazyLock = LazyLock::new(|| Regex::new(r"https?://i\.redd\.it/(.*)").unwrap()); +static REGEX_URL_THUMBS_A: LazyLock = LazyLock::new(|| Regex::new(r"https?://a\.thumbs\.redditmedia\.com/(.*)").unwrap()); +static REGEX_URL_THUMBS_B: LazyLock = LazyLock::new(|| Regex::new(r"https?://b\.thumbs\.redditmedia\.com/(.*)").unwrap()); +static REGEX_URL_EMOJI: LazyLock = LazyLock::new(|| Regex::new(r"https?://emoji\.redditmedia\.com/(.*)/(.*)").unwrap()); +static REGEX_URL_PREVIEW: LazyLock = LazyLock::new(|| Regex::new(r"https?://preview\.redd\.it/(.*)").unwrap()); +static REGEX_URL_EXTERNAL_PREVIEW: LazyLock = LazyLock::new(|| Regex::new(r"https?://external\-preview\.redd\.it/(.*)").unwrap()); +static REGEX_URL_STYLES: LazyLock = LazyLock::new(|| Regex::new(r"https?://styles\.redditmedia\.com/(.*)").unwrap()); +static REGEX_URL_STATIC_MEDIA: LazyLock = LazyLock::new(|| Regex::new(r"https?://www\.redditstatic\.com/(.*)").unwrap()); /// Direct urls to proxy if proxy is enabled pub fn format_url(url: &str) -> String { @@ -1075,8 +1075,8 @@ pub fn format_url(url: &str) -> String { } } -static REGEX_BULLET: Lazy = Lazy::new(|| Regex::new(r"(?m)^- (.*)$").unwrap()); -static REGEX_BULLET_CONSECUTIVE_LINES: Lazy = Lazy::new(|| Regex::new(r"\n
    ").unwrap()); +static REGEX_BULLET: LazyLock = LazyLock::new(|| Regex::new(r"(?m)^- (.*)$").unwrap()); +static REGEX_BULLET_CONSECUTIVE_LINES: LazyLock = LazyLock::new(|| Regex::new(r"
\n
    ").unwrap()); pub fn render_bullet_lists(input_text: &str) -> String { // ref: https://stackoverflow.com/a/4902622 @@ -1087,11 +1087,11 @@ pub fn render_bullet_lists(input_text: &str) -> String { } // These are links we want to replace in-body -static REDDIT_REGEX: Lazy = Lazy::new(|| Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.|)(reddit\.com|redd\.it)/"#).unwrap()); -static REDDIT_PREVIEW_REGEX: Lazy = Lazy::new(|| Regex::new(r"https?://(external-preview|preview|i)\.redd\.it(.*)").unwrap()); -static REDDIT_EMOJI_REGEX: Lazy = Lazy::new(|| Regex::new(r"https?://(www|).redditstatic\.com/(.*)").unwrap()); -static REDLIB_PREVIEW_LINK_REGEX: Lazy = Lazy::new(|| Regex::new(r#"/(img|preview/)(pre|external-pre)?/(.*?)>"#).unwrap()); -static REDLIB_PREVIEW_TEXT_REGEX: Lazy = Lazy::new(|| Regex::new(r">(.*?)").unwrap()); +static REDDIT_REGEX: LazyLock = LazyLock::new(|| Regex::new(r#"href="(https|http|)://(www\.|old\.|np\.|amp\.|new\.|)(reddit\.com|redd\.it)/"#).unwrap()); +static REDDIT_PREVIEW_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"https?://(external-preview|preview|i)\.redd\.it(.*)").unwrap()); +static REDDIT_EMOJI_REGEX: LazyLock = LazyLock::new(|| Regex::new(r"https?://(www|).redditstatic\.com/(.*)").unwrap()); +static REDLIB_PREVIEW_LINK_REGEX: LazyLock = LazyLock::new(|| Regex::new(r#"/(img|preview/)(pre|external-pre)?/(.*?)>"#).unwrap()); +static REDLIB_PREVIEW_TEXT_REGEX: LazyLock = LazyLock::new(|| Regex::new(r">(.*?)").unwrap()); /// Rewrite Reddit links to Redlib in body of text pub fn rewrite_urls(input_text: &str) -> String { @@ -1162,10 +1162,10 @@ pub fn rewrite_urls(input_text: &str) -> String { } // These links all follow a pattern of "https://reddit-econ-prod-assets-permanent.s3.amazonaws.com/asset-manager/SUBREDDIT_ID/RANDOM_FILENAME.png" -static REDDIT_EMOTE_LINK_REGEX: Lazy = Lazy::new(|| Regex::new(r#"https://reddit-econ-prod-assets-permanent.s3.amazonaws.com/asset-manager/(.*)"#).unwrap()); +static REDDIT_EMOTE_LINK_REGEX: LazyLock = LazyLock::new(|| Regex::new(r#"https://reddit-econ-prod-assets-permanent.s3.amazonaws.com/asset-manager/(.*)"#).unwrap()); // These all follow a pattern of '"emote|SUBREDDIT_IT|NUMBER"', we want the number -static REDDIT_EMOTE_ID_NUMBER_REGEX: Lazy = Lazy::new(|| Regex::new(r#""emote\|.*\|(.*)""#).unwrap()); +static REDDIT_EMOTE_ID_NUMBER_REGEX: LazyLock = LazyLock::new(|| Regex::new(r#""emote\|.*\|(.*)""#).unwrap()); pub fn rewrite_emotes(media_metadata: &Value, comment: String) -> String { /* Create the paths we'll use to look for our data inside the json.