Files
contracts/History/sonnet-zip-cors.md
2026-06-23 09:07:26 +04:00

2.6 KiB

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:

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:

var zipResp = await fetch(UNZIP_URL, {
    method: 'POST',
    body: f,
    headers: { 'Content-Type': 'application/zip' }
});

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