2.6 KiB
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
План реализации (когда «делай»)
- nginx: перенести CORS-заголовки внутрь
if-блока - JS:
fetch(UNZIP_URL, { method: 'POST', body: f, headers: {'Content-Type': 'application/zip'} }) - VM: raw binary как основной путь, multipart как fallback
- Убрать FormData из JS
- Bump, пуш, синк VM + nginx