Сегодня мы освоим настройку CORS (Cross-Origin Resource Sharing) в Django.
Вообразите ситуацию: вы создали блестящее API. Всё работает идеально, пока вы не решите подключить ваше любимое фронтенд-приложение, запущенное на другом домене или порту.
Пример: ваш сервер работает на http://127.0.0.1:8000, а фронтенд — на http://localhost:3000.
Тут в игру вступает CORS — Cross-Origin Resource Sharing.
Браузеры, из соображений безопасности, блокируют запросы к API, которые отправляются с одного домена (например, http://localhost:3000) к серверу на другом домене (например, http://127.0.0.1:8000).
Это называется Same-Origin Policy — механизм, предотвращающий отправку запросов от вашего имени к другим ресурсам без разрешения.
CORS позволяет серверу сообщать браузеру, что он доверяет запросам с другого домена.
Это достигается добавлением специальных заголовков CORS в ответы API.
Таким образом, ваш фронтенд сможет взаимодействовать с API без проблем.
Установка и настройка django-cors-headers
В Django есть несколько способов настроить CORS, но самый популярный и удобный — это библиотека django-cors-headers. Давайте установим и настроим её.
pip install django-cors-headers
Шаг 1: подключение приложения
После установки необходимо зарегистрировать приложение в INSTALLED_APPS. Откройте файл settings.py и добавьте:
INSTALLED_APPS = [
...
'corsheaders',
...
]
Чтобы библиотека могла обрабатывать запросы до того, как они попадут в Django Middleware, добавьте corsheaders.middleware.CorsMiddleware в список MIDDLEWARE прямо после SecurityMiddleware:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
Шаг 2: базовая настройка CORS
Теперь, когда приложение добавлено, нужно указать, каким доменам разрешено обращаться к вашему API. Для этого добавьте в settings.py параметр CORS_ALLOWED_ORIGINS:
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000", # Разрешаем доступ фронтенду с порта 3000
"http://127.0.0.1:3000", # Еще один вариант локального хоста
]
Этого достаточно для настроек приложения, если вы хотите разрешить доступ только конкретным доменам.
Настройка wildcard-домена для всех источников (НЕ РЕКОМЕНДУЕТСЯ)
Если вы хотите разрешить доступ всем доменам (например, для разработки), можно использовать настройку CORS_ALLOW_ALL_ORIGINS. Будьте осторожны с этим параметром, так как он может поставить вашу систему под угрозу в продакшен-среде.
CORS_ALLOW_ALL_ORIGINS = True
Помните: никогда не используйте CORS_ALLOW_ALL_ORIGINS = True в продакшене. Вы не хотите, чтобы кто угодно, где угодно мог делать запросы к вашему API.
Настройка допустимых методов и заголовков
Библиотека django-cors-headers позволяет дополнительно настроить методы HTTP и заголовки, которые сервер разрешает обрабатывать. Например:
По умолчанию разрешены только стандартные HTTP-методы: GET, POST, PUT, PATCH, DELETE, OPTIONS. Если вам нужно разрешить другие методы, используйте следующую настройку:
CORS_ALLOW_METHODS = [
"GET",
"POST",
"PUT",
"DELETE",
"OPTIONS",
"PATCH",
]
Если ваш фронтенд отправляет дополнительные заголовки (например, Authorization для аутентификации), их нужно явно указать:
CORS_ALLOW_HEADERS = [
"content-type",
"authorization",
"x-csrf-token",
]
Политики CORS для конкретных эндпоинтов
Иногда вам может понадобиться разрешить CORS только для определённых эндпоинтов. Например, открытые ресурсы, такие как "список товаров", могут быть доступны всем, а приватные ресурсы — только аутентифицированным пользователям.
Для таких случаев можно использовать декоратор @cors_allow_all.
Пример настройки:
from corsheaders.decorators import cors_allow_all
@cors_allow_all
def my_open_endpoint(request):
return JsonResponse({"message": "Hello, world!"})
Однако, такой подход редко используется, так как в большинстве случаев все настройки качества обрабатываются глобально.
Практическое задание
Задание: подключаем внешний фронтенд
Шаги:
- Создайте простое REST API в Django — например, список задач (ToDo).
- Настройте CORS для разрешения запросов с домена
http://localhost:3000. - Подключите ваше API к фронтенд-приложению (например, React).
- Попробуйте отправить запросы
GETиPOSTс фронтенда. Проверьте, что ошибки CORS больше не возникают.
Решение
# settings.py
INSTALLED_APPS = [
...
'corsheaders',
...
]
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
]
# views.py
from django.http import JsonResponse
from rest_framework.decorators import api_view
@api_view(["GET"])
def todo_list(request):
todos = [
{"id": 1, "task": "Изучить Django", "completed": False},
{"id": 2, "task": "Написать REST API", "completed": True},
]
return JsonResponse(todos, safe=False)
С фронтенда вы можете использовать библиотеку axios для отправки запросов:
import axios from 'axios';
axios.get("http://127.0.0.1:8000/api/todos/")
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error("Ошибка:", error);
});
Частые проблемы и их решения
Иногда вам могут встретиться ошибки, даже если вы всё настроили правильно.
Проблема: ошибка No Access-Control-Allow-Origin header is present on the requested resource
Эта проблема обычно возникает, если вы забыли добавить ваш фронтенд-домен в CORS_ALLOWED_ORIGINS. Убедитесь, что он указан в settings.py.
Проблема: ошибка CORS при использовании авторизации
Если вы используете токены для доступа, убедитесь, что заголовок Authorization добавлен в список CORS_ALLOW_HEADERS.
CORS_ALLOW_HEADERS = [
"content-type",
"authorization",
]
Настройка CORS — это важный шаг в интеграции вашего Django-приложения с внешними фронтенд-приложениями. Она позволяет сделать API безопасным и доступным в рамках современных стандартов веб-разработки.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