- добавлена сборка Caddy с Souin, Otter и NutsDB - добавлена конфигурация dev, prod и test Docker Compose - настроено кеширование через Otter L1 и NutsDB L2 - добавлены e2e-тесты Bun для кеша, restart и purge - добавлена документация по запуску, API кеша и тестам
93 lines
4.1 KiB
Markdown
93 lines
4.1 KiB
Markdown
# Обзор проекта
|
||
|
||
## Что это
|
||
|
||
Image Gateway — self-hosted сервер для обработки и кеширования изображений. Принимает URL оригинального изображения, изменяет размер/формат/качество по запросу, кеширует результат и отдаёт быстро.
|
||
|
||
## Зачем
|
||
|
||
- **Оптимизация изображений** — автоматический resize, crop, конвертация в WebP/AVIF
|
||
- **Кеширование** — однократная обработка, последующие запросы отдаются из кеша за ~1ms
|
||
- **Самостоятельный хостинг** — нет зависимости от внешних SaaS-сервисов (Cloudinary, imgix и т.д.)
|
||
- **Простая интеграция** — URL-based API, совместимое с `next/image`, `<img>` и любым HTTP-клиентом
|
||
|
||
## Архитектура
|
||
|
||
```
|
||
Клиент → Caddy (:8888)
|
||
├─ HIT: отдаёт из кеша (~1ms)
|
||
└─ MISS: → imgproxy → скачивает оригинал → обработка → ответ + кеширование
|
||
```
|
||
|
||
### Компоненты
|
||
|
||
| Компонент | Роль |
|
||
|---|---|
|
||
| **Caddy** | Reverse proxy, кеширование (Souin plugin), HTTPS |
|
||
| **imgproxy** | Обработка изображений (resize, crop, конвертация форматов, качество) |
|
||
|
||
### Маршрутизация
|
||
|
||
```
|
||
Caddy (:8888)
|
||
├─ /* → imgproxy (через кеш Souin)
|
||
└─ /souin-api/* → Souin API (управление кешем)
|
||
```
|
||
|
||
## Возможности
|
||
|
||
### Обработка изображений (imgproxy)
|
||
|
||
- **Resize** — вписать (`fit`), заполнить (`fill`), точный размер (`force`)
|
||
- **Crop** — обрезка с указанием ширины/высоты
|
||
- **Конвертация форматов** — JPEG, PNG, WebP, AVIF, GIF
|
||
- **Качество** — от 1 до 100
|
||
- **Гравитация** — `ce` (центр), `no` (север), `ea` (восток), и т.д.
|
||
- **Подпись URL** — HMAC-SHA256 для защиты от несанкционированного использования
|
||
- **Whitelist доменов** — ограничение источников изображений через `IMGPROXY_ALLOWED_SOURCES`
|
||
|
||
### Кеширование (Souin)
|
||
|
||
- Кеширует обработанные изображения в памяти
|
||
- TTL по умолчанию — 1 год (определяется `Cache-Control` от imgproxy)
|
||
- HTTP-заголовок `Cache-Status` в каждом ответе — `hit` или `miss`
|
||
- API для программного сброса кеша (`/souin-api/souin/`)
|
||
|
||
### Режимы работы
|
||
|
||
| Режим | Описание | Защита |
|
||
|---|---|---|
|
||
| **Unsigned** | URL с префиксом `/unsafe/` | Whitelist доменов (`IMGPROXY_ALLOWED_SOURCES`) |
|
||
| **Signed** | URL с HMAC-SHA256 подписью | Подпись + whitelist |
|
||
|
||
Unsigned режим рекомендуется для SPA-приложений — ключи подписи не утекают в браузер.
|
||
|
||
## Интеграция
|
||
|
||
### HTML
|
||
|
||
```html
|
||
<img src="http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg" />
|
||
```
|
||
|
||
### Next.js (loader)
|
||
|
||
```ts
|
||
const imageGatewayLoader = ({ src, width, quality }) => {
|
||
const q = quality ?? 80
|
||
return `http://localhost:8888/unsafe/resize:fit:${width}:0:0/q:${q}/plain/${src}`
|
||
}
|
||
```
|
||
|
||
### Любой HTTP-клиент
|
||
|
||
```
|
||
GET http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
## Что НЕ входит в проект
|
||
|
||
- Админ-панель — реализуется как внешний сервис (Next.js, SPA и т.д.)
|
||
- Хранилище оригиналов — проект только обрабатывает изображения по URL
|
||
- CDN-слой — проект работает за CDN или напрямую
|