Avatar refactor, move avatar code from models
to models.avatars
, remove duplicated code #17123
Labels
No Label
backport/done
backport/v1.0
backport/v1.1
backport/v1.10
backport/v1.11
backport/v1.12
backport/v1.13
backport/v1.14
backport/v1.15
backport/v1.2
backport/v1.3
backport/v1.4
backport/v1.5
backport/v1.6
backport/v1.7
backport/v1.8
backport/v1.9
bounty
changelog
dependencies
frontport/done
frontport/main
good first issue
Hacktoberfest
hacktoberfest-accepted
in progress
kind/api
kind/breaking
kind/bug
kind/build
kind/deployment
kind/deprecated
kind/docs
kind/enhancement
kind/feature
kind/lint
kind/misc
kind/moderation
kind/package
kind/proposal
kind/question
kind/refactor
kind/regression
kind/security
kind/summary
kind/testing
kind/translation
kind/ui
kind/upstream-related
kind/usability
kind/ux
lgtm/done
lgtm/need 1
lgtm/need 2
performance/bigrepo
performance/cpu
performance/memory
performance/speed
priority/critical
priority/low
priority/maybe
priority/medium
proposal/rejected
reviewed/confirmed
reviewed/duplicate
reviewed/fixed
reviewed/invalid
reviewed/not-a-bug
reviewed/wontfix
skip-changelog
stale
status/blocked
status/needs-feedback
status/wip
theme/2fa
theme/authentication
theme/avatar
theme/backup-restore
theme/docker
theme/federation
theme/issues
theme/kanban
theme/markdown
theme/migration
theme/mobile
theme/pr
theme/signing
theme/sqlite
theme/timetracker
theme/webhook
theme/wiki
No Milestone
No project
No Assignees
4 Participants
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: lunny/gitea#17123
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "avatar-refactor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Why this refactor
The goal is to move most files from
models
package tomodels.xxx
package. Many models depend on avatar model, so just move this first.And the existing logic is not clear, there are too many function like
AvatarLink
,RelAvatarLink
,SizedRelAvatarLink
,SizedAvatarLink
,MakeFinalAvatarURL
,HashedAvatarLink
, etc. This refactor make everything clear:And many duplicated code are deleted in route handler, the handler and the model share the same avatar logic now.
@ -0,0 +102,4 @@
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
}
return lowerEmail, nil
Can't it be written as the following, or am I misunderstanding something here?
Alternatively, if I interpret the
[1:]
correctly:Alternatively, the version using formatted strings would be possible here but that would require the re-import of
fmt
.Why is the size here lower bounded to
0
, and in line 126 below toDefaultAvatarSize
? I think these two should be set to the same value.@ -60,61 +59,41 @@ func (u *User) generateRandomAvatar(e db.Engine) error {
return nil
By doing that, you can remove the whole
useLocalAvatar
variable and make the calls below a little easier to read. Especially the return in 96 can then be removed.Does something speak against
here?
And this would then be the else block.
@ -0,0 +102,4 @@
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
}
return lowerEmail, nil
They are from the legacy code. I do not want to change the logic now.
@ -60,61 +59,41 @@ func (u *User) generateRandomAvatar(e db.Engine) error {
return nil
I'd like to put all generated / returned URL together, it makes the flow more clear. There may be more switch-cases which doesn't use local avatar and needs more logic, current flow can be extended easily.
@ -60,61 +59,41 @@ func (u *User) generateRandomAvatar(e db.Engine) error {
return nil
The
else
doesn't help about the logic. And thesize
andu.Avatar
are independent variables, it's better to keep them in differentif
.@ -60,61 +59,41 @@ func (u *User) generateRandomAvatar(e db.Engine) error {
return nil
Explained above.
0
and-1
have same meaning in related logic, all will be default avatar size.I prefer to use 0 here because the generated URL
/user/avatar/user-name/0
is more beautiful than/user/avatar/user-name/-1
@ -0,0 +102,4 @@
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
}
return lowerEmail, nil
@delvh just searched a while, I think we use
setting.AppSubURL + "/user/avatar/" + userName + "/" + strconv.Itoa(size)
can be better here. I am not sure aboutshould we use AppURL or StaticURLPrefix
. Anyway, it just works as before now.Now I removed the useless constant
DefaultAvatarSize
. Only0
.I don't agree to lowering this because it creates different caching behaviour of local vs. remote (Gravatar) avatars. Local avatars don't hit this code path so are still subject to
setting.StaticCacheTime
.I think we should introduce a new config option for avatar cache time (default 5 minutes), which should apply to both this redirect and the cache headers of local avatars.
It doesn't create different caching behavior of local vs. remote (Gravatar) avatars, because we can not control or can not depend on Gravatar's cache behavior, so the difference is not important at all.
5 minutes is still too long. Why should we make a user can't see his new avatar in 5 minutes? And I do not think we should introduce so many config options, it only makes users more confused.
The
cacheableRedirect
was just introduced recently, there is no evidence any user benefits from it. The original issue was not likely related to it, either. The server has worked correctly for a long time before, a one-minute cacheable redirection is already better than before, and won't make users confused too much. If the cahce is not a must, we can choose to remove thecacheableRedirect
and revert to the old behavior.But to be fair: How often do you change your avatar?
Once or twice a year? If at all?
So I can definitely understand caching it for a longer time.
If needed, the user can still force his cache to be cleared.
But the 302 request doesn't cost much, it's not necessary to pay much attention to a fast 302 request. And even more, with this refactor, most local avatar images are responded by a
final
URL, they do not need the 302 redirection anymore.The 302 redirection only occurs in some rare cases. So my first preference is to revert to the old behavior (302 without cache). Second preference is to make the 302 cache time not more than one minute (or 5 minutes at most ?). It's not worthy to introduce more config options.
Yes, we should get rid of this redirect, at least for the cases where the URL can be synchonously obtained, which is certainly possible for Gravatar, but not for some other federated services like libravatar.org, IIRC.
So Gravatar should just render
img src="<gravatar-url>"
. Is this the case after this refactor?I guess I'm fine with this short cache on the cases where redirect needs to stay. It's not like I'd use services like libravatar.org :)
Yes, in most cases user's Gravatar image will be rendered as
img src="<gravatar-url>"
, and user's custom avatar will be rendered asimg src="<real-local-avatars-url>"
.The only cases that our 302 redirection occurs:
/user/avatar/${name}/${size}
(currently no such case, there is no caller toGenerateUserAvatarFastLink
now, this function is for potential further cases)LibravatarService
is used, then we use/avatar/${hash}
I can not find more cases that need the 302 redirection. So the cases are rare enough.
@ -0,0 +100,4 @@
return nil
}); err != nil {
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
You're pointing to /user/avatar/:username/:size here so AppSubURL is the correct thing.
@ -0,0 +100,4 @@
return nil
}); err != nil {
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
might be better to extract this out to a function then you can return the result of this function at 144 and at 154.
That would allow you to simplify some of the logic above.
@ -0,0 +100,4 @@
return nil
}); err != nil {
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
But there is no caller to these codes now. It only works for gravatar-like URLs. The line 114 doesn't share the same logic as here.I think we can postpone the function extraction to next time when others need it?@ -0,0 +100,4 @@
return nil
}); err != nil {
// Seriously we don't care about any DB problems just return the lowerEmail - we expect the transaction to fail most of the time
return lowerEmail, nil
Oh, I know your meaning, just a minute ~~~
@ -0,0 +139,4 @@
// if final is false, it always uses a fast path.
func generateEmailAvatarLink(email string, size int, final bool) string {
email = strings.TrimSpace(email)
if email == "" {
I know of someone who wants to change that once he sees it 😉
@ -27,0 +33,4 @@
}
c++
}
return c
Yeah, I can see that, but maybe we should rename the
Formal
toOfficial
orStandard
.@ -27,1 +36,4 @@
return c
}
func TestHandleFileETagCache(t *testing.T) {
I wouldn't even check for
X-Gitea
,I would instead check only for
X-
as according to my knowledge any header starting with that is not standardized.You do not know if there will ever be a custom header that is not
X-Gitea
.Oh wait, I just noticed that this is a testing method where you can indeed influence what headers are being sent.
I guess you can then ignore this comment.
Isn't there a return missing here?
@ -27,0 +33,4 @@
}
c++
}
return c
I didn't use "standard" because we may want some customization in future, which contains our customized headers should be counted. It's just a personal preference, and this function just appears in the unit test privately, so I think this name doesn't matter much.
@ -27,1 +36,4 @@
return c
}
func TestHandleFileETagCache(t *testing.T) {
Yep, explained above.
fixed
Even though my approval won't count, here it is.