Files
quoter/docs/upload-api-detailed.md
Untone 6c3262edbe
Some checks failed
Deploy / deploy (push) Has been skipped
CI / lint (push) Failing after 8s
CI / test (push) Failing after 3m57s
simpler-auth+no-overlay
2025-09-01 20:36:15 +03:00

10 KiB
Raw Blame History

📤 API загрузки файлов с квотами - Точная документация

Обзор

Quoter предоставляет API для загрузки файлов с системой квот и автоматической обработкой различных типов медиа.

Базовый URL

http://localhost:8080

Аутентификация

Все эндпоинты загрузки требуют JWT токен в заголовке:

Authorization: Bearer <jwt-token>

📤 Загрузка файлов (УЛУЧШЕННАЯ ВЕРСИЯ)

POST /

Загружает файл(ы) в S3-совместимое хранилище (Storj) с улучшенной проверкой квот и валидацией.

Заголовки запроса

Authorization: Bearer <jwt-token>
Content-Type: multipart/form-data

Параметры

  • file (required) - файл(ы) для загрузки в multipart/form-data

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

Автоматическое определение MIME-типа из содержимого файла:

  • Изображения: JPEG, PNG, GIF, WebP, HEIC
  • Видео: MP4, WebM, AVI
  • Аудио: MP3, WAV, OGG
  • Документы: PDF

🔄 Улучшенная логика обработки

  1. Проверка авторизации - извлечение и валидация JWT токена
  2. Получение текущей квоты пользователя из Redis
  3. Предварительная проверка квоты - пользователь не достиг лимита
  4. Streaming чтение файла с проверками на каждом chunk:
    • Проверка лимита одного файла (500 МБ)
    • Проверка общей квоты пользователя
  5. Пропуск пустых файлов
  6. Определение MIME-типа из содержимого (не из расширения!)
  7. Генерация UUID имени файла с правильным расширением
  8. Загрузка в Storj S3
  9. Обновление квоты пользователя
  10. Сохранение метаданных в Redis (с обработкой ошибок)

Ограничения

  • Максимальная квота на пользователя: 5 ГБ (5,368,709,120 байт)
  • Максимальный размер одного файла: 500 МБ (524,288,000 байт)
  • Проверка квоты происходит во время чтения (streaming)
  • Поддержка множественных файлов в одном запросе

Успешные ответы

Один файл:

HTTP/1.1 200 OK
Content-Type: text/plain

uuid-filename.ext

Несколько файлов:

HTTP/1.1 200 OK
Content-Type: application/json

{
  "uploaded_files": ["uuid1.jpg", "uuid2.png"],
  "count": 2
}

Коды ошибок (ИСПРАВЛЕННЫЕ)

Код Условие Описание
400 Bad Request Нет файлов "No files provided or all files were empty"
401 Unauthorized Отсутствует токен "Authorization token required"
401 Unauthorized Неверный токен "Invalid authorization token"
413 Payload Too Large 🎯 Превышена квота "Author quota limit exceeded"
413 Payload Too Large 🎯 Большой файл "Single file size limit exceeded"
413 Payload Too Large 🎯 Превышение при загрузке "Author quota limit would be exceeded"
415 Unsupported Media Type Неподдерживаемый MIME "Unsupported file format"
415 Unsupported Media Type Нет расширения для MIME "Unsupported content type"
500 Internal Server Error Ошибка S3 "File upload failed"
500 Internal Server Error Ошибка квоты "Failed to update user quota"

Исправленные проблемы

  1. Правильный код ошибки для квоты: 413 Payload Too Large
  2. Efficient memory usage: streaming с проверками на каждом chunk
  3. Предварительная проверка квоты перед началом загрузки
  4. Лимит размера одного файла: 500 МБ
  5. Улучшенная обработка ошибок с детальными сообщениями
  6. Поддержка множественных файлов в одном запросе
  7. Детальное логирование с процентом использования квоты

🔄 Как это работает

  1. JWT декодирование - извлекается user_id из токена
  2. Redis lookup - опциональный поиск сессии по ключу session:{user_id}:{token}
  3. Quota lookup - получение квоты по ключу quota:{user_id} из Redis
  4. Activity update - обновление last_activity timestamp (если сессия найдена)
  5. Response building - объединение данных пользователя и квоты

Заголовки запроса

Authorization: Bearer <jwt-token>

Успешный ответ

HTTP/1.1 200 OK
Content-Type: application/json

{
  "user_id": "user_12345",
  "username": "john_doe",
  "token_type": "session",
  "created_at": "1642248600",
  "last_activity": "1642335000",
  "auth_data": "{\"roles\": [\"user\"], \"permissions\": [...]}",
  "device_info": "{\"platform\": \"web\", \"browser\": \"Chrome\"}",
  "quota": {
    "current_quota": 1073741824,
    "max_quota": 5368709120,
    "usage_percentage": 20.0
  }
}

Поля ответа

Поле Тип Описание
user_id string Уникальный ID пользователя
username string | null Имя пользователя
token_type string | null Тип токена (обычно "session")
created_at string | null Unix timestamp создания сессии
last_activity string | null Unix timestamp последней активности
auth_data string | null JSON-строка с данными авторизации
device_info string | null JSON-строка с информацией об устройстве
quota.current_quota number Текущее использование квоты в байтах
quota.max_quota number Максимальная квота в байтах
quota.usage_percentage number Процент использования квоты

Коды ошибок

Код Условие Описание
401 Unauthorized Отсутствует токен "Authorization token required"
401 Unauthorized Неверный JWT "Invalid or expired session token"
401 Unauthorized Сессия не найдена "Session not found or expired"

Примеры использования

# Получение информации о текущем пользователе
curl -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
     http://localhost:8080/

📊 Управление квотами

GET /quota

Получает информацию о квоте пользователя.

Параметры запроса

GET /quota?user_id=<user_id>

Ответ

{
  "user_id": "user123",
  "current_quota": 1073741824,
  "max_quota": 5368709120
}

POST /quota/increase

Увеличивает квоту пользователя (admin-only).

Тело запроса

{
  "user_id": "user123",
  "additional_bytes": 1073741824
}

Валидация

  • additional_bytes должно быть > 0
  • Требуется админский токен

POST /quota/set

Устанавливает абсолютное значение квоты (admin-only).

Тело запроса

{
  "user_id": "user123", 
  "new_quota_bytes": 2147483648
}

🔍 Получение файлов

GET /{filename}

Возвращает файл по имени с возможными трансформациями.

Параметры URL

  • filename - имя файла или имя_размер.расширение для миниатюр

Query параметры

  • s=<shout_id> - добавляет оверлей с данными shout (только изображения)

Примеры

GET /uuid-file.jpg                    # Оригинальный файл
GET /uuid-file_300.jpg               # Миниатюра 300px
GET /uuid-file_300.jpg/webp          # Миниатюра в WebP
GET /uuid-file.jpg?s=123             # С оверлеем shout

🧪 Примеры использования

Загрузка файла

curl -X POST http://localhost:8080/ \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc..." \
  -F "file=@photo.jpg"

Ответ при успехе:

c4ca4238-a0b9-23f1-8429-81dc9bdb9a1f.jpg

Ответ при превышении квоты:

HTTP/1.1 401 Unauthorized
Quota exceeded

Проверка квоты

curl "http://localhost:8080/quota?user_id=user123" \
  -H "Authorization: Bearer admin-token"

Увеличение квоты (admin)

curl -X POST http://localhost:8080/quota/increase \
  -H "Authorization: Bearer admin-token" \
  -H "Content-Type: application/json" \
  -d '{"user_id": "user123", "additional_bytes": 1073741824}'

🔧 Рекомендации по улучшению

  1. Исправить код ошибки квоты: 401 → 413
  2. Добавить предварительную проверку размера из Content-Length
  3. Streaming загрузка вместо полного чтения в память
  4. Лимит размера одного файла
  5. Детальная валидация MIME-типов
  6. Метрики использования квот

Документация актуальна для версии кода на момент создания. Для изменений см. CHANGELOG.md.