Ошибка при получении HTTPS из REST API в Angular - PullRequest
2 голосов
/ 27 апреля 2020

У меня запущено приложение Angular, которое использует внешний API для получения ISO стран. Этот API использует https и выдает ошибку.

Дело в том, что когда я использую прокси в моей локальной среде angular, отображение /iso-api/ на реальный URL работает нормально.

"/iso-api/*": {
    "target": "https://www...",
    "pathRewrite": { "^/iso-api": "" },
    "secure": false,
    "changeOrigin": true,
    "logLevel": "debug"
}

Но я хочу, чтобы это работало на производстве, поэтому я хочу использовать реальный URL.

На моем сервере я уже возвращаю заголовок Access-Control-Allow-Origin: *.

I ' Я пытался запустить сервер angular с помощью ssl (поскольку внешний API-интерфейс использует https), но я получаю ту же ошибку.

Я знаю, что решение будет заключаться в реализации прокси на сервере, но я считаю, это не должно быть сделано, и может быть способ извлечь эти данные из внешнего интерфейса. Помогите пожалуйста.

Ответ

Это сетевая ошибка в Chrome: browser network tab

В Firefox, запрос заканчивается на 200 OK и возвращает данные, но выдается ошибка CORS, и я не могу получить доступ к данным из приложения: CORS header 'Access-Control-Allow-Origin' missing

General

Request URL: https://www...
Referrer Policy: no-referrer-when-downgrade

Заголовки запроса

:method: GET
:scheme: https
accept: application/json, text/plain, */*
accept-encoding: gzip, deflate, br
accept-language: es-ES,es;q=0.9,en;q=0.8
origin: http://localhost:4200
referer: http://localhost:4200/app/login
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: cross-site

Заголовки ответа

accept-ranges: bytes
cache-control: max-age=0
content-encoding: gzip
content-language: en-US
content-length: 68356
content-type: application/json
date: Mon, 27 Apr 2020 14:49:30 GMT
expires: Mon, 27 Apr 2020 14:49:30 GMT
referrer-policy: strict-origin-when-cross-origin
server-timing: cdn-cache; desc=HIT
server-timing: edge; dur=1
server-timing: ACTT;dur=0,ACRTT;dur=88
set-cookie: ... expires=Mon, 27 Apr 2020 16:49:30 GMT; max-age=7200; path=/; domain=...; HttpOnly
set-cookie: ... Domain=...; Path=/; Expires=Mon, 27 Apr 2020 18:49:30 GMT; Max-Age=14400; HttpOnly
set-cookie: ... Domain=...; Path=/; Expires=Tue, 27 Apr 2021 14:49:30 GMT; Max-Age=31536000; Secure
status: 200
vary: Accept-Encoding

ОБНОВЛЕНИЕ

Angular сервисный код

import { HttpClient } from '@angular/common/http';

...

constructor(
    private _http: HttpClient,
    private _errorUtil: ErrorUtilService,
    private _converter: StoreConverter
  ) {}

...
  getCountries(): Observable<CountryWithLanguages[]> {
    return this._http.get<GetStoresResponse>(API.storeUrl).pipe(
      catchError(this._errorUtil.handle),
      map(result => result.stores),
      switchMap(stores => stores),
      filter(this._isActiveStore),
      map(store => this._converter.toView(store)),
      toArray()
    );
  }

Для обслуживания приложения, которое я использую angular dev server, я не добавляю заголовок «Access-Control-Allow-Origin» вручную, но в браузере вижу, что оно добавляется.

Chrome Network tab

angular. json

"serve": {
          "builder": "@angular-devkit/build-angular:dev-server",
          "options": {
            "browserTarget": "push-web-app:build",
            "proxyConfig": "src/proxy-local.conf.json"
          },
         }

Ответы [ 4 ]

1 голос
/ 06 мая 2020

Вы не можете запросить ресурс у другого домена. Это будет дыра в безопасности. Вы можете прочитать больше здесь: Политика того же происхождения

Отправка Access-Control-Allow-Origin: * с вашего сервера не даст вам доступа к вышеупомянутому API. Поставщик этого API должен дать вам разрешение на доступ к API, вы не можете сами дать это разрешение.

В опубликованной вами ошибке указано, что заголовок Access-Control-Allow-Origin отсутствует. Это означает, что API не отправляет этот заголовок.

Возможны две причины, по которым этот API не отправляет заголовок Access-Control-Allow-Origin.

  1. Неправильная конфигурация на стороне это API. В этом случае вы должны попросить поставщика этого API исправить эту проблему.
  2. Поставщик API намеренно ограничивает доступ к API. В этом случае вы должны попросить поставщика этого API предоставить вам доступ с вашего домена.

Вы также можете прокси-запрос через ваш сервер. Основное отличие при использовании прокси состоит в том, что ваш сервер читает ресурс из API, а не из браузера клиента. См. Ответ Дэвида о том, как настроить прокси с nginx.

1 голос
/ 06 мая 2020

Вы не можете обойти сторону браузера CORS. Если вы не можете изменить серверную часть, ваше единственное решение - использовать прокси.

В целях разработки вы можете использовать встроенный прокси-сервер angular, но не для производства.

Вот базовая c nginx конфигурация для этого

server {
    listen          80;
    server_name     yourdomain.com; #domain where your angular code is deployed

    location /iso-api{

        RewriteRule                     ^/iso-api/(.*)$ /$1 break;
        proxy_pass                      https://thirdpartyapidomain.com; #url of the API you are trying to access
    }

    location
    {
        #Your normal angular location
        #try_files ...
    }
}

Это перенаправит запросы как

http://yourdomain.com/iso-api/countriesList на https://thirdpartyapidomain.com/countriesList;

Поскольку теперь вызовы API клиента и сервера находятся в одном домене, у вас не должно быть проблем с CORS

0 голосов
/ 06 мая 2020

Попробуйте вызов .get с параметром withCredentials: true:

return this._http.get<GetStoresResponse>(API.storeUrl, { withCredentials: true }).pipe();

... и / или убедитесь, что ваши браузеры обновлены.

0 голосов
/ 05 мая 2020

Используйте этот сайт для устранения ошибки CORS: https://cors-anywhere.herokuapp.com/

Использовать пример https://cors-anywhere.herokuapp.com/https: //freegeoip.app/json

this._http.get('https://cors-anywhere.herokuapp.com/https://freegeoip.app/json')

Это просто обходной путь, но он работает. Используйте его даже для того, чтобы понять, связана ли ошибка с CORS или чем-то еще.

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