fix(avatars): always return correct mime type for cached avatar
This commit is contained in:
parent
2ead48c1e9
commit
734033c843
|
|
@ -32,6 +32,7 @@ import (
|
|||
|
||||
type avatar struct {
|
||||
content []byte
|
||||
mimeType string
|
||||
loadedAt time.Time
|
||||
}
|
||||
|
||||
|
|
@ -78,10 +79,18 @@ func (g *Provider) GetAvatar(user *user.User, size int64) ([]byte, string, error
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
// Determine the mime type from the response
|
||||
mimeType := "image/jpeg"
|
||||
if contentType := resp.Header.Get("Content-Type"); contentType != "" {
|
||||
mimeType = contentType
|
||||
}
|
||||
|
||||
avatars[cacheKey] = &avatar{
|
||||
content: avatarContent,
|
||||
mimeType: mimeType,
|
||||
loadedAt: time.Now(),
|
||||
}
|
||||
}
|
||||
return avatars[cacheKey].content, "image/jpg", nil
|
||||
return avatars[cacheKey].content, avatars[cacheKey].mimeType, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -151,36 +151,51 @@ func getAvatarForUser(u *user.User) (fullSizeAvatar *image.RGBA64, err error) {
|
|||
return fullSizeAvatar, nil
|
||||
}
|
||||
|
||||
// CachedAvatar represents a cached avatar with its content and mime type
|
||||
type CachedAvatar struct {
|
||||
Content []byte
|
||||
MimeType string
|
||||
}
|
||||
|
||||
// GetAvatar returns an initials avatar for a user
|
||||
func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType string, err error) {
|
||||
cacheKey := getCacheKey("resized", u.ID, size)
|
||||
|
||||
exists, err := keyvalue.GetWithValue(cacheKey, &avatar)
|
||||
var cachedAvatar CachedAvatar
|
||||
exists, err := keyvalue.GetWithValue(cacheKey, &cachedAvatar)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
if !exists {
|
||||
log.Debugf("Initials avatar for user %d and size %d not cached, creating...", u.ID, size)
|
||||
fullAvatar, err := getAvatarForUser(u)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
img := imaging.Resize(fullAvatar, int(size), int(size), imaging.Lanczos)
|
||||
buf := &bytes.Buffer{}
|
||||
err = png.Encode(buf, img)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
avatar = buf.Bytes()
|
||||
err = keyvalue.Put(cacheKey, avatar)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
} else {
|
||||
if exists && len(cachedAvatar.Content) > 0 {
|
||||
log.Debugf("Serving initials avatar for user %d and size %d from cache", u.ID, size)
|
||||
return cachedAvatar.Content, cachedAvatar.MimeType, nil
|
||||
}
|
||||
|
||||
return avatar, "image/png", nil
|
||||
log.Debugf("Initials avatar for user %d and size %d not cached, creating...", u.ID, size)
|
||||
fullAvatar, err := getAvatarForUser(u)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
img := imaging.Resize(fullAvatar, int(size), int(size), imaging.Lanczos)
|
||||
buf := &bytes.Buffer{}
|
||||
err = png.Encode(buf, img)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
avatar = buf.Bytes()
|
||||
mimeType = "image/png"
|
||||
|
||||
cachedAvatar = CachedAvatar{
|
||||
Content: avatar,
|
||||
MimeType: mimeType,
|
||||
}
|
||||
|
||||
err = keyvalue.Put(cacheKey, cachedAvatar)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return avatar, mimeType, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,12 +35,18 @@ import (
|
|||
type Provider struct {
|
||||
}
|
||||
|
||||
// CachedAvatar represents a cached avatar with its content and mime type
|
||||
type CachedAvatar struct {
|
||||
Content []byte
|
||||
MimeType string
|
||||
}
|
||||
|
||||
// GetAvatar returns an uploaded user avatar
|
||||
func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType string, err error) {
|
||||
|
||||
cacheKey := "avatar_upload_" + strconv.Itoa(int(u.ID))
|
||||
|
||||
var cached map[int64][]byte
|
||||
var cached map[int64]*CachedAvatar
|
||||
exists, err := keyvalue.GetWithValue(cacheKey, &cached)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
|
@ -48,16 +54,16 @@ func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType
|
|||
|
||||
if !exists {
|
||||
// Nothing ever cached for this user so we need to create the size map to avoid panics
|
||||
cached = make(map[int64][]byte)
|
||||
cached = make(map[int64]*CachedAvatar)
|
||||
} else {
|
||||
a := cached
|
||||
if a != nil && a[size] != nil {
|
||||
log.Debugf("Serving uploaded avatar for user %d and size %d from cache.", u.ID, size)
|
||||
return a[size], "", nil
|
||||
return a[size].Content, a[size].MimeType, nil
|
||||
}
|
||||
// This means we have a map for the user, but nothing in it.
|
||||
if a == nil {
|
||||
cached = make(map[int64][]byte)
|
||||
cached = make(map[int64]*CachedAvatar)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -87,9 +93,16 @@ func (p *Provider) GetAvatar(u *user.User, size int64) (avatar []byte, mimeType
|
|||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
cached[size] = avatar
|
||||
|
||||
// Always use image/png for resized avatars since we're encoding with png
|
||||
mimeType = "image/png"
|
||||
cached[size] = &CachedAvatar{
|
||||
Content: avatar,
|
||||
MimeType: mimeType,
|
||||
}
|
||||
|
||||
err = keyvalue.Put(cacheKey, cached)
|
||||
return avatar, f.Mime, err
|
||||
return avatar, mimeType, err
|
||||
}
|
||||
|
||||
// InvalidateCache invalidates the avatar cache for a user
|
||||
|
|
|
|||
Loading…
Reference in New Issue