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 или напрямую
|