# Решение CORS Error ## Что такое CORS? CORS (Cross-Origin Resource Sharing) - это механизм безопасности браузера, который блокирует запросы между разными доменами/портами. ## Проблема При разработке: - **Frontend** (Flutter Web) работает на `http://localhost:xxxxx` (случайный порт) - **Backend** работает на `http://localhost:8000` - Браузер блокирует запросы между этими портами ## Решение ### 1. ✅ Backend настроен (исправлено 19 окт 2025) В файле `mnemo_cards_backend/lib/api/mnemo_shelf.dart` добавлена правильная CORS конфигурация: ```dart final corsConfig = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS', 'Access-Control-Allow-Headers': 'Origin, Content-Type, Accept, Authorization, user_token, request_token, app_version', 'Access-Control-Expose-Headers': 'Authorization', 'Access-Control-Max-Age': '86400', }; ``` **⚠️ ВАЖНО:** CORS middleware должен быть **ПЕРВЫМ** в pipeline, иначе preflight запросы (OPTIONS) будут блокироваться авторизацией: ```dart final handler = Pipeline() .addMiddleware(corsHeaders(headers: corsConfig)) // ← CORS ПЕРВЫМ! .addMiddleware(logRequests(logger: logger('app'))) .addMiddleware(appAuthorize(getIt.get())) .addHandler(rootRouter); ``` Это позволяет: - ✅ Принимать запросы с любого origin (`*`) - ✅ Разрешает все необходимые HTTP методы - ✅ Разрешает кастомные заголовки (`user_token`, `request_token`, `app_version`) - ✅ Разрешает читать заголовок `Authorization` в ответе - ✅ OPTIONS запросы обрабатываются до проверки авторизации ### 2. 🚀 Запуск Backend Используйте скрипт для запуска backend в режиме разработки: ```bash cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_backend ./run_dev.sh ``` Backend будет доступен на `http://localhost:8000` ### 3. 🌐 Запуск Frontend В отдельном терминале запустите веб-версию: ```bash cd /Users/dmitry/StudioProjects/mnemo_cards/mnemo_cards_web_v2 flutter run -d chrome ``` ### 4. ✔️ Проверка После запуска обоих сервисов: 1. Откройте DevTools в Chrome (F12) 2. Перейдите на вкладку Network 3. Проверьте что запросы к `/packs/previews`, `/games` и т.д. успешны 4. В заголовках ответа должны быть CORS заголовки ## Альтернативные решения (если не помогло) ### Вариант 1: Отключить web security в Chrome (только для разработки!) ```bash # macOS open -n -a "Google Chrome" --args --user-data-dir="/tmp/chrome_dev_session" --disable-web-security # Linux google-chrome --disable-web-security --user-data-dir="/tmp/chrome_dev_session" ``` ⚠️ **Внимание**: Это небезопасно! Используйте только для разработки. ### Вариант 2: Использовать Flutter с --web-port Запускайте Flutter на фиксированном порту: ```bash flutter run -d chrome --web-port=8080 ``` ### Вариант 3: Production CORS (для деплоя) Для production версии: 1. **Backend** уже настроен с правильными CORS настройками ✅ 2. **Frontend** использует `api.memo-cards.online` ✅ 3. **Nginx** настроен без конфликтующих COEP/COOP headers ✅ Текущая конфигурация позволяет: - ✅ Запросы с `memo-cards.online` на `api.memo-cards.online` - ✅ Все необходимые HTTP методы и headers - ✅ Preflight OPTIONS запросы ## Диагностика Если CORS ошибка все еще возникает: 1. **Проверьте что backend запущен**: ```bash curl http://localhost:8000/games ``` 2. **Проверьте CORS заголовки**: ```bash curl -H "Origin: http://localhost:8080" -H "Access-Control-Request-Method: POST" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose http://localhost:8000/games ``` 3. **Посмотрите логи backend** - там будут видны все входящие запросы 4. **Проверьте что ApiConfig использует правильный URL**: ```dart // В lib/domain/config/api_config.dart static const String baseUrl = 'http://localhost:8000'; ``` ## Полезные ссылки - [MDN: CORS](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS) - [shelf_cors_headers package](https://pub.dev/packages/shelf_cors_headers) - [Flutter Web: CORS](https://docs.flutter.dev/platform-integration/web/building#handling-cors-errors-only-applicable-to-web)