【问题标题】:Angular returns preflight CORS error, no errors with other toolsAngular 返回预检 CORS 错误,其他工具没有错误
【发布时间】:2021-05-03 20:42:40
【问题描述】:

我必须从托管在在线外部服务器上的 json 获取数据。网址看起来像http://example.com/path/to/resource.json。我可以通过浏览器、邮递员和其他工具读取这个 json。

但是当我尝试从 Angular 11 应用程序中获取数据时,我收到了 CORS 错误:

Access to XMLHttpRequest at 'http://example.com/path/to/resource.json'
from origin 'http://localhost:4200' has been blocked by CORS policy:
Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.

代码实际上只是带有HttpClient 类的GET:

this.http.get('http://example.com/path/to/resource.json)'

我尝试的是配置代理但没有成功:

// proxy.conf.json
{
    "/path": {
        "target": "http://example.com",
        "secure": false
    }
}

// angular.json
"serve": {
  [...]
  "options": {
    [...]
    "proxyConfig": "proxy.conf.json"
  },
  [...]
},

这两个文件都在项目的根文件夹中。

我对服务器没有控制权,所以我不能允许 CORS 或更改其他设置,但我认为这不是问题。

我不明白为什么我可以通过许多工具访问资源,但我在使用 Angular 时总是遇到问题。

【问题讨论】:

  • 由于您无法控制服务器,我建议您查看此帖子。 stackoverflow.com/questions/35588699/…
  • CORS 实际上不是 Angular 问题 - 它是需要它的浏览器(以及执行 OPTIONS 预检的浏览器)。为了让您的代理工作,您必须使用相对路径,所以 this.http.get('/path/to/resource.json)'
  • 在运行应用程序时尝试使用扩展程序。比如这个:Allow CORS: Access-Control-Allow-Origin
  • 所以这不是 Angular 问题,它只是一些浏览器块。我尝试了一个 Chrome 扩展程序,它可以工作,但我只能将它用于开发。有没有办法让它在没有浏览器扩展的情况下从 Angular 代码中工作?我需要将项目展示给其他人,我不能强制安装浏览器扩展。为什么使用其他工具我可以毫无问题地获取资源,但它不适用于使用 HttpClient 的 Angular?

标签: angular cors angular-httpclient preflight


【解决方案1】:

引用MDN Web Docs on CORS

谁应该阅读这篇文章?

每个人,真的。

我同意并强烈建议阅读that page。它将极大地帮助您了解发生了什么以及为什么以及如何正确处理。

我不明白为什么我可以通过许多工具访问资源,但我在使用 Angular 时总是遇到问题。

首先:这不是 Angular 的问题,而只是浏览器的安全功能。

但简而言之:在浏览器中从您的 (Angular) Web 应用调用 API 会导致 跨域请求,因为 Web 应用是在与外部 API。这将导致浏览器首先触发 preflight 请求,询问外部 API 服务器是否允许来自您的 Web 应用程序的跨域请求。如果不是这种情况,则请求被浏览器阻止。

当您直接在浏览器或类似工具中访问 API 时,会直接访问 URL,并且浏览器/工具不会像 CORS 请求那样发出预检请求。

基本上有两种方法可以解决这个问题:

  1. 分别在 API 服务器上配置 CORS - 由于您无法控制 API 服务器,因此已将其消除
  2. 使用代理服务器,例如Angular proxy

在第一种情况下,您无需更改前端代码中的任何内容,在后一种情况下,您需要更改前端中的 URL 以访问代理服务器,即

this.http.get('http://example.com/path/to/resource.json')

变成

this.http.get('/path/to/resource.json')

(假设您的代理与您的 Angular 应用程序在同一源下运行)

但同样,我建议阅读MDN Web Docs on CORS 以获得更好的理解!

【讨论】:

    猜你喜欢
    • 2015-08-10
    • 2020-10-26
    • 1970-01-01
    • 2019-04-11
    • 1970-01-01
    • 2019-12-12
    • 2017-08-01
    • 2018-01-05
    • 2011-11-17
    相关资源
    最近更新 更多