Skip to content

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

  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} ```

  1. Перевірте в DevTools Network tab:
  2. Чи запити йдуть на /api/city/assets/proxy/...?
  3. Який статус відповіді (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 обробляє всі ці випадки автоматично.