Благодаря чему появляется ошибка CORS в браузере
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Благодаря чему появляется ошибка CORS в браузере
CORS (Cross-Origin Resource Sharing) - это механизм безопасности браузера, который контролирует доступ к ресурсам с других доменов. Ошибка CORS появляется, когда браузер блокирует запрос к ресурсу с другого источника.
Что такое Origin (источник)
Origin состоит из трёх частей: схема (protocol) + домен (domain) + порт (port)
https://example.com:443
^ ^ ^
протокол домен порт
Примеры разных Origin-ов:
https://example.com (стандартный)
https://example.com:3000 (другой порт!)
http://example.com (другой протокол!)
https://api.example.com (другой домен!)
https://example.org (совсем другой домен)
Когда появляется ошибка CORS
Same-Origin Policy - браузер разрешает запросы только на тот же Origin.
// Запрос со страницы: https://example.com
// ОК: Same-Origin
fetch('https://example.com/api/users');
// ОШИБКА CORS: Другой Origin
fetch('https://api.example.com/users');
// ОШИБКА CORS: Другой порт
fetch('https://example.com:3000/api/users');
// ОШИБКА CORS: Другой протокол
fetch('http://example.com/api/users');
Сообщение об ошибке
Access to XMLHttpRequest at 'https://api.example.com/users'
from origin 'https://example.com'
has been blocked by CORS policy:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Как работает CORS
Шаг 1: Браузер отправляет Preflight запрос (для небезопасных запросов)
OPTIONS /api/users HTTP/1.1
Host: api.example.com
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type
Шаг 2: Сервер отвечает с CORS заголовками
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Шаг 3: Если заголовки ОК, браузер отправляет реальный запрос
POST /api/users HTTP/1.1
Host: api.example.com
Origin: https://example.com
Content-Type: application/json
{"name": "John"}
Примеры CORS ошибок
1. Простой GET запрос
// Страница: https://example.com
fetch('https://api.example.com/posts')
.then(r => r.json())
.catch(e => console.error(e));
// ОШИБКА! Потому что сервер не возвращает:
// Access-Control-Allow-Origin: https://example.com
2. POST с JSON телом
// Страница: https://example.com
fetch('https://api.example.com/users', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: 'John' })
})
.catch(e => console.error(e));
// ОШИБКА CORS! Потому что:
// 1. Это "небезопасный" запрос (POST не простой)
// 2. Header Content-Type требует разрешения
// 3. Сервер должен вернуть Access-Control-Allow-* заголовки
Какие запросы простые (не требуют Preflight)
Простые запросы:
- GET, HEAD, POST
- Только определённые заголовки (Content-Type, Accept, Accept-Language)
- Content-Type только: application/x-www-form-urlencoded, multipart/form-data, text/plain
// ПРОСТОЙ запрос (без Preflight)
fetch('https://api.example.com/posts');
// ПРОСТОЙ POST
fetch('https://api.example.com/posts', {
method: 'POST',
body: new FormData() // form-data
});
Небезопасные запросы (требуют Preflight):
- PUT, DELETE, PATCH
- Кастомные заголовки (Authorization, X-Custom-Header)
- application/json Content-Type
// НЕБЕЗОПАСНЫЙ запрос (требует Preflight)
fetch('https://api.example.com/users/1', {
method: 'DELETE',
headers: {
'Authorization': 'Bearer token123'
}
});
// Браузер отправит OPTIONS запрос перед DELETE
Решения для CORS ошибок
1. Сервер должен установить правильные заголовки
# FastAPI
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"],
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE"],
allow_headers=["Content-Type", "Authorization"],
)
// Express
const cors = require('cors');
app.use(cors({
origin: 'https://example.com',
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
}));
2. Wildcard (разрешить всем)
Access-Control-Allow-Origin: *
Это позволяет запросам с любого Origin, но имеет ограничения (no credentials).
3. JSONP (старый способ, НЕ рекомендуется)
// Работает без CORS, но устаревший подход
function handleCallback(data) {
console.log(data);
}
const script = document.createElement('script');
script.src = 'https://api.example.com/data?callback=handleCallback';
document.head.appendChild(script);
4. Прокси на своём сервере
// Фронтенд запрашивает СВОЙ сервер
fetch('https://example.com/api/proxy/users')
// Свой сервер переадресовывает на api.example.com
// (нет CORS, потому что backend->backend запрос)
fetch('https://api.example.com/users')
Настройка CORS в Next.js
// app/api/users/route.ts
export async function GET(request: Request) {
const response = await fetch('https://api.example.com/users');
const data = await response.json();
return new Response(JSON.stringify(data), {
headers: {
'Access-Control-Allow-Origin': '*',
'Content-Type': 'application/json'
}
});
}
Или использовать прокси-мидлвэр
// next.config.js
module.exports = {
async rewrites() {
return {
beforeFiles: [
{
source: '/api/external/:path*',
destination: 'https://api.example.com/:path*'
}
]
};
}
};
Тогда фронтенд может запрашивать:
fetch('/api/external/users')
// Будет переадресовано на https://api.example.com/users
Отладка CORS
В DevTools:
- Открой Network вкладку
- Найди запрос, который вызвал ошибку
- Перейди на вкладку Response Headers
- Проверь наличие
Access-Control-Allow-Origin
Проверка заголовков:
curl -i https://api.example.com/users
# Ищи Access-Control-Allow-Origin в ответе
Частые ошибки
Ошибка 1: Wildcard с credentials
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Это ОШИБКА! Нельзя использовать * с credentials. Нужно явно указать Origin.
Ошибка 2: Забыли про Preflight
// Думаешь, это просто запрос
fetch('https://api.example.com/users', {
method: 'DELETE',
headers: { 'Authorization': 'Bearer token' }
});
// На самом деле браузер отправляет 2 запроса:
// 1. OPTIONS /users (Preflight)
// 2. DELETE /users (если Preflight OK)
Итог
- CORS - защита браузера от межсайтовых запросов
- Ошибка появляется, когда Origin отличается (домен, порт или протокол)
- Сервер должен вернуть
Access-Control-Allow-Originзаголовок - Preflight запрос (OPTIONS) отправляется для небезопасных методов
- Решения: правильная конфигурация CORS на сервере, прокси или JSONP