# API кеша (Souin) ## Обзор Кеширование реализовано через Souin plugin для Caddy. Обработанные изображения кешируются с TTL = 1 год. Souin API доступен через **Caddy admin API** (порт 2019). Это отдельный endpoint, не доступный извне через основной порт. ## Заголовки ### Cache-Status Каждый ответ содержит заголовок `Cache-Status`: ``` Cache-Status: Souin; hit; ttl=31535999; key=GET-...; detail=DEFAULT ``` | Значение | Описание | |---|---| | `hit` | Ответ из кеша | | `fwd=uri-miss; stored` | Первый запрос, результат закеширован | | `fwd=uri-miss; detail=UNCACHEABLE-*` | Запрос не может быть закеширован | ### Cache-Control imgproxy возвращает: ``` Cache-Control: max-age=31536000, public ``` Souin использует этот заголовок для определения TTL. ## Souin API API доступно через Caddy admin API на порту `2019`. ### Список закешированных ключей ```bash curl http://localhost:2019/souin-api/souin/ ``` Ответ — JSON-массив ключей: ```json [ "GET-http-localhost:8888-/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg", "GET-http-localhost:8888-/unsafe/resize:fit:200:0:0/q:60/plain/https://example.com/photo.jpg" ] ``` ### Purge по ключу (regex) ```bash curl -X PURGE "http://localhost:2019/souin-api/souin/.*example.com/photo.jpg" ``` `regex` — регулярное выражение для поиска ключей кеша. Используйте `$` в конце для точного совпадения. Примеры: ```bash # Purge конкретного размера curl -X PURGE "http://localhost:2019/souin-api/souin/.*resize:fit:800.*photo\.jpg$" # Purge всех вариантов одного изображения curl -X PURGE "http://localhost:2019/souin-api/souin/.*example.com/photo.jpg" # Purge всех изображений домена curl -X PURGE "http://localhost:2019/souin-api/souin/.*example\.com.*" ``` Ответ: `204 No Content` — успешно. ### Purge всего кеша ```bash curl -X PURGE http://localhost:2019/souin-api/souin/flush ``` Ответ: `204 No Content` — успешно. ## Формат ключа кеша Souin формирует ключ кеша из HTTP-метода, схемы, хоста и пути: ``` {METHOD}-{scheme}-{host}:{port}-{path} ``` Пример: ``` GET-http-localhost:8888-/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg ``` При purge по regex ищите совпадение по частям пути. ## Примеры использования ### curl ```bash # Закешировать изображение curl -s -o /dev/null -w "status: %{http_code}, time: %{time_total}s\n" \ "http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg" # → status: 200, time: 0.570s (MISS) # Повторный запрос curl -s -o /dev/null -w "status: %{http_code}, time: %{time_total}s\n" \ "http://localhost:8888/unsafe/resize:fit:800:0:0/q:80/plain/https://example.com/photo.jpg" # → status: 200, time: 0.001s (HIT) # Purge curl -X PURGE "http://localhost:2019/souin-api/souin/.*example.com/photo.jpg" ``` ### JavaScript ```ts async function purgeCache(imageUrl: string) { const response = await fetch( `http://localhost:2019/souin-api/souin/.*${escapeRegex(imageUrl)}`, { method: 'PURGE' } ) return response.ok } function escapeRegex(str: string): string { return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') } ``` ## Безопасность Caddy admin API по умолчанию доступен только на `localhost:2019`. В production: - Порт 2019 не должен быть открыт наружу - Можно настроить `admin off` в Caddyfile и использовать альтернативный доступ - Или ограничить через firewall ## Ограничения - **In-memory storage** — по умолчанию кеш хранится в памяти. При перезапуске Caddy кеш теряется - Для production рекомендуется подключить дисковый storage (Badger, NutsDB) через дополнительный плагин