use enum for image proxy setting

markdown-link-rule
Felix Ableitner 2024-01-08 12:36:21 +01:00
parent a88f4d6ef3
commit 518af87802
4 changed files with 70 additions and 51 deletions

View File

@ -36,29 +36,36 @@
# Maximum number of active sql connections # Maximum number of active sql connections
pool_size: 95 pool_size: 95
} }
# Settings related to activitypub federation
# Pictrs image server configuration. # Pictrs image server configuration.
pictrs: { pictrs: {
# Address where pictrs is available (for image hosting) # Address where pictrs is available (for image hosting)
url: "http://localhost:8080/" url: "http://localhost:8080/"
# Set a custom pictrs API key. ( Required for deleting images ) # Set a custom pictrs API key. ( Required for deleting images )
api_key: "string" api_key: "string"
# If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`. # Specifies how to handle remote images, so that users don't have to connect directly to remote servers.
# This improves privacy as users don't expose their IP to untrusted servers, and decreases load image_mode:
# on other servers. However it causes more load for the local server. # Leave images unchanged, don't generate any local thumbnails for post urls. Instead the the
# # Opengraph image is directly returned as thumbnail
# Requires pict-rs 0.5 "None"
image_proxy: false
# By default the thumbnails for external links are stored in pict-rs. This ensures that they # or
# can be reliably retrieved and can be resized using pict-rs APIs. However it also increases
# storage usage. In case this is disabled, the Opengraph image is directly returned as # Generate thumbnails for external post urls and store them persistently in pict-rs. This
# thumbnail.Note that it still gets proxied through the local instance if `image_proxy` is # ensures that they can be reliably retrieved and can be resized using pict-rs APIs. However
# enabled. # it also increases storage usage.
# #
# In some countries it is forbidden to copy preview images from newspaper articles and only # This is the default behaviour, and also matches Lemmy 0.18.
# hotlinking is allowed. If that is the case for your instance, make sure that `image_proxy` and "StoreLinkPreviews"
# `cache_external_link_previews` are both disabled.
cache_external_link_previews: true # or
# If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`,
# including embedded images in markdown. Images are stored temporarily in pict-rs for caching.
# This improves privacy as users don't expose their IP to untrusted servers, and decreases load
# on other servers. However it increases bandwidth use for the local server.
#
# Requires pict-rs 0.5
"ProxyAllImages"
# Timeout for uploading images to pictrs (in seconds) # Timeout for uploading images to pictrs (in seconds)
upload_timeout: 30 upload_timeout: 30
} }

View File

