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:
+25
-6
@@ -144,14 +144,19 @@ PG_PASSWORD=change_me
|
||||
PG_DATABASE=shared_album
|
||||
PG_SSLMODE=disable
|
||||
|
||||
# S3 (Garage)
|
||||
# S3 (Garage) - внутреннее хранилище, клиенту не раскрывается
|
||||
S3_ENDPOINT=http://s3.localnet:3900
|
||||
S3_REGION=garage
|
||||
S3_ACCESS_KEY=GKchange_me
|
||||
S3_SECRET_KEY=change_me
|
||||
S3_BUCKET=albums
|
||||
S3_USE_PATH_STYLE=true
|
||||
S3_PUBLIC_URL=http://s3.localnet:3900/albums
|
||||
|
||||
# Storage backend
|
||||
STORAGE_BACKEND=s3 # s3 (default) | fs (local filesystem)
|
||||
FS_ROOT=/var/lib/galo/objects # required when STORAGE_BACKEND=fs
|
||||
URL_SECRET=change_me # signs object URLs; falls back to JWT_SECRET
|
||||
OBJECT_URL_TTL=1h # lifetime of signed object URLs
|
||||
|
||||
# Auth
|
||||
JWT_SECRET=change_me_long_random
|
||||
@@ -339,6 +344,11 @@ colors: {
|
||||
|
||||
## 10. Слой хранения и слой метаданных
|
||||
|
||||
**Слой хранения выбирается параметром `STORAGE_BACKEND`:** `s3` (S3-совместимое
|
||||
хранилище, по умолчанию) или `fs` (локальная файловая система, `FS_ROOT`). Оба
|
||||
бэкенда реализуют единый интерфейс `storage.Backend` и используют одни и те же
|
||||
непрозрачные ключи, поэтому переключение не меняет формат данных.
|
||||
|
||||
**S3 (Garage) — непрозрачное объектное хранилище.** Ключи не содержат сущностей
|
||||
метаданных (альбома, фото). Каждый физический файл адресуется своим `object_id`:
|
||||
|
||||
@@ -350,6 +360,11 @@ colors: {
|
||||
└── preview.webp
|
||||
```
|
||||
|
||||
При `STORAGE_BACKEND=fs` те же ключи отображаются в файлы под `FS_ROOT`. Отдача
|
||||
идёт через сам сервис: `GET /api/objects/<key>` с HMAC-подписью (`e`, `s`),
|
||||
поддержкой Range и Content-Type. Один и тот же маршрут обслуживает авторизованных
|
||||
пользователей и анонимные share-ссылки.
|
||||
|
||||
**Postgres — журнал истины.** Таблица `objects` описывает каждый блоб (ключ, mime,
|
||||
размер, габариты, checksum, состояние `pending|ready|deleting`), таблица
|
||||
`photo_objects` связывает фото с объектами по ролям (`original|thumb|preview`),
|
||||
@@ -358,13 +373,16 @@ colors: {
|
||||
|
||||
Следствия:
|
||||
- **Копирование** между альбомами — только новые строки `photos`+`photo_objects`,
|
||||
ссылающиеся на те же объекты; операции с S3 не выполняются.
|
||||
ссылающиеся на те же объекты; операции с хранилищем не выполняются.
|
||||
- **Перенос** — только `UPDATE photos.album_id`; объекты не трогаются.
|
||||
- **Удаление** фото удаляет строки; фоновый воркер удаляет блоб лишь когда на
|
||||
объект не осталось ни одной ссылки (сборка мусора по ledger-состояниям).
|
||||
|
||||
Доступ: **presigned URL** со сроком 1 час (бакет приватный).
|
||||
Garage поддерживает presigned URL через SigV4 query-string signatures.
|
||||
Доступ: **только через бэкенд** — подписанный URL со сроком 1 час на
|
||||
`/api/objects/<key>`, независимо от бэкенда хранилища. Для S3 (Garage) байты
|
||||
стримятся из внутренней сети через бэкенд (ranged `GetObject`), presigned URL наружу
|
||||
не выдаются; для ФС — чтение с диска. Переключение бэкенда не переносит существующие
|
||||
блобы — перенос выполняется вручную.
|
||||
|
||||
## 11. API-эндпоинты
|
||||
|
||||
@@ -609,7 +627,8 @@ invites, photos, comments, likes, notifications. Применяются к pg.lo
|
||||
Реализуй загрузку фото в Garage с генерацией трёх превью
|
||||
(thumb 200px, preview 1200px, original) и извлечением EXIF.
|
||||
Структура ключей: albums/{album_id}/{original|preview|thumb}/{photo_id}.{ext|webp}.
|
||||
Отдавай фото через presigned URL (срок 1 час).
|
||||
Отдавай фото через бэкенд: подписанный URL `/api/objects/<key>` (срок 1 час),
|
||||
S3-байты стримятся из внутренней сети через бэкенд.
|
||||
Эндпоинты загрузки, списка с cursor-пагинацией, удаления.
|
||||
На фронтенде — Uploader с drag&drop и прогрессом, PhotoGrid с ленивой загрузкой,
|
||||
Lightbox со свайпами.
|
||||
|
||||
Reference in New Issue
Block a user