Ответ
CORS (Cross-Origin Resource Sharing) — это механизм безопасности, встроенный в браузеры, который позволяет веб-странице запрашивать ресурсы с другого домена (origin), отличного от того, с которого она была загружена.
Проблема, которую решает CORS
По умолчанию в браузерах действует политика одинакового источника (Same-Origin Policy, SOP), которая запрещает скриптам с одного сайта получать доступ к данным на другом. Это защищает пользователей от вредоносных сайтов, которые могли бы читать данные из вашей почты или банковского аккаунта, открытых в соседних вкладках.
CORS предоставляет серверу контролируемый способ "ослабить" эту политику и разрешить доверенным сайтам получать доступ к его ресурсам.
Как это работает?
Когда фронтенд (например, с https://my-app.com) пытается отправить "сложный" запрос (например, PUT или с кастомными заголовками) к API на https://api.service.com, браузер автоматически выполняет preflight-запрос (предварительный запрос) с методом OPTIONS.
Сервер должен ответить, разрешает ли он такой запрос, отправив специальные HTTP-заголовки:
Access-Control-Allow-Origin: Указывает, каким доменам разрешен доступ (https://my-app.comили*для всех).Access-Control-Allow-Methods: Список разрешенных методов (GET,POST,DELETEи т.д.).Access-Control-Allow-Headers: Список разрешенных заголовков запроса.
Если ответ сервера разрешающий, браузер отправляет основной запрос. В противном случае — блокирует его.
Пример на Flask с использованием flask-cors (best practice):
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
# Разрешить запросы с домена 'https://my-app.com' для всех роутов, начинающихся с /api/
CORS(app, resources={r"/api/*": {"origins": "https://my-app.com"}})
@app.route('/api/data')
def get_data():
return jsonify({'message': 'This is cross-origin data!'}) Ответ 18+ 🔞
Так, слушай, а вот есть у нас такая хуйня в браузерах — CORS. Это, блядь, не просто так, это защита, чтобы какой-нибудь левый сайт не мог слить твою почту или банковские данные, пока ты в другой вкладке сидишь. По умолчанию браузер — он как строгий отец: «С какого хуя ты лезешь на чужой домен? Нельзя!». Это политика одинакового источника, SOP называется.
Но иногда нам надо, понимаешь? Фронтенд на my-app.com хочет стянуть данные с API на api.service.com. Вот тут CORS и включается. Это такой контролируемый способ сказать браузеру: «Эй, расслабься, я этого чувака знаю, пусть берёт».
А теперь самое весёлое. Когда твой скрипт пытается отправить не простой запрос (не GET или POST с обычными заголовками), а какой-нибудь замудрённый — с методом PUT или кастомными заголовками, — браузер, этот дотошный пидорас, сначала шлёт предварительный запрос (preflight) методом `OPTIONS**. Типа: «Эй, сервак, а можно так-то?».
И сервер должен ответить правильно, а то пиздец. Он шлёт заголовки:
Access-Control-Allow-Origin: с какого домена можно (например,https://my-app.comили звёздочка*— но это, блядь, как дверь нараспашку, осторожно).Access-Control-Allow-Methods: какие методы разрешены (GET,POST,DELETE— весь список).Access-Control-Allow-Headers: какие заголовки в запросе можно использовать.
Если сервер ответил «да, вали, братан», браузер отпускает основной запрос. Если нет — просто блокирует его, и ты в консоли видишь эту ёбаную ошибку, от которой волосы дыбом встают.
Вот как это по-человечески на Flask делается (с расширением flask-cors, ибо самому всё это прописывать — тот ещё геморрой):
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
# Разрешаем запросы только с 'https://my-app.com' и только для роутов, которые начинаются с /api/
# Чтобы не открывать всё нараспашку, как последнему распиздю.
CORS(app, resources={r"/api/*": {"origins": "https://my-app.com"}})
@app.route('/api/data')
def get_data():
return jsonify({'message': 'This is cross-origin data!'})
Вот и вся магия. Главное — не забыть на сервере эти заголовки правильно выставить, а то будет «ошибка CORS», и ты полдня будешь искать, в чём же, блядь, дело.