【发布时间】:2018-05-03 17:49:56
【问题描述】:
我正在尝试进行外部 api 调用,但遇到了 CORS 问题。我可以使用 Postman 访问 api,但是从我的 Angular 客户端尝试时,我得到了
'对预检请求的响应未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。因此,Origin 'http://localhost' 不允许访问。响应的 HTTP 状态代码为 405。'
这是我拨打电话的方式
let params = new HttpParams()
.set('id', itemId)
let headers = new HttpHeaders()
.set('Content-Type', 'application/json')
.set(this.apiKeyHeaderName, this.apiKey);
let result = this.http.get<T>(this.url,
{ params: params, headers: headers }).share();
// do stuff with result
在 Chrome 网络选项卡 > 预览中检查呼叫时,我看到错误消息
请求的资源不支持http方法'OPTIONS'
我知道 'Content-Type'、'application/json' 会触发预检请求,我正在尝试更好地理解错误消息并查看代码中需要更改哪些内容才能使请求生效。
这是请求标头
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Access-Control-Request-Headers: content-type, api-key
Access-Control-Request-Method: GET
Connection: keep-alive
Host: xxxxxxxxxx
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36
我看到没有设置 Access-Control-Allow-Origin,这就是我们收到该错误的原因,但为什么呢?如何配置设置?
请求的资源不支持 http 方法 'OPTIONS' “请求的资源”到底指的是什么?我假设这是我这边的事情,因为我可以使用 Postman 访问 api。
我做了一些研究并添加到我的 Web.config 中
<security>
<requestFiltering>
<verbs>
<add verb="OPTIONS" allowed="true" />
</verbs>
</requestFiltering>
</security>
和
<customHeaders>
…
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE,OPTIONS" />
…
</customHeaders>
和
<handlers>
<!-- <remove name="OPTIONSVerbHandler" /> -->
</handlers>
但是没有任何效果。这些对 Web.config 的更改实际上是否对我的应用程序如何发出请求做任何事情,或者这是否仅与我拥有自己的 api 并管理对它的请求的处理方式有关?
--- 已回答,我需要从后端拨打电话,这样我就不会遇到 CORS 问题 ---
【问题讨论】:
-
如果您向无法控制的外部 API 端点发出请求,那么您无法在自己的客户端代码中执行任何操作来解决问题中描述的问题。如果服务器使用 405 或 2xx 成功代码以外的任何内容响应 OPTIONS 请求,您将永远无法从前端 JavaScript 代码直接向该服务器发出请求。而且,您在自己的服务器后端执行什么 CORS 配置并不重要——而是需要在托管您发送请求的 API 端点的第三方服务器上更改 CORS 配置。
-
您唯一的选择是从您的后端/服务器端代码发出请求,并在那里使用响应。因为在这种情况下,一开始不会发出 OPTIONS 请求,更广泛地说,没有浏览器施加跨域限制。 (因为浏览器是跨域限制和评估任何 CORS 协议放松 API 端点服务器可能表明它选择加入的限制的执行点。)
-
我同意@sideshowbarker,我将不得不从我的后端代码中执行此操作。我只需要了解为什么它应该是这样的,感谢您的帮助!