无法使用 Fetch API 从 localhost 加载 Deezer API 资源
Posted
技术标签:
【中文标题】无法使用 Fetch API 从 localhost 加载 Deezer API 资源【英文标题】:Cannot load Deezer API resources from localhost with the Fetch API 【发布时间】:2018-01-11 00:46:19 【问题描述】:我正在尝试从 localhost 访问 Deezer API,但我不断收到以下错误:
Fetch API cannot load http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem.
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost' is therefore not allowed access.
If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
localhost 的响应标头确实有 Access-Control-Allow-Origin 标头 (访问控制允许来源:*)。
我正在使用 fetch,例如:
fetch('http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem')
.
我做错了什么?
【问题讨论】:
看看这个:***.com/a/20035319/4304132 使用html5rocks-cors.s3-website-us-east-1.amazonaws.com/index.html,它会加载请求,但使用api.deezer.com/search/track/autocomplete?limit=1&q=eminem,它会以同样的方式出错。 api 是否使用access-control-allow-origin: *
响应该请求?还是这个演员 localhost 中的 access-control-allow-origin:<your origin>
?
不使用 cors definitin 将有助于一些标题不需要的 api
【参考方案1】:
向服务器发出的 CORS 或跨域请求
http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem
在这种情况下,所有现代浏览器都启用预检检查。
如果服务器没有以Access-control
标头响应,通常会失败。
如果是fetch
,因为你基本上是在摆弄javascript
,
您需要服务器以灵活的Access-control-Allow-Origin
标头进行响应。
您无能为力,除非 API 本身变得灵活且更开放。
但是,您可以使用 fetch
并将模式设置为 no-cors
IFFF 你只希望缓存你提出的请求的结果,作为响应,而不是自己消费它
阅读Opaque Responses
无CORS定义
no-cors — 防止方法成为 HEAD、GET 或 POST 以外的任何方法。如果任何 ServiceWorkers 拦截了这些请求,它们可能不会添加或覆盖除这些之外的任何标头。此外,JavaScript 可能不会访问结果响应的任何属性。这样可以确保 ServiceWorker 不会影响 Web 的语义,并防止因跨域泄露数据而引起的安全和隐私问题
【讨论】:
请注意,就mode: no-cors
而言,实际上您几乎从不想使用mode: no-cors
。原因是当您为请求设置它时,它会告诉浏览器在任何情况下阻止您的前端 JavaScript 代码对响应进行任何访问。它还告诉浏览器完全阻止您的前端代码向请求添加任何自定义标头。我不确定在实践中您是否可以按照您所说的方式传递来自mode: no-cors
请求的响应。至少据我所知,基本上你能做的就是缓存它(使用服务人员)。
再来一次!很高兴了解更多信息!如果我可能会问,由于服务工作者可以拦截,但不能从这样的响应中读取,如果我要调用另一个 API 并传递不透明的响应,是否会转发整个正文?
据我了解,您不能将不透明的响应传递给任何其他代码,句号。我认为您可以用它做的所有事情就是让服务工作者在处理对它的请求时从其缓存中加载它(而不是重新获取它)。我可能是错的,但我认为这就是它的工作原理【参考方案2】:
您可以通过公共 CORS 代理发出请求;为此,请尝试将您的代码更改为:
fetch('https://cors-anywhere.herokuapp.com/http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem')
通过https://cors-anywhere.herokuapp.com 发送请求,https://cors-anywhere.herokuapp.com 将请求转发到http://api.deezer.com/search/track/autocomplete?limit=1&q=eminem
,然后接收响应。 https://cors-anywhere.herokuapp.com
后端将 Access-Control-Allow-Origin
标头添加到响应中,并将其传递回您的请求前端代码。
然后浏览器将允许您的前端代码访问响应,因为带有Access-Control-Allow-Origin
响应标头的响应是浏览器看到的。
您还可以使用 https://github.com/Rob--W/cors-anywhere/ 轻松设置自己的 CORS 代理
详细了解当您使用 XHR 或 JavaScript 库中的 Fetch API 或 AJAX 方法从前端 JavaScript 代码发送跨域请求时浏览器会做什么,以及有关必须接收哪些响应标头才能让浏览器允许前端代码的详细信息访问回复——请参阅https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS。
【讨论】:
很高兴知道!但是,作为 API 作者,我还能限制我的 API 不响应代理吗?或者代理无论如何都会获取 没有通用的方法来检测请求是来自代理还是来自某人的后端服务器代码。无论如何,它至少在 CORS 配置的范围之外——因为即使 CORS 配置也不会限制您的服务器响应任何请求,而只会影响向响应添加(或不添加)哪些响应标头。至少对于 CORS,完全由浏览器对前端代码发出的请求实施跨域限制。 cors-anywhere 不再可用:cors-anywhere.herokuapp.com/corsdemo【参考方案3】:目前,无法提出此请求。您可以从自己的后端代理对 API 的请求或使用 jsonp。这是一个具有类似 fetch 语法的库 https://github.com/camsong/fetch-jsonp。用法示例https://jsfiddle.net/4dmfo0dd/1/
fetchJsonp('https://api.deezer.com/search/track/autocomplete?limit=1&q=eminem&output=jsonp')
.then(function(response)
return response.json();
)
.then(json => console.log(json))
.catch(function(error) console.log(error); );
【讨论】:
以上是关于无法使用 Fetch API 从 localhost 加载 Deezer API 资源的主要内容,如果未能解决你的问题,请参考以下文章
Javascript fetch 无法从 GMail API Batch 请求中读取 Multipart 响应
Fetch Api 无法从 PHP 服务器获取 Session
React 无法使用 Fetch API 下载数据 [重复]