У меня возникла проблема с CORS, связанная с использованием REST API Django Rest Framework из приложения Angular 6.
API работает на http://localhost:55098/admin. Он прекрасно работает, когда я вызываю его с Insomnia.Приложение Angular работает на http://localhost:4200.
Когда я впервые набрал http://localhost:4200/cgestores, оно должно было перенаправить на http://localhost:55098/admin/cgestores,, и это произошло, но я получил сообщение об ошибке CORS (см. Ниже).
Моя конфигурация:
REST API : я использую Python 3.7 (64 бит), Django (2.1.5) и Django Rest Framework (3.9.1)
Мои settings.py:
ALLOWED_HOSTS = [
'testserver',
'localhost'
]
CORS_ORIGIN_ALLOW_ALL = True
INSTALLED_APPS = [
# Add your apps here to enable them
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'rest_framework_swagger',
'corsheaders',
'admin_v20',
]
MIDDLEWARE_CLASSES = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
Клиент Angular : Я использую Angular 6.4.1.Служба (apiusuarios.service.ts):
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
@Injectable({
providedIn: 'root'
})
export class ApiusuariosService {
datos: iCentroGestor;
constructor(private http: HttpClient) { }
getMock(): any{
return [
{"gececo":"a", "gecdes":"one"},
{"gececo":"b", "gecdes":"two"},
{"gececo":"c", "gecdes":"three"}
];
}
getUsers(): Observable<any> {
return this.http.get(endpoint + 'cgestores').pipe(map(this.extractData));
}
}
export interface iCentroGestor {
gececo: string;
gecdes: string;
}
const endpoint = 'http://localhost:55098/admin/';
Метод getMock()
возвращает фиксированное значение JSON только для целей тестирования и работает нормально.Метод, который фактически вызывает API, является getUsers()
, и это метод, который вызывает ошибку CORS:
Доступ к XMLHttpRequest в «http://localhost:55098/admin/cgestores/' от источника» http://localhost:4200' заблокирован политикой CORS: в запрошенном ресурсе отсутствует заголовок «Access-Control-Allow-Origin».
(это Chrome; Firefox и Edge возвращают похожие ответы)
Это казалось проблемой для многих людей, я проверил следующие статьи:
... и еще несколько, а также это видео:
... и все они в значительной степени сказали одно и то же: это не проблема Angular, это проблема сервера, и я должен внести следующие изменения в мой проект DRF:
Установите пакет заголовков CORS
Измените файл settings.py следующим образом:
- Добавьте CORS_ORIGIN_WHITELIST
- Добавьте корсайдеры в INSTALLED_APPS
- Добавьте corsheaders.middleware.CorsMiddleware в MIDLEWARE_CLASSES
Все готово, но все равно не работает.Попробовав все это, я прочитал, что могу указать заголовок, который мне нужен в моем ответе.Итак, я попробовал это в своем проекте DRF:
return Response(data=pDatos, status=pStatus, headers={"Access-Control-Allow-Origin":"*"})
... и бинго, это сработало!
Однако это не совсем решение, я не хочу зависеть от конкретного параметра от конкретного ответа.И, кроме того, у меня нет возможности ограничить, кто может получить доступ к сайту, а кто нет, что было бы очень легко сделать с помощью CORS_ORIGIN_WHITELIST (ну, я мог бы, но написание параметра со списком сайтов на местесимвол звездочки не кажется правильным вариантом).
Итак, что я делаю не так?Почему мои settings.py
опции не работают?Я закомментировал их и просто оставил return Response...
, и он все еще работает, поэтому settings.py
ничего не делает.
Извините за этот длинный пост.Есть идеи?Заранее спасибо за помощь.