@ -7,7 +7,7 @@ use encoding::{all::encodings, DecoderTrap};
use lemmy_db_schema::newtypes::DbUrl; use lemmy_db_schema::newtypes::DbUrl;
use lemmy_utils::{ use lemmy_utils::{
error::{LemmyError, LemmyErrorType}, error::{LemmyError, LemmyErrorType},
settings::structs::Settings, settings::structs::{ImageProxyMode, Settings},
version::VERSION, version::VERSION,
REQWEST_TIMEOUT, REQWEST_TIMEOUT,
}; };
@ -258,7 +258,7 @@ async fn generate_pictrs_thumbnail(
) -> Result<Url, LemmyError> { ) -> Result<Url, LemmyError> {
let pictrs_config = context.settings().pictrs_config()?; let pictrs_config = context.settings().pictrs_config()?;
if !pictrs_config.cache_external_link_previews { if pictrs_config.image_mode == ImageProxyMode::ProxyAllImages {
return Ok(proxy_image_link(image_url.clone(), context).await?.into()); return Ok(proxy_image_link(image_url.clone(), context).await?.into());
} }

View File

@ -35,7 +35,7 @@ use lemmy_utils::{
email::{send_email, translations::Lang}, email::{send_email, translations::Lang},
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult}, error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
rate_limit::{ActionType, BucketConfig}, rate_limit::{ActionType, BucketConfig},
settings::structs::Settings, settings::structs::{ImageProxyMode, Settings},
utils::{ utils::{
markdown::markdown_rewrite_image_links, markdown::markdown_rewrite_image_links,
slurs::{build_slur_regex, remove_slurs}, slurs::{build_slur_regex, remove_slurs},
@ -846,7 +846,7 @@ pub async fn process_markdown(
context: &LemmyContext, context: &LemmyContext,
) -> LemmyResult<String> { ) -> LemmyResult<String> {
let text = remove_slurs(text, slur_regex); let text = remove_slurs(text, slur_regex);
if context.settings().pictrs_config()?.image_proxy { if context.settings().pictrs_config()?.image_mode == ImageProxyMode::ProxyAllImages {
let (text, links) = markdown_rewrite_image_links(text); let (text, links) = markdown_rewrite_image_links(text);
RemoteImage::create(&mut context.pool(), links).await?; RemoteImage::create(&mut context.pool(), links).await?;
Ok(text) Ok(text)
@ -872,13 +872,13 @@ pub async fn process_markdown_opt(
/// as separate parameter so it can be changed in tests. /// as separate parameter so it can be changed in tests.
async fn proxy_image_link_internal( async fn proxy_image_link_internal(
link: Url, link: Url,
force_image_proxy: bool, image_proxy_mode: ImageProxyMode,
context: &LemmyContext, context: &LemmyContext,
) -> LemmyResult<DbUrl> { ) -> LemmyResult<DbUrl> {
// Dont rewrite links pointing to local domain. // Dont rewrite links pointing to local domain.
if link.domain() == Some(&context.settings().hostname) || !force_image_proxy { if link.domain() == Some(&context.settings().hostname) {
Ok(link.into()) Ok(link.into())
} else { } else if image_proxy_mode == ImageProxyMode::ProxyAllImages {
let proxied = format!( let proxied = format!(
"{}/api/v3/image_proxy?url={}", "{}/api/v3/image_proxy?url={}",
context.settings().get_protocol_and_hostname(), context.settings().get_protocol_and_hostname(),
@ -886,6 +886,8 @@ async fn proxy_image_link_internal(
); );
RemoteImage::create(&mut context.pool(), vec![link]).await?; RemoteImage::create(&mut context.pool(), vec![link]).await?;
Ok(Url::parse(&proxied)?.into()) Ok(Url::parse(&proxied)?.into())
} else {
Ok(link.into())
} }
} }
@ -894,7 +896,7 @@ async fn proxy_image_link_internal(
pub(crate) async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult<DbUrl> { pub(crate) async fn proxy_image_link(link: Url, context: &LemmyContext) -> LemmyResult<DbUrl> {
proxy_image_link_internal( proxy_image_link_internal(
link, link,
context.settings().pictrs_config()?.image_proxy, context.settings().pictrs_config()?.image_mode,
context, context,
) )
.await .await
@ -993,16 +995,21 @@ mod tests {
// image from local domain is unchanged // image from local domain is unchanged
let local_url = Url::parse("http://lemmy-alpha/image.png").unwrap(); let local_url = Url::parse("http://lemmy-alpha/image.png").unwrap();
let proxied = proxy_image_link_internal(local_url.clone(), true, &context) let proxied =
.await proxy_image_link_internal(local_url.clone(), ImageProxyMode::ProxyAllImages, &context)
.unwrap(); .await
.unwrap();
assert_eq!(&local_url, proxied.inner()); assert_eq!(&local_url, proxied.inner());
// image from remote domain is proxied // image from remote domain is proxied
let remote_image = Url::parse("http://lemmy-beta/image.png").unwrap(); let remote_image = Url::parse("http://lemmy-beta/image.png").unwrap();
let proxied = proxy_image_link_internal(remote_image.clone(), true, &context) let proxied = proxy_image_link_internal(
.await remote_image.clone(),
.unwrap(); ImageProxyMode::ProxyAllImages,
&context,
)
.await
.unwrap();
assert_eq!( assert_eq!(
"https://lemmy-alpha/api/v3/image_proxy?url=http%3A%2F%2Flemmy-beta%2Fimage.png", "https://lemmy-alpha/api/v3/image_proxy?url=http%3A%2F%2Flemmy-beta%2Fimage.png",
proxied.as_str() proxied.as_str()

View File

@ -12,7 +12,6 @@ pub struct Settings {
/// settings related to the postgresql database /// settings related to the postgresql database
#[default(Default::default())] #[default(Default::default())]
pub database: DatabaseConfig, pub database: DatabaseConfig,
/// Settings related to activitypub federation
/// Pictrs image server configuration. /// Pictrs image server configuration.
#[default(Some(Default::default()))] #[default(Some(Default::default()))]
pub(crate) pictrs: Option<PictrsConfig>, pub(crate) pictrs: Option<PictrsConfig>,
@ -79,31 +78,37 @@ pub struct PictrsConfig {
#[default(None)] #[default(None)]
pub api_key: Option<String>, pub api_key: Option<String>,
/// If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`. /// Specifies how to handle remote images, so that users don't have to connect directly to remote servers.
/// This improves privacy as users don't expose their IP to untrusted servers, and decreases load #[default(ImageProxyMode::StoreLinkPreviews)]
/// on other servers. However it causes more load for the local server. pub image_mode: ImageProxyMode,
///
/// Requires pict-rs 0.5
#[default(false)]
pub image_proxy: bool,
/// By default the thumbnails for external links are stored in pict-rs. This ensures that they
/// can be reliably retrieved and can be resized using pict-rs APIs. However it also increases
/// storage usage. In case this is disabled, the Opengraph image is directly returned as
/// thumbnail.Note that it still gets proxied through the local instance if `image_proxy` is
/// enabled.
///
/// In some countries it is forbidden to copy preview images from newspaper articles and only
/// hotlinking is allowed. If that is the case for your instance, make sure that `image_proxy` and
/// `cache_external_link_previews` are both disabled.
#[default(true)]
pub cache_external_link_previews: bool,
/// Timeout for uploading images to pictrs (in seconds) /// Timeout for uploading images to pictrs (in seconds)
#[default(30)] #[default(30)]
pub upload_timeout: u64, pub upload_timeout: u64,
} }
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document, PartialEq)]
#[serde(deny_unknown_fields)]
pub enum ImageProxyMode {
/// Leave images unchanged, don't generate any local thumbnails for post urls. Instead the the
/// Opengraph image is directly returned as thumbnail
None,
/// Generate thumbnails for external post urls and store them persistently in pict-rs. This
/// ensures that they can be reliably retrieved and can be resized using pict-rs APIs. However
/// it also increases storage usage.
///
/// This is the default behaviour, and also matches Lemmy 0.18.
#[default]
StoreLinkPreviews,
/// If enabled, all images from remote domains are rewritten to pass through `/api/v3/image_proxy`,
/// including embedded images in markdown. Images are stored temporarily in pict-rs for caching.
/// This improves privacy as users don't expose their IP to untrusted servers, and decreases load
/// on other servers. However it increases bandwidth use for the local server.
///
/// Requires pict-rs 0.5
ProxyAllImages,
}
#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] #[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)]
#[serde(default)] #[serde(default)]
pub struct DatabaseConfig { pub struct DatabaseConfig {