- 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
199 lines
6.1 KiB
Markdown
199 lines
6.1 KiB
Markdown
# 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 з БД
|
||
|
||
```text
|
||
https://assets.daarion.space/daarion-assets/microdao/logo/2025/12/02/abc123.png
|
||
```
|
||
|
||
### Вихідний URL для фронта (після normalizeAssetUrl)
|
||
|
||
```text
|
||
/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png
|
||
```
|
||
|
||
### Шлях до MinIO (всередині proxy)
|
||
|
||
```text
|
||
daarion-assets/microdao/logo/2025/12/02/abc123.png
|
||
```
|
||
|
||
**Важливо:** `normalizeAssetUrl` відрізає `daarion-assets/` з URL, тому proxy отримує шлях без префіксу бакету. Proxy додає `ASSETS_BUCKET` автоматично.
|
||
|
||
## Використання в компонентах
|
||
|
||
**ЗАВЖДИ** використовуйте `normalizeAssetUrl` для всіх asset URLs:
|
||
|
||
```typescript
|
||
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
|
||
|
||
```env
|
||
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
|
||
|
||
```python
|
||
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 на фронті
|
||
|
||
```typescript
|
||
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
|
||
|
||
1. Перевірте чи файл існує в MinIO:
|
||
```bash
|
||
docker exec daarion-minio mc ls minio/daarion-assets/microdao/logo/2025/12/02/
|
||
```
|
||
|
||
2. Перевірте чи правильний шлях передається в proxy:
|
||
```bash
|
||
curl -I "https://daarion.space/api/city/assets/proxy/microdao/logo/2025/12/02/abc123.png"
|
||
```
|
||
|
||
3. Перевірте логи city-service:
|
||
```bash
|
||
docker logs daarion-city-service | grep "assets/proxy"
|
||
```
|
||
|
||
### 500 Internal Server Error
|
||
|
||
1. Перевірте ENV змінні в docker-compose:
|
||
```bash
|
||
docker exec daarion-city-service env | grep MINIO
|
||
```
|
||
|
||
2. Перевірте чи MinIO доступний:
|
||
```bash
|
||
docker exec daarion-city-service curl -I http://minio:9000/minio/health/live
|
||
```
|
||
|
||
### Assets не відображаються на фронті
|
||
|
||
1. Перевірте чи компонент використовує `normalizeAssetUrl`:
|
||
```typescript
|
||
// ✅ ПРАВИЛЬНО
|
||
src={normalizeAssetUrl(url)}
|
||
|
||
// ❌ НЕПРАВИЛЬНО
|
||
src={url}
|
||
```
|
||
|
||
2. Перевірте в DevTools Network tab:
|
||
- Чи запити йдуть на `/api/city/assets/proxy/...`?
|
||
- Який статус відповіді (200/404/500)?
|
||
|
||
## Додавання нових компонентів
|
||
|
||
При додаванні нового компонента, який відображає assets:
|
||
|
||
1. **Імпортуйте** `normalizeAssetUrl`:
|
||
```typescript
|
||
import { normalizeAssetUrl } from '@/lib/utils/assetUrl';
|
||
```
|
||
|
||
2. **Використовуйте** для всіх asset URLs:
|
||
```typescript
|
||
<img src={normalizeAssetUrl(logo_url)!} alt="Logo" />
|
||
<div style={{ backgroundImage: `url(${normalizeAssetUrl(banner_url)})` }} />
|
||
```
|
||
|
||
3. **НЕ використовуйте** прямі 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` обробляє всі ці випадки автоматично.
|
||
|