# Гайд использования Руководство по кейсам — копируй, вставляй, проверяй. Без обдумывания. ## 1. Запуск ```bash cp .env.example .env docker compose -f docker-compose.dev.yml up -d --build ``` Проверка: ```bash curl -s -o /dev/null -w "%{http_code}" \ "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" # → 200 ``` ## 2. Обработка изображений ### Resize — вписать в ширину 800px ```bash curl -s -o /tmp/fit800.jpg \ "http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://picsum.photos/1200/800" # → файл /tmp/fit800.jpg, ширина = 800px ``` ### Resize — вписать в квадрат 200x200 ```bash curl -s -o /tmp/fit200.jpg \ "http://localhost:8888/unsafe/resize:fit:200:200:0/q:80/plain/https://picsum.photos/1200/800" # → файл 200x?, пропорции сохранены ``` ### Resize — заполнить 400x300 (с обрезкой) ```bash curl -s -o /tmp/fill400.jpg \ "http://localhost:8888/unsafe/resize:fill:400:300:0/g:ce/q:80/plain/https://picsum.photos/1200/800" # → файл точно 400x300, лишнее обрезано по центру ``` ### Crop — обрезка 200x200 ```bash curl -s -o /tmp/crop200.jpg \ "http://localhost:8888/unsafe/crop:200:200/plain/https://picsum.photos/1200/800" # → файл 200x200 ``` ### WebP — конвертация формата ```bash curl -s -D - -o /tmp/webp.webp \ "http://localhost:8888/unsafe/format:webp/q:80/plain/https://picsum.photos/800/600" \ 2>&1 | grep Content-Type # → Content-Type: image/webp ``` ### AVIF ```bash curl -s -D - -o /tmp/avif.avif \ "http://localhost:8888/unsafe/format:avif/q:80/plain/https://picsum.photos/800/600" \ 2>&1 | grep Content-Type # → Content-Type: image/avif ``` ### Качество — сравнить q:10 vs q:100 ```bash curl -s -o /tmp/q10.jpg \ "http://localhost:8888/unsafe/resize:fit:400:0:0/q:10/plain/https://picsum.photos/800/600" curl -s -o /tmp/q100.jpg \ "http://localhost:8888/unsafe/resize:fit:400:0:0/q:100/plain/https://picsum.photos/800/600" ls -la /tmp/q10.jpg /tmp/q100.jpg # → q10 ~4KB, q100 ~50KB — разница ~12x ``` ### Комбинированные — resize + WebP + качество ```bash curl -s -o /tmp/combined.webp \ "http://localhost:8888/unsafe/resize:fit:800:0:0/g:ce/q:75/format:webp/plain/https://picsum.photos/1200/800" # → 800px по ширине, WebP, качество 75 ``` ### base64url — закодированный source URL ```bash B64=$(echo -n "https://picsum.photos/800/600" | base64 -w0 | tr '+/' '-_' | tr -d '=') curl -s -o /tmp/b64.jpg "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/$B64" # → работает как plain/, но без /plain/ префикса ``` ## 3. Кеширование ### MISS → HIT — базовая проверка ```bash URL="http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/400/300" # Первый запрос — MISS (обработка через imgproxy) curl -s -o /dev/null -D - -w "\ntime: %{time_total}s\n" "$URL" | grep -E "Cache-Status|time" # → Cache-Status: Souin; fwd=uri-miss; stored # → time: 0.5s # Второй запрос — HIT (из кеша) curl -s -o /dev/null -D - -w "\ntime: %{time_total}s\n" "$URL" | grep -E "Cache-Status|time" # → Cache-Status: Souin; hit; ttl=31535999; detail=DEFAULT # → time: 0.001s ``` ### Что значит Cache-Status ``` Cache-Status: Souin; hit; ... → из кеша Cache-Status: Souin; fwd=uri-miss; stored; key=GET-... → первый запрос, закешировано Cache-Status: Souin; fwd=uri-miss; detail=UNCACHEABLE-... → не закешировано (ошибка upstream) ``` ### Разные размеры = разные ключи ```bash SRC="https://picsum.photos/id/42/800/600" curl -s -o /dev/null "http://localhost:8888/unsafe/resize:fit:200:0:0/q:80/plain/$SRC" curl -s -o /dev/null "http://localhost:8888/unsafe/resize:fit:400:0:0/q:80/plain/$SRC" curl -s "http://localhost:2019/souin-api/souin/" # → 2 ключа: ...resize:fit:200... и ...resize:fit:400... ``` ## 4. Purge кеша > Все purge-запросы идут через Caddy Admin API на порту **2019**. ### Purge — сбросить всё ```bash # Закешировать curl -s -o /dev/null "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/400/300" # Purge curl -s -w "status: %{http_code}\n" -X PURGE http://localhost:2019/souin-api/souin/flush # → status: 204 # Проверить — снова MISS curl -s -o /dev/null -D - "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/400/300" \ | grep Cache-Status # → Cache-Status: Souin; fwd=uri-miss; stored ``` ### Purge — конкретное изображение (все размеры) ```bash # Закешировать 2 размера SRC="https://picsum.photos/id/77/800/600" curl -s -o /dev/null "http://localhost:8888/unsafe/resize:fit:200:0:0/q:80/plain/$SRC" curl -s -o /dev/null "http://localhost:8888/unsafe/resize:fit:400:0:0/q:80/plain/$SRC" # Purge по regex (id/77) curl -s -w "status: %{http_code}\n" -X PURGE "http://localhost:2019/souin-api/souin/.*id/77.*" # → status: 204 # Оба размера сброшены ``` ### Purge — конкретный размер ```bash curl -s -w "status: %{http_code}\n" -X PURGE \ "http://localhost:2019/souin-api/souin/.*resize:fit:200.*id/77.*$" # → status: 204 — только 200px сброшен, 400px остался ``` ## 5. Caddy Admin API (Souin) Порт **2019**, только localhost. ### Список закешированных ключей ```bash curl -s http://localhost:2019/souin-api/souin/ # → ["GET-http-localhost:8888-/unsafe/resize:fit:200:0:0/q:80/plain/https://..."] ``` ### Purge — все методы ```bash # Полный сброс curl -X PURGE http://localhost:2019/souin-api/souin/flush # → 204 # По regex curl -X PURGE "http://localhost:2019/souin-api/souin/.*example.com/photo.jpg" # → 204 # Точное совпадение (с $ в конце) curl -X PURGE "http://localhost:2019/souin-api/souin/.*resize:fit:800.*photo\.jpg$" # → 204 ``` ## 6. Signed vs Unsigned ### Unsigned — по умолчанию Ключи не заданы → `/unsafe/` работает: ```bash # С /unsafe/ → работает curl -s -o /dev/null -w "%{http_code}" \ "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" # → 200 # Без /unsafe/ → тоже работает (ключи не заданы, подпись не проверяется) curl -s -o /dev/null -w "%{http_code}" \ "http://localhost:8888/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" # → 200 ``` ### Signed — включить подпись 1. Сгенерировать ключи: ```bash openssl rand -hex 32 # → KEY openssl rand -hex 32 # → SALT ``` 2. Добавить в `.env`: ```env IMGPROXY_KEY=<сгенерированный_ключ> IMGPROXY_SALT=<сгенерированная_соль> ``` 3. Перезапустить: ```bash docker compose -f docker-compose.dev.yml restart imgproxy ``` 4. Проверить: ```bash # Без /unsafe/ и без подписи → ошибка curl -s -o /dev/null -w "%{http_code}" \ "http://localhost:8888/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" # → 403 # С /unsafe/ → тоже ошибка (ключи заданы, unsafe запрещён) curl -s -o /dev/null -w "%{http_code}" \ "http://localhost:8888/unsafe/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" # → 403 ``` 5. Подписать URL: ```bash KEY="<сгенерированный_ключ>" SALT="<сгенерированная_соль>" PATH_URL="/resize:fit:100:0:0/q:80/plain/https://picsum.photos/200/200" SIG=$(echo -n "$SALT" | xxd -r -p | openssl dgst -sha256 -hmac "$(echo -n "$KEY" | xxd -r -p)" -binary | base64 | tr '+/' '-_' | tr -d '=' | head -c 32) curl -s -o /dev/null -w "%{http_code}" "http://localhost:8888/${SIG}${PATH_URL}" # → 200 ``` 6. Вернуть unsigned — убрать ключи из `.env` и перезапустить.