diff --git a/pkg/cluster/routes/routes.go b/pkg/cluster/routes/routes.go index 79b18f1b..f4dc2640 100644 --- a/pkg/cluster/routes/routes.go +++ b/pkg/cluster/routes/routes.go @@ -203,11 +203,16 @@ func SlaveFileListRoute(srcPath string, recursive bool) string { return fmt.Sprintf("%s?%s", base, query.Encode()) } -func SlaveThumbUrl(base *url.URL, srcPath, ext string) *url.URL { +func SlaveThumbUrl(base *url.URL, srcPath, ext string, entityID int) *url.URL { srcPath = url.PathEscape(base64.URLEncoding.EncodeToString([]byte(srcPath))) ext = url.PathEscape(ext) route, _ := url.Parse(constants.APIPrefixSlave + fmt.Sprintf("/file/thumb/%s/%s", srcPath, ext)) base = base.ResolveReference(route) + if entityID > 0 { + query := base.Query() + query.Set("eid", strconv.Itoa(entityID)) + base.RawQuery = query.Encode() + } return base } diff --git a/pkg/filemanager/driver/remote/remote.go b/pkg/filemanager/driver/remote/remote.go index b7a762df..878d4352 100644 --- a/pkg/filemanager/driver/remote/remote.go +++ b/pkg/filemanager/driver/remote/remote.go @@ -98,7 +98,7 @@ func (handler *Driver) Thumb(ctx context.Context, expire *time.Time, ext string, return "", fmt.Errorf("parse server url failed: %w", err) } - thumbURL := routes.SlaveThumbUrl(serverURL, e.Source(), ext) + thumbURL := routes.SlaveThumbUrl(serverURL, e.Source(), ext, e.ID()) signedThumbURL, err := auth.SignURI(ctx, handler.AuthInstance, thumbURL.String(), expire) if err != nil { return "", err diff --git a/service/explorer/slave.go b/service/explorer/slave.go index c4335aff..40e26367 100644 --- a/service/explorer/slave.go +++ b/service/explorer/slave.go @@ -151,6 +151,9 @@ type ( SlaveThumbService struct { Src string `uri:"src" binding:"required"` Ext string `uri:"ext" binding:"required"` + // Eid optionally carries the entity ID of the requested blob so the + // slave can resolve encryption metadata from the shared DB (#3164). + Eid int `form:"eid"` } ) @@ -165,12 +168,32 @@ func (s *SlaveThumbService) Thumb(c *gin.Context) error { } settings := dep.SettingProvider() - var entity fs.Entity - entity, err = local.NewLocalFileEntity(types.EntityTypeThumbnail, string(src)+settings.ThumbSlaveSidecarSuffix(c)) + var ( + entity fs.Entity + srcEntity fs.Entity + ) + // Resolve the DB entity when the caller knows its ID: it carries the + // encryption metadata needed to serve/generate encrypted thumbnails. + if s.Eid > 0 { + if e, err := dep.FileClient().GetEntityByID(c, s.Eid); err == nil { + dbEntity := fs.NewEntity(e) + if dbEntity.Type() == types.EntityTypeThumbnail { + entity = dbEntity + } else { + srcEntity = dbEntity + } + } + } + + if entity == nil { + entity, err = local.NewLocalFileEntity(types.EntityTypeThumbnail, string(src)+settings.ThumbSlaveSidecarSuffix(c)) + } if err != nil { - srcEntity, err := local.NewLocalFileEntity(types.EntityTypeVersion, string(src)) - if err != nil { - return fs.ErrPathNotExist.WithError(err) + if srcEntity == nil { + srcEntity, err = local.NewLocalFileEntity(types.EntityTypeVersion, string(src)) + if err != nil { + return fs.ErrPathNotExist.WithError(err) + } } entity, err = m.SubmitAndAwaitThumbnailTask(c, nil, s.Ext, srcEntity)