# Sonnet Analysis — ZIP Upload CORS + Multipart Дата: 2026-06-23 | Источник: Sonnet (новый чат) Связано: index.cfm, convert_server.py, nginx-contracts.conf --- ## Текущее состояние - JS на `contractor.luceek8s.dev.nubes.ru` шлёт FormData через fetch на `contracts.kube5s.ru/unzip-upload` - VM (Python, 8766) парсит multipart через `email.parser.BytesParser` - Nginx проксирует `/unzip-upload` → VM:8766 - CURL работает, браузер — `Failed to fetch` ## Диагноз Sonnet ### 1. CORS в nginx — add_header внутри if не работает `add_header` в родительском `location` не применяется к ответу из `if (...) { return 200; }` — это новый контекст. **Исправление:** заголовки внутрь `if`: ```nginx location /unzip-upload { if ($request_method = OPTIONS) { add_header Access-Control-Allow-Origin "*"; add_header Access-Control-Allow-Methods "POST, OPTIONS"; add_header Access-Control-Allow-Headers "*"; add_header Content-Length 0; return 204; } add_header Access-Control-Allow-Origin "*"; proxy_pass http://127.0.0.1:8766; client_max_body_size 100m; } ``` ### 2. Multipart парсинг — filename*= кодировка Браузер для файлов с не-ASCII именами использует `filename*=UTF-8''...` (RFC 5987). `part.get_filename()` может вернуть None. **Решение:** переход на raw binary (п.3) устраняет проблему полностью. ### 3. Raw binary — лучший вариант **JS:** ```javascript var zipResp = await fetch(UNZIP_URL, { method: 'POST', body: f, headers: { 'Content-Type': 'application/zip' } }); ``` **Python:** ```python if "multipart" in content_type: # fallback для curl ... else: zip_data = self.rfile.read(length) ``` **Плюсы:** - Нет multipart overhead - Нет проблем с filename-кодировкой - Нет проблем с boundary **Минусы:** - Нужен правильный CORS preflight (Content-Type: application/zip — не simple) - Нужен `client_max_body_size` в nginx ## План реализации (когда «делай») 1. nginx: перенести CORS-заголовки внутрь `if`-блока 2. JS: `fetch(UNZIP_URL, { method: 'POST', body: f, headers: {'Content-Type': 'application/zip'} })` 3. VM: raw binary как основной путь, multipart как fallback 4. Убрать FormData из JS 5. Bump, пуш, синк VM + nginx