- добавлена сборка Caddy с Souin, Otter и NutsDB - добавлена конфигурация dev, prod и test Docker Compose - настроено кеширование через Otter L1 и NutsDB L2 - добавлены e2e-тесты Bun для кеша, restart и purge - добавлена документация по запуску, API кеша и тестам
160 lines
4.2 KiB
Markdown
160 lines
4.2 KiB
Markdown
# URL-справочник
|
||
|
||
## Формат URL
|
||
|
||
### Unsigned (по умолчанию)
|
||
|
||
```
|
||
/unsafe/{processing_options}/plain/{source_url}
|
||
```
|
||
|
||
### Signed
|
||
|
||
```
|
||
/{signature}/{processing_options}/plain/{source_url}
|
||
```
|
||
|
||
### Source URL
|
||
|
||
Два варианта кодирования source URL:
|
||
|
||
| Вариант | Пример |
|
||
|---|---|
|
||
| `plain/{url}` | `plain/https://example.com/photo.jpg` |
|
||
| `{base64url}` | `aHR0cHM6Ly9leGFtcGxlLmNvbS9waG90by5qcGc` |
|
||
|
||
## Processing options
|
||
|
||
### Resize
|
||
|
||
Вписать в размер (сохраняет пропорции, не увеличивает):
|
||
|
||
```
|
||
/unsafe/resize:fit:{width}:{height}:0/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
Заполнить размер (сохраняет пропорции, обрезает лишнее):
|
||
|
||
```
|
||
/unsafe/resize:fill:{width}:{height}:0/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
Точный размер (растягивает/сжимает):
|
||
|
||
```
|
||
/unsafe/resize:force:{width}:{height}:0/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
> `height:0` = автоопределение высоты по пропорциям.
|
||
|
||
### Crop
|
||
|
||
```
|
||
/unsafe/crop:{width}:{height}:0/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
### Качество
|
||
|
||
```
|
||
/unsafe/q:{1-100}/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
### Конвертация формата
|
||
|
||
Добавить расширение к source URL:
|
||
|
||
```
|
||
/unsafe/q:80/plain/https://example.com/photo.jpg.webp
|
||
/unsafe/q:80/plain/https://example.com/photo.jpg.avif
|
||
```
|
||
|
||
Поддерживаемые форматы: JPEG, PNG, WebP, AVIF, GIF, ICO, SVG, TIFF, HEIC
|
||
|
||
### Гравитация (для crop/fill)
|
||
|
||
```
|
||
/unsafe/resize:fill:400:300:0/g:ce/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
| Значение | Описание |
|
||
|---|---|
|
||
| `ce` | Центр (по умолчанию) |
|
||
| `no` | Верх |
|
||
| `so` | Низ |
|
||
| `ea` | Право |
|
||
| `we` | Лево |
|
||
| `noea` | Верх-право |
|
||
| `nowe` | Верх-лево |
|
||
| `soea` | Низ-право |
|
||
| `sowe` | Низ-лево |
|
||
|
||
### Автоопределение высоты
|
||
|
||
`height = 0` — imgproxy автоматически вычисляет высоту, сохраняя пропорции:
|
||
|
||
```
|
||
/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
## Примеры
|
||
|
||
### Вписать в 800px по ширине, качество 80
|
||
|
||
```
|
||
http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
### Превью 200x200, качество 60
|
||
|
||
```
|
||
http://localhost:8888/unsafe/resize:fill:200:200:0/g:ce/q:60/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
### Конвертация в WebP
|
||
|
||
```
|
||
http://localhost:8888/unsafe/q:80/plain/https://example.com/photo.jpg.webp
|
||
```
|
||
|
||
### Комбинированная обработка
|
||
|
||
```
|
||
http://localhost:8888/unsafe/resize:fit:1200:0:0/g:ce/q:75/plain/https://example.com/photo.jpg.webp
|
||
```
|
||
|
||
### Использование base64url
|
||
|
||
```bash
|
||
echo -n "https://example.com/photo.jpg" | base64 -w0 | tr '+/' '-_' | tr -d '='
|
||
# → aHR0cHM6Ly9leGFtcGxlLmNvbS9waG90by5qcGc
|
||
|
||
http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/aHR0cHM6Ly9leGFtcGxlLmNvbS9waG90by5qcGc
|
||
```
|
||
|
||
## Подпись URL (HMAC-SHA256)
|
||
|
||
Когда заданы `IMGPROXY_KEY` и `IMGPROXY_SALT`, каждый запрос должен быть подписан.
|
||
|
||
```ts
|
||
import crypto from 'crypto'
|
||
|
||
function signUrl(key: string, salt: string, path: string): string {
|
||
const hmac = crypto.createHmac('sha256', Buffer.from(key, 'hex'))
|
||
hmac.update(Buffer.from(salt, 'hex'))
|
||
hmac.update(path)
|
||
const signature = hmac.digest().slice(0, 32).toString('base64url')
|
||
return `/${signature}${path}`
|
||
}
|
||
|
||
// Использование:
|
||
const path = '/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg'
|
||
const url = signUrl(IMGPROXY_KEY, IMGPROXY_SALT, path)
|
||
// → /SIGNED_SIGNATURE/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg
|
||
```
|
||
|
||
> **Внимание:** В SPA-приложениях ключи подписи утекают в браузер. Рекомендуется использовать unsigned режим (`/unsafe/`) с `IMGPROXY_ALLOWED_SOURCES` для защиты.
|
||
|
||
## Справочник
|
||
|
||
Полная документация по параметрам обработки: [imgproxy.net/docs](https://imgproxy.net/docs/)
|