- Add comprehensive documentation in docs/ASSETS_PROXY.md - Add contract comments in normalizeAssetUrl and proxy_asset - Verify all components use normalizeAssetUrl - Verify ENV variables are correctly set - Add troubleshooting guide
6.1 KiB
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, immutableAccess-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:
docker exec daarion-minio mc ls minio/daarion-assets/microdao/logo/2025/12/02/ -
Перевірте чи правильний шлях передається в proxy:
curl -I "https://daarion.space/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png" -
Перевірте логи city-service:
docker logs daarion-city-service | grep "assets/proxy"
500 Internal Server Error
-
Перевірте ENV змінні в docker-compose:
docker exec daarion-city-service env | grep MINIO -
Перевірте чи MinIO доступний:
docker exec daarion-city-service curl -I http://minio:9000/minio/health/live
Assets не відображаються на фронті
-
Перевірте чи компонент використовує
normalizeAssetUrl:// ✅ ПРАВИЛЬНО src={normalizeAssetUrl(url)} // ❌ НЕПРАВИЛЬНО src={url} -
Перевірте в DevTools Network tab:
- Чи запити йдуть на
/api/city/assets/proxy/...? - Який статус відповіді (200/404/500)?
- Чи запити йдуть на
Додавання нових компонентів
При додаванні нового компонента, який відображає assets:
-
Імпортуйте
normalizeAssetUrl:import { normalizeAssetUrl } from '@/lib/utils/assetUrl'; -
Використовуйте для всіх asset URLs:
<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 обробляє всі ці випадки автоматично.