From 2f9d6a21f6316ea225d187f91004150a0ca13035 Mon Sep 17 00:00:00 2001 From: min Date: Wed, 10 Jun 2026 01:27:48 +0300 Subject: [PATCH] =?UTF-8?q?fix(rbxl-importer):=20CORS=20preflight=20+=20?= =?UTF-8?q?=D0=BE=D1=82=D0=BA=D1=80=D1=8B=D1=82=20=D0=B4=D0=BB=D1=8F=20?= =?UTF-8?q?=D0=B2=D1=81=D0=B5=D1=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Фронт студии (studio.rublox.pro) делал POST /import/rbxl/analyze на minecraftia-school.ru/api-rbxl, preflight (OPTIONS) не получал Access-Control-Allow-Origin → CORS ошибка. Фиксы: - after_request гарантированно ставит CORS-заголовки на ВСЕ ответы (включая OPTIONS) — раньше flask-cors иногда их не отдавал - Явный handler для OPTIONS /import/rbxl/analyze + create - Headers: Allow-Origin=*, Allow-Methods, Allow-Headers content-type+x-user-id - Убрал ALLOWED_USER_IDS=[1] (импорт открыт всем — кнопка в UI уже без гейтинга, см. вики «Импорт из Roblox») Деплой: вручную через SSH на VM 130 (rbxl-importer не имеет CI/CD). --- rbxl-importer/src/app.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/rbxl-importer/src/app.py b/rbxl-importer/src/app.py index 9da2929..78c5bc3 100644 --- a/rbxl-importer/src/app.py +++ b/rbxl-importer/src/app.py @@ -59,10 +59,28 @@ STORAGE_ROOT = os.environ.get('STORAGE_ROOT', '/opt/roblox-assets') PUBLIC_ASSET_BASE = os.environ.get('PUBLIC_ASSET_BASE', 'https://assets.rublox.pro/roblox') MAX_RBXL_SIZE = 50 * 1024 * 1024 # 50 MB -ALLOWED_USER_IDS = [1] # пока только МИН app = Flask(__name__) -CORS(app, resources={r'/*': {'origins': '*'}}) +# CORS открыт для всех источников — фронт студии живёт на studio.rublox.pro, +# api-rbxl проксируется через NPM на minecraftia-school.ru/api-rbxl/*. +# Поддерживаем preflight (OPTIONS) явно через after_request — иногда +# flask-cors не отдавал заголовки для OPTIONS если NPM их перекрывал. +CORS(app, resources={r'/*': {'origins': '*'}}, supports_credentials=False) + + +@app.after_request +def _add_cors_headers(resp): + resp.headers['Access-Control-Allow-Origin'] = '*' + resp.headers['Access-Control-Allow-Methods'] = 'GET, POST, OPTIONS' + resp.headers['Access-Control-Allow-Headers'] = 'Content-Type, X-User-Id, X-User-Login' + resp.headers['Access-Control-Max-Age'] = '3600' + return resp + + +@app.route('/import/rbxl/analyze', methods=['OPTIONS']) +@app.route('/import/rbxl/create', methods=['OPTIONS']) +def _preflight(): + return '', 204 # Devlog для удалённой отладки dev-сессий студии: фронт пушит сюда # console.error/warn, failed network requests, неожиданные exceptions. @@ -93,8 +111,7 @@ def auth_check(req) -> int: uid = int(user_id_str) except ValueError: raise RuntimeError(f'Bad X-User-Id: {user_id_str!r}') - if uid not in ALLOWED_USER_IDS: - raise RuntimeError(f'User {uid} not allowed (only МИН)') + # Импорт открыт всем (см. вики «Импорт из Roblox»). return uid