简体   繁体   中英

Error when GET HTTPS from REST API in Angular

I have an Angular app running which uses an external api to get countries ISOs. This API uses https and it's giving me an error.

The thing is: when I use a proxy in my angular local environment, mapping /iso-api/ to the real url it works ok.

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

But I want this to work in production, so I want to use the real url.

In my server I am returning the Access-Control-Allow-Origin: * header already.

I've tried to run the angular server with ssl (as the external api uses https), but I receive the same error.

I know a solution would be to implement the proxy in the server, but I believe this should not be done and there may be a way to retrieve this data from the frontend. Help please.

Response

This is the network error in Chrome : 浏览器网络选项卡

In Firefox , the request ends with 200 OK and returns data, but CORS error is thrown and I cannot access the data from the app: CORS header 'Access-Control-Allow-Origin' missing

General

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

Request headers

: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

Response headers

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

UPDATE

Angular service code

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()
    );
  }

To serve the app I use angular dev server, I do not add the 'Access-Control-Allow-Origin' header manually but, in the browser, I see that it is being added.

Chrome 网络标签

angular.json

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

You cannot bypass CORS browser side. If you are not able to modify the server side, your only solution is to use a proxy.

For development purposes, you can use angular's built-in proxy server, but not for production.

Here is a basic nginx config to do this

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 ...
    }
}

This will redirects requests like

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

Since now client and server API calls are on the same domain, you should not have CORS issues

You can't request a resource from another domain. This would be a security hole. You can read more here: Same-origin policy

Sending Access-Control-Allow-Origin: * from your server won't give you access to the aforementioned API. The provider of this API needs to give you permission to access the API, you can't give yourself this permission.

The error you posted states that the Access-Control-Allow-Origin header is missing. It means that the API isn't sending this header.

There might be two reasons why this API isn't sending Access-Control-Allow-Origin header.

  1. A misconfiguration on the side of this API. In this case you have to ask the provider of this API to fix this issue.
  2. The API provider is restricting access to the API on purpose. In this case you have to ask the provider of this API to give you access from your domain.

You can also proxy the request through your server. The core difference when using proxy is that your server reads the resource from the API and not the client browser. See David's response on how to configure proxy with nginx.

Try the.get call with option withCredentials: true :

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

...and/or making sure your browsers are up to date.

Use this site to resolve the CORS error: https://cors-anywhere.herokuapp.com/

Use Exemple https://cors-anywhere.herokuapp.com/https://freegeoip.app/json

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

It's just a workaround but it works. Use it even just to understand if the error is related to CORS or something else.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM