-
-
Notifications
You must be signed in to change notification settings - Fork 886
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Image api rework #5260
base: main
Are you sure you want to change the base?
Image api rework #5260
Conversation
b38a9ee
to
d252be2
Compare
09b06f0
to
60ba7af
Compare
f66e392
to
7c771d2
Compare
use lemmy_utils::rate_limit::RateLimitCell; | ||
|
||
// Deprecated, use api v4 instead. | ||
// When removing api v3, we also need to rewrite all links in database with | ||
// `/api/v3/image_proxy` to use `/api/v4/image_proxy` instead. | ||
// `/api/v3/image_proxy` to use `/api/v4/image/proxy` instead. | ||
pub fn config(cfg: &mut ServiceConfig, rate_limit: &RateLimitCell) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indentation was changed in this file, use "hide whitespace" in github to review it.
Ready to review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice job, adding these as API actions is going to be much better.
- We still need a way to clear images. I'd add some
POST
orDELETE
endpoints, that just delete the images and return that item. IEPOST /site/icon/delete
,/community/banner/delete
...- Speaking of which, I see that this PR is the first one that adds
HTTP DELETE
. Maybe we should use that instead ofPOST
for all our delete API actions.
- Speaking of which, I see that this PR is the first one that adds
- Banners can't be square. So whether that means adding both a max height and max width, or just unfortunately not being able to resize them.
- We're gonna need a DB migration to fix the history of all proxied images. So unfortunately that means doing a DB replace for
comment.content
, andpost.body
, wherelocal = true
. I believe the regular image endpoints stayed the same, so no need to correct those.
max_banner_size: 512 | ||
# Prevent users from uploading images for posts or embedding in markdown. Avatars, icons and | ||
# banners can still be uploaded. | ||
image_upload_disabled: false |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need to run scripts/./update_config_defaults.sh
delete_old_image(&local_user_view.person.banner, &context).await?; | ||
|
||
let form = PersonUpdateForm { | ||
banner: Some(Some(image.image_url.into())), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So how are we clearing these now?
You removed the code that sent an empty string to be able to set Some(None)
for these fields, so postgres can clear / unset an image. You need to have some way to be able to do this now.
@@ -46,14 +44,6 @@ pub async fn save_user_settings( | |||
.as_deref(), | |||
); | |||
|
|||
let avatar = diesel_url_update(data.avatar.as_deref())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By removing this, we don't have a way to clear / unset images, see comment above.
|
||
// Pictrs cannot use proxy | ||
#[allow(clippy::expect_used)] | ||
pub(super) static PICTRS_CLIENT: LazyLock<ClientWithMiddleware> = LazyLock::new(|| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This scares me, using a global static for a client. We should be trying to avoid these as much as possible, and instantiating a single client in the context and passing that around explicitly.
/// Otherwise we have to use crop, or use max_width/max_height which throws error | ||
/// if image is larger. | ||
/// TODO: whats a sensible default here? | ||
#[default(512)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Banners should never be square, so we probably should do max width + max height.
I found some banner sizes for current websites here.
|
||
pub async fn upload_community_icon( | ||
req: HttpRequest, | ||
query: Query<CommunityIdQuery>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@@ -18,7 +18,7 @@ pub fn markdown_rewrite_image_links(mut src: String) -> (String, Vec<Url>) { | |||
// If link points to remote domain, replace with proxied link | |||
if parsed.domain() != Some(&SETTINGS.hostname) { | |||
let mut proxied = format!( | |||
"{}/api/v4/image_proxy?url={}", | |||
"{}/api/v4/image/proxy?url={}", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be the right endpoint for new ones, but what about for all the past post bodies and comments? This is probably going to need a DB migration that fixes all the past ones, at least for our local images.
.route("/proxy", get().to(image_proxy)) | ||
.route("/{filename}", get().to(get_image)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the filename one is the same, but the /proxy
is new, correct? That means we're going to need to do a DB migration to correct all the past ones, or we're going to have broken proxied images.
is there a reason to expose the pict-rs delete token to the user? i guess this was historically exposed to the user during upload before it got used in the media listing, but there isn't really any need to keep that, now that we have the media listing. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For handling old image proxy links, I would prefer keeping both the old and new image proxy api endpoints permanently. Replacing old links in markdown content is slow, complicated, error prone, and might break a few image links from outside of Lemmy.
let local_site = LocalSite::read(&mut context.pool()).await?; | ||
if local_site.private_instance && local_user_view.is_none() { | ||
return Ok(HttpResponse::Unauthorized().finish()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optimization
let local_site = LocalSite::read(&mut context.pool()).await?; | |
if local_site.private_instance && local_user_view.is_none() { | |
return Ok(HttpResponse::Unauthorized().finish()); | |
} | |
if local_user_view.is_none() { | |
let local_site = LocalSite::read(&mut context.pool()).await?; | |
if local_site.private_instance { | |
return Ok(HttpResponse::Unauthorized().finish()); | |
} | |
} |
pub(super) fn file_type(file_type: Option<String>, name: &str) -> String { | ||
file_type | ||
.clone() | ||
.unwrap_or_else(|| name.split('.').last().unwrap_or("jpg").to_string()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not totally sure yet, but the calls to clone
and unwrap_or_else
probably shouldn't be in this function's body. The meaning of file_type.clone.unwrap_or_else(|| file_type(name))
could be more intuitive than file_type(file_type, name)
/api/v4/image/
crates/api_common/src/image.rs
, no more exposing of pictrs data structurescrates/routes/images
adapt_request()
for image upload, not for simple things like delete or health checkPOST /api/v4/account/avatar
which directly takes image upload, instead of setting avatar url via/api/v4/account/settings/save
POST /api/v4/account/banner
,POST /api/v4/community/icon
,POST /api/v4/community/banner
,POST /api/v4/site/icon
andPOST /api/v4/site/banner