Files
contracts/History/llm-analysis/sonnet-zip-cors.md
T

80 lines
2.6 KiB
Markdown

# 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