feat(storage): serve media through backend and add local FS backend

- introduce storage.Backend with S3 and local file-system implementations
- deliver all blobs via signed GET/HEAD /api/objects/<key> (Range, Content-Type)
- stream S3 objects through the backend; remove presigned URL path
- share shared HMAC Signer between backends
- remove S3_PUBLIC_URL; rename S3_PRESIGN_TTL to OBJECT_URL_TTL
- make storage label in health dynamic; nginx proxy_buffering off for objects
This commit is contained in:
iu
2026-10-11 09:15:03 +03:00
parent 7ae9bcf305
commit ec8d907565
28 changed files with 1714 additions and 65 deletions
+4 -4
View File
@@ -21,10 +21,10 @@ type Service struct {
store *Store
members MemberLookup
hub *sse.Hub
storage *storage.Client
storage storage.Backend
}
func NewService(store *Store, members MemberLookup, hub *sse.Hub, storage *storage.Client) *Service {
func NewService(store *Store, members MemberLookup, hub *sse.Hub, storage storage.Backend) *Service {
return &Service{store: store, members: members, hub: hub, storage: storage}
}
@@ -61,12 +61,12 @@ func (s *Service) List(ctx context.Context, userID string) ([]models.Album, erro
return out, nil
}
// attachCover fills CoverThumbURL from the presigned thumbnail key, when present.
// attachCover fills CoverThumbURL from the signed thumbnail URL, when present.
func (s *Service) attachCover(ctx context.Context, a *models.Album) {
if s.storage == nil || a == nil || a.CoverThumbKey == "" {
return
}
if url, err := s.storage.PresignGet(ctx, a.CoverThumbKey); err == nil {
if url, err := s.storage.URL(ctx, a.CoverThumbKey); err == nil {
a.CoverThumbURL = url
}
}