Комментарии (3)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое разные источники запросов?
Различные источники запросов в браузере — это важная концепция безопасности и производительности. Источник определяется протоколом, доменом и портом, и это влияет на то, какие запросы браузер разрешает по умолчанию.
Same-Origin и Cross-Origin
Источник (origin) определяется как комбинация протокола, домена и порта:
// Примеры определения origin:
// https://example.com:443 -> origin = https://example.com
// Same-origin (одинаковые origin):
// - https://example.com/page1 и https://example.com/page2 - ДА
// - https://example.com и https://example.com:443 - ДА (443 порт по умолчанию)
// - https://example.com и http://example.com - НЕТ (разные протоколы)
// - https://example.com и https://api.example.com - НЕТ (разные домены)
// - https://example.com:3000 и https://example.com:3001 - НЕТ (разные порты)
CORS - Cross-Origin Resource Sharing
CORS - это механизм, который позволяет запросы с одного origin к другому origin:
// На фронтенде запрос идет просто так:
fetch('https://api.example.com/data')
.then(response => response.json())
.then(data => console.log(data))
// Браузер автоматически добавляет заголовок Origin:
// Origin: https://myapp.example.com
// Сервер должен ответить с заголовком Access-Control-Allow-Origin:
// Access-Control-Allow-Origin: https://myapp.example.com
// Или для всех:
// Access-Control-Allow-Origin: *
// Если этого заголовка нет - браузер блокирует ответ!
Preflight запросы
Для сложных запросов браузер сначала отправляет OPTIONS запрос:
// Сложный запрос (не simple request):
fetch('https://api.example.com/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ name: 'John' })
})
// Браузер сначала отправит:
// OPTIONS /data HTTP/1.1
// Origin: https://myapp.example.com
// Access-Control-Request-Method: POST
// Access-Control-Request-Headers: content-type
// Сервер должен ответить:
// HTTP/1.1 200 OK
// Access-Control-Allow-Origin: https://myapp.example.com
// Access-Control-Allow-Methods: POST, GET, PUT
// Access-Control-Allow-Headers: content-type
// Access-Control-Max-Age: 86400
Simple requests (без preflight)
Простые запросы не требуют preflight и отправляются сразу:
// Simple requests условия:
// 1. Метод: GET, HEAD, POST
// 2. Заголовки: Accept, Accept-Language, Content-Language, Content-Type (только определенные значения)
// 3. Content-Type только: application/x-www-form-urlencoded, multipart/form-data, text/plain
// Пример простого запроса:
fetch('https://api.example.com/data')
// Пример сложного запроса (нужен preflight):
fetch('https://api.example.com/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'John' })
})
Credentials и аутентификация
CORS требует специальной обработки для отправки cookies и авторизационных заголовков:
// По умолчанию cookies не отправляются на cross-origin:
fetch('https://api.example.com/data')
.then(response => response.json())
// Чтобы отправить cookies - нужен credentials: 'include':
fetch('https://api.example.com/data', {
credentials: 'include',
headers: {
'Authorization': 'Bearer token123'
}
})
// Сервер должен ответить:
// Access-Control-Allow-Credentials: true
// Access-Control-Allow-Origin: https://myapp.example.com (НЕ * при credentials!)
Proxy для разработки
Во время разработки часто используют proxy в webpack dev server:
// next.config.js или webpack.config.js
module.exports = {
async rewrites() {
return [
{
source: '/api/:path*',
destination: 'http://localhost:8000/api/:path*'
}
]
}
}
// Теперь запрос к /api/data на фронтенде
// будет проксирован на http://localhost:8000/api/data
fetch('/api/data')
JSONP - старый способ обхода CORS
JSONP - это старый способ, совсем не рекомендуется использовать:
// Старый способ (не используй!):
<script src="https://api.example.com/data?callback=myFunction"></script>
function myFunction(data) {
console.log(data)
}
// Проблемы:
// - Только GET запросы
// - Нет обработки ошибок
// - Security issues
Обработка CORS ошибок
CORS ошибки в консоли означают, что сервер не разрешил запрос:
// Типичная CORS ошибка в консоли:
// "Access to XMLHttpRequest at 'https://api.example.com/data'
// from origin 'https://myapp.example.com'
// has been blocked by CORS policy"
// Решение - конфигурируй CORS на бэкенде:
// Express.js:
const cors = require('cors')
app.use(cors({
origin: ['https://myapp.example.com', 'https://admin.example.com'],
credentials: true
}))
// FastAPI:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=['https://myapp.example.com'],
allow_credentials=True,
allow_methods=['GET', 'POST'],
allow_headers=['*']
)
Локальное хранилище и источники
LocalStorage, SessionStorage и Cookies привязаны к origin:
// На https://example.com:
localStorage.setItem('key', 'value')
// На https://api.example.com:
console.log(localStorage.getItem('key')) // null - разные origins!
// Каждый origin имеет свой отдельный storage
Вывод
Разные источники запросов (origins) - это фундаментальная концепция безопасности браузера. CORS контролирует, какие cross-origin запросы браузер разрешает. Всегда правильно конфигурируй CORS на бэкенде, отправляй правильные заголовки, и используй credentials осторожно для безопасности.