md
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
# 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
|
||||
Reference in New Issue
Block a user