Assets Proxy — Документація¶
Огляд¶
DAARION використовує MinIO (S3-compatible object storage) для зберігання assets (логотипи, банери, аватарки). Для доступу до assets без налаштування DNS для assets.daarion.space використовується Asset Proxy через city-service.
Архітектура¶
┌─────────────┐
│ Frontend │ → /api/city/assets/proxy/microdao/logo/...
└─────────────┘
│
↓
┌─────────────┐
│ city-service│ → /city/assets/proxy/{path}
│ (FastAPI) │
└─────────────┘
│
↓
┌─────────────┐
│ MinIO │ → daarion-assets/microdao/logo/...
│ (Docker) │
└─────────────┘
Контракт normalizeAssetUrl ↔ Asset Proxy¶
Вхідний URL з БД¶
https://assets.daarion.space/daarion-assets/microdao/logo/2025/12/02/abc123.png
Вихідний URL для фронта (після normalizeAssetUrl)¶
/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png
Шлях до MinIO (всередині proxy)¶
daarion-assets/microdao/logo/2025/12/02/abc123.png
Важливо: normalizeAssetUrl відрізає daarion-assets/ з URL, тому proxy отримує шлях без префіксу бакету. Proxy додає ASSETS_BUCKET автоматично.
Використання в компонентах¶
ЗАВЖДИ використовуйте normalizeAssetUrl для всіх asset URLs:
import { normalizeAssetUrl } from '@/lib/utils/assetUrl';
// ✅ ПРАВИЛЬНО
<img src={normalizeAssetUrl(logo_url)!} alt="Logo" />
// ❌ НЕПРАВИЛЬНО
<img src={logo_url} alt="Logo" />
Endpoint¶
City Service¶
- Path:
/city/assets/proxy/{path:path} - Method:
GET - Router prefix:
/city(монтується вmain.pyбез додаткового префіксу) - Повний URL:
/api/city/assets/proxy/{path}
Параметри¶
path— шлях до файлу в MinIO (без префіксу бакету)- Приклад:
microdao/logo/2025/12/02/abc123.png
Відповідь¶
- 200 OK — файл знайдено
Content-Type:image/png,image/jpeg, тощоCache-Control:public, max-age=86400, immutable-
Access-Control-Allow-Origin:* -
404 Not Found — файл не знайдено в MinIO
ENV змінні¶
City Service¶
MINIO_ENDPOINT=http://minio:9000
MINIO_ROOT_USER=assets-admin
MINIO_ROOT_PASSWORD=<password>
ASSETS_BUCKET=daarion-assets
ASSETS_PUBLIC_BASE_URL=https://assets.daarion.space/daarion-assets
Примітка: ASSETS_PUBLIC_BASE_URL використовується тільки для генерації URL при завантаженні. Для читання використовується proxy.
Приклади¶
Завантаження asset¶
from lib.assets_client import upload_asset
url = upload_asset(
file_obj,
content_type="image/png",
prefix="microdao/logo",
filename="logo.png"
)
# Повертає: https://assets.daarion.space/daarion-assets/microdao/logo/2025/12/02/abc123.png
Відображення asset на фронті¶
const logoUrl = "https://assets.daarion.space/daarion-assets/microdao/logo/2025/12/02/abc123.png";
const normalized = normalizeAssetUrl(logoUrl);
// normalized = "/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png"
<img src={normalized} alt="Logo" />
Troubleshooting¶
404 Not Found¶
-
Перевірте чи файл існує в MinIO:
bash docker exec daarion-minio mc ls minio/daarion-assets/microdao/logo/2025/12/02/ -
Перевірте чи правильний шлях передається в proxy:
bash curl -I "https://daarion.space/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png" -
Перевірте логи city-service:
bash docker logs daarion-city-service | grep "assets/proxy"
500 Internal Server Error¶
-
Перевірте ENV змінні в docker-compose:
bash docker exec daarion-city-service env | grep MINIO -
Перевірте чи MinIO доступний:
bash docker exec daarion-city-service curl -I http://minio:9000/minio/health/live
Assets не відображаються на фронті¶
- Перевірте чи компонент використовує
normalizeAssetUrl: ```typescript // ✅ ПРАВИЛЬНО src={normalizeAssetUrl(url)}
// ❌ НЕПРАВИЛЬНО src={url} ```
- Перевірте в DevTools Network tab:
- Чи запити йдуть на
/api/city/assets/proxy/...? - Який статус відповіді (200/404/500)?
Додавання нових компонентів¶
При додаванні нового компонента, який відображає assets:
-
Імпортуйте
normalizeAssetUrl:typescript import { normalizeAssetUrl } from '@/lib/utils/assetUrl'; -
Використовуйте для всіх asset URLs:
typescript <img src={normalizeAssetUrl(logo_url)!} alt="Logo" /> <div style={{ backgroundImage: `url(${normalizeAssetUrl(banner_url)})` }} /> -
НЕ використовуйте прямі URLs з БД без нормалізації.
Міграція зі старих URL¶
Якщо в БД є старі формати URL:
/static/uploads/logo.png→ автоматично конвертується в/api/static/uploads/logo.png/assets/logos/logo.png→ залишається як єhttps://assets.daarion.space/...→ конвертується в/api/city/assets/proxy/...
normalizeAssetUrl обробляє всі ці випадки автоматично.