Files
quoter/docs/url-format.md
Untone b876564f4a 📚 Complete documentation overhaul
### New Documentation:
- **URL Format Guide**: Complete guide for image resizer URL patterns
- **Hybrid Architecture**: Vercel Edge + Quoter integration strategy
- **Updated How-it-works**: Comprehensive system architecture with diagrams
- **Enhanced Configuration**: Security settings, troubleshooting, Vercel integration

### Documentation Structure:
📋 Architecture & Principles:
- 🚀 How Quoter Works (detailed system architecture)
- 🔀 Hybrid Architecture (Vercel + Quoter best practices)
- 📐 URL Format (complete resizer URL guide)

🛡️ Security & Configuration:
- 🔒 Security & DDoS Protection (comprehensive guide)
- ⚙️ Configuration (updated with new settings)
- 🚀 Deployment & 📊 Monitoring

🎨 Integrations:
- Vercel OG Integration guides
- Edge Function examples

### Key Features Documented:
- Complete URL patterns for image resizing
- Security rate limiting configuration
- Hybrid upload (Quoter) + download (Vercel) strategy
- JWT validation and session management
- Multi-cloud storage (Storj + AWS fallback)
- Performance optimization techniques
- Production deployment strategies

All documentation is now production-ready and includes practical examples! 📖
2025-09-02 12:32:15 +03:00

7.5 KiB
Raw Blame History

📐 Формат URL для ресайзера изображений

Обзор

Quoter поддерживает автоматическое изменение размера изображений через URL параметры. Система автоматически генерирует миниатюры в предопределенных размерах и возвращает ближайший подходящий размер.

🎯 Поддерживаемые размеры

Предопределенные ширины

[10, 40, 110, 300, 600, 800, 1400] // пикселей по ширине
  • 10px - микро-превью
  • 40px - аватары, иконки
  • 110px - маленькие превью
  • 300px - средние превью
  • 600px - стандартные изображения
  • 800px - большие изображения
  • 1400px - максимальный размер

📝 Синтаксис URL

1. Современный формат (рекомендуется)

GET /{filename}_{width}.{extension}

Примеры:

# Запрос изображения шириной 300px
GET /439efaa0-816f-11ef-b201-439da98539bc_300.jpg

# Запрос изображения шириной 600px
GET /5627e002-0c53-11ee-9565-0242ac110006_600.png

# Запрос оригинального размера (без ресайза)
GET /439efaa0-816f-11ef-b201-439da98539bc.jpg

2. Legacy формат (поддерживается)

GET /unsafe/{width}x/production/image/{filename}.{extension}

Примеры:

# Legacy формат с указанием ширины
GET /unsafe/1440x/production/image/439efaa0-816f-11ef-b201-439da98539bc.jpg

# Legacy формат без ресайза
GET /unsafe/production/image/5627e002-0c53-11ee-9565-0242ac110006.png

3. Конверсия формата

GET /{filename}.{extension}/webp

Примеры:

# Конверсия в WebP
GET /439efaa0-816f-11ef-b201-439da98539bc.jpg/webp

# Конверсия с ресайзом
GET /439efaa0-816f-11ef-b201-439da98539bc_600.jpg/webp

🔧 Логика обработки

Алгоритм выбора размера

  1. Точное совпадение: Если запрошенная ширина есть в предопределенных размерах
  2. Ближайший размер: Выбирается размер с минимальной разностью
  3. Максимальный лимит: Если запрошенная ширина > 1400px, возвращается 1400px
  4. Оригинал: Если ширина не указана (0), возвращается оригинальное изображение

Примеры выбора размера

# Запрос 150px → вернет 110px (ближайший меньший)
# Запрос 250px → вернет 300px (ближайший больший)  
# Запрос 2000px → вернет 1400px (максимальный)
# Запрос 299px → вернет 300px (ближайший)
# Запрос 301px → вернет 300px (ближайший)

Генерация миниатюр

  • Lazy generation: Миниатюры создаются по первому запросу
  • Асинхронная обработка: Генерация происходит в фоне
  • Кэширование: Созданные миниатюры сохраняются в S3
  • Fallback: При отсутствии миниатюры возвращается оригинал

🎨 Поддерживаемые форматы

Входные форматы

  • JPEG (.jpg, .jpeg)
  • PNG (.png)
  • GIF (.gif)
  • WebP (.webp)
  • HEIC (.heic, .heif) - конвертируется в JPEG
  • TIFF (.tiff, .tif) - конвертируется в JPEG

Выходные форматы

  • Сохраняется исходный формат (кроме HEIC/TIFF → JPEG)
  • WebP конверсия через /webp суффикс
  • Автоматическая оптимизация для web

🚀 HTTP заголовки

Кэширование

ETag: "filename.ext"
Cache-Control: public, max-age=31536000, immutable
Access-Control-Allow-Origin: *

Условные запросы

# Клиент отправляет
If-None-Match: "filename.ext"

# Сервер отвечает (если не изменено)
HTTP/1.1 304 Not Modified

💡 Оптимизация производительности

Клиентская оптимизация

<!-- Используйте srcset для разных размеров -->
<img src="/image_600.jpg" 
     srcset="/image_300.jpg 300w, 
             /image_600.jpg 600w, 
             /image_800.jpg 800w"
     sizes="(max-width: 600px) 300px, 600px"
     alt="Описание">

<!-- WebP с fallback -->
<picture>
  <source srcset="/image_600.jpg/webp" type="image/webp">
  <img src="/image_600.jpg" alt="Описание">
</picture>

API использование

// Функция для получения оптимального URL
function getImageUrl(filename, maxWidth) {
  const sizes = [10, 40, 110, 300, 600, 800, 1400];
  const optimalSize = sizes.find(size => size >= maxWidth) || 1400;
  
  const [name, ext] = filename.split('.');
  return `https://files.dscrs.site/${name}_${optimalSize}.${ext}`;
}

// Примеры использования
const thumbUrl = getImageUrl('image.jpg', 300);    // image_300.jpg
const fullUrl = getImageUrl('image.jpg', 1200);    // image_1400.jpg

🔍 Мониторинг и отладка

Логи сервера

# Успешная обработка
INFO  GET image_300.jpg [START]
INFO  Parsed request - base: image, width: 300, ext: jpg
INFO  Cache hit for image.jpg, returning 304

# Генерация миниатюры
WARN  Thumbnail not found, generating: image_300.jpg
WARN  generate new thumb files: image.jpg
INFO  Generated thumbnail: image_300.jpg

Проверка через API

# Проверка существования файла
curl -I https://files.dscrs.site/image_300.jpg

# Проверка с условным запросом
curl -H "If-None-Match: \"image.jpg\"" https://files.dscrs.site/image_300.jpg

⚠️ Ограничения и рекомендации

Лимиты

  • Максимальная ширина: 1400px
  • Поддерживаемые форматы: см. список выше
  • Размер файла: до 500MB для загрузки

Рекомендации

  1. Используйте WebP для лучшего сжатия
  2. Кэшируйте на CDN для лучшей производительности
  3. Указывайте размеры заранее для избежания layout shift
  4. Используйте lazy loading для изображений вне viewport

Troubleshooting

# Если изображение не отображается
1. Проверьте формат файла (поддерживается ли)
2. Проверьте размер запроса (не превышает ли лимиты)
3. Проверьте логи сервера на ошибки генерации
4. Убедитесь в корректности URL формата