Приложение Angular не может прочитать API Django Rest Framework из-за проблемы с CORS - PullRequest
0 голосов
/ 12 февраля 2019

У меня возникла проблема с 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:

  1. Установите пакет заголовков CORS

  2. Измените файл 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 ничего не делает.

Извините за этот длинный пост.Есть идеи?Заранее спасибо за помощь.

1 Ответ

0 голосов
/ 14 февраля 2019

Сам нашел ответ, я бы хотел поделиться им.

Я использую Django 2.1.5.Похоже, что секция MIDDLEWARE_CLASS просто называется MIDDLEWARE начиная с версии 2. Когда я изменил ее, я был вынужден закомментировать django.contrib.auth.middleware.SessionAuthenticacionMiddleware, и это сработало.Теперь все работает как надо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...