Files
upload-platform/HISTORY/2026-09-06-layer2-implementation-and-tests.md
T

7.2 KiB
Raw Blame History

2026-09-06: Реализация и верификация Слоя 2 (пофайловый транзит через RAM)

1. Контекст задачи

В рамках репозитория upload-platform выполнена реализация Слоя 2 (транзитная доставка файлов в сессию бэкенда через внешний буфер) поверх завершённого Слоя 1 (File Picker v0.1.13) с поднятием версии платформы до 0.2.0.


2. Ключевые архитектурные решения и реализация

1. Пофайловый транзит (Per-File Transit)

Вместо накопления всей пачки файлов на ВМ реализован потоковый пофайловый цикл:

  1. Браузер берёт файл k и отправляет его методом PUT в буфер на ВМ (putToVm через XHR со стримингом прогресса и поддержкой AbortSignal).
  2. Браузер сразу делает POST /api/upload_refs только для этого одного файла k.
  3. Бэкенд забирает файл исходящим потоковым GET (httpx.stream) прямо в оперативную память сессии (upload/backend/session).
  4. Бэкенд немедленно отправляет DELETE на буфер ВМ.
  5. Файл на ВМ удалён, буфер чист. Браузер переходит к файлу k+1.
  • Результат: в буфере на ВМ в любой момент времени находится максимум один файл; объем потребляемой буфером памяти минимален.

2. Хранение строго в оперативной памяти (RAM-only)

  • На бэкенде: файлы сессии хранятся в RAM-структуре _sessions (upload/backend/session/state.py). Никаких временных файлов на диске.
  • Защита памяти: настраиваемые лимиты MAX_FILE_BYTES (по умолчанию 50 МБ) и MAX_SESSION_BYTES (по умолчанию 500 МБ).
  • Автоматическая очистка: TTL-таймер (по умолчанию 30 мин), функции touch, pause_ttl, resume_ttl, cleanup.

3. Защита и параметры (Zero Hardcode & Security)

  • SSRF-защита: create_upload_refs_blueprint валидирует входящие URL по префиксу vmUploadPrefix (поддерживаются абсолютные URL для прода и относительные для локального мока). Запросы к сторонним хостам отсекаются.
  • Path Traversal защита: модуль safe_name нормализует пути, запрещает .. и сохраняет безопасные относительные подпапки.
  • Мягкая отмена: поддержка AbortSignal на фронтенде и threading.Event на бэкенде (request_cancel, get_cancel_event).
  • Слой 3 (эмуляция/интеграция): в create_upload_refs_blueprint добавлен колбэк onFileReceived(sid, name, content), вызываемый при успешной доставке файла в RAM.

4. Автономный mock-буфер и тестовый стенд

  • В site/app.py встроен in-memory mock WebDAV (PUT, GET, DELETE по пути /mock-buffer/<key>), хранящий данные в RAM.
  • Позволяет запускать тесты и локальный demo-стенд на 100% автономно без доступа к внешней сети или боевой ВМ.
  • В шаблоне site/templates/index.html добавлена панель запуска Слоя 2, отображение прогресса пофайловой передачи и просмотр файлов, сохранённых в RAM сессии.

3. Автоматическое тестирование

Создан полный набор автоматических тестов (19 тестов, 100% PASS):

  1. Бэкенд тесты (pytest tests/ -v, 10 тестов, 0.99s):

    • test_safe_name_simple — проверка корректных путей и слэшей.
    • test_safe_name_traversal — отсечение атак .., абсолютных путей, пустых строк.
    • test_session_lifecycle — полный жизненный цикл сессии (создание, добавление, чтение, TTL, отмена, cleanup).
    • test_session_limits — проверка ограничения суммарного размера сессии в RAM.
    • test_upload_refs_pull_and_delete — проверка pull по исходящему GET, удаления из буфера, вызова колбэка Слоя 3.
    • test_upload_refs_ssrf_protection — блокировка попыток pull с недоверенных хостов (SSRF).
    • test_health — liveness-проверка платформы.
    • test_index_page — проверка отдачи UI стенда.
    • test_mock_buffer_crud — операции PUT, GET, DELETE и статус mock-буфера.
    • test_full_transit_flow_mock — сквозной тест пофайлового транзита от mock-буфера до сессии Flask.
  2. Фронтенд тесты (npm test, node:test, 9 тестов, 329ms):

    • putToVm: успешная отправка — проверка корректности HTTP PUT с сырым бинарным телом.
    • putToVm: ошибка HTTP статуса — обработка ответов 4xx/5xx.
    • putToVm: сетевая ошибка — обработка XHR onerror.
    • putToVm: таймаут — обработка XHR ontimeout.
    • putToVm: прерывание через AbortSignal — мгновенный abort текущего XHR.
    • uploadViaVM: пофайловый транзит — проверка, что N файлов вызывают N парных запросов PUT + upload_refs последовательно, передавая session_id.
    • uploadViaVM: поддержка формата FilePicker.getFiles() — совместимость со Слой 1.
    • uploadViaVM: обработка ошибки PUT — остановка конвейера и возврат ошибки.
    • uploadViaVM: прерывание через signal — отмена всего пофайлового цикла.

4. Версионирование и сборка

  • Версия поднята с 0.1.13 до 0.2.0 в package.json и site/app.py.
  • Собраны актуальные дистрибутивные бандлы dist/file-picker.esm.js (40.1 KB) и dist/file-picker.iife.js (43.4 KB).
  • Документация в README.md и upload/README.md полностью обновлена с пошаговой инструкцией интеграции в drhider и contractor.