静态HTML页面使用原生JavaScript获取远程JSON元数据时跨域请求被阻止的原因问询
解决跨域Fetch请求的CORS错误问题
问题分析
你碰到的这个Cross-Origin Request Blocked错误,核心原因是**浏览器的同源策略(Same Origin Policy)**在起作用:
- 当你直接在浏览器地址栏访问
URL_SOURCE时,这属于浏览器发起的「普通导航请求」,浏览器不会触发CORS校验,所以能正常拿到JSON数据。 - 但通过原生JavaScript的
fetch发起请求时,这属于「跨域AJAX/Fetch请求」,浏览器会强制校验目标服务器返回的响应头,要求必须包含Access-Control-Allow-Origin字段,用来明确允许哪些域名的页面可以访问该资源。如果服务器没返回这个头,浏览器就会拦截请求,抛出你看到的错误。
另外顺便提一句,你的代码里还有个小bug:data变量是在fetch的回调里赋值的,但外面的if (data)判断会在fetch请求完成前执行,所以永远是undefined,根本走不到后续的逻辑。这个问题和CORS无关,但也是需要修正的点。
解决方案
针对CORS错误,你可以根据实际情况选择以下方案:
1. 配置目标服务器添加CORS响应头(最优解)
如果URL_SOURCE是你自己维护的服务器,直接在服务器端添加Access-Control-Allow-Origin响应头即可:
- 允许所有域名访问:设置
Access-Control-Allow-Origin: * - 仅允许你的静态页面域名访问:比如你的页面部署在
https://your-static-page.com,就设置Access-Control-Allow-Origin: https://your-static-page.com
不同服务器的配置方式不同,比如Nginx、Apache、Node.js Express都有对应的配置方法,根据你的服务器类型调整即可。
2. 使用代理服务器中转请求(第三方API场景)
如果URL_SOURCE是第三方服务,你无法修改它的CORS配置,那可以自己搭建一个简单的代理服务器:
- 代理服务器和你的静态页面同源(比如部署在同一个域名下)
- 由代理服务器去请求
URL_SOURCE,然后把响应返回给你的页面 - 因为页面和代理服务器同源,就不会触发CORS校验
举个简单的Node.js代理示例(用express和http-proxy-middleware):
const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const app = express(); app.use('/proxy', createProxyMiddleware({ target: 'https://example.source.host', changeOrigin: true, pathRewrite: { '^/proxy': '' } })); app.listen(3000, () => console.log('Proxy server running on port 3000'));
然后你的前端代码里把URL_SOURCE改成http://localhost:3000/proxy即可。
3. 临时禁用浏览器CORS校验(仅开发测试用)
如果你只是在本地开发测试,可以临时关闭浏览器的CORS校验:
- Chrome:启动时添加参数
chrome.exe --disable-web-security --user-data-dir="C:/ChromeDevSession"(注意路径自行调整) - Firefox:可以安装CORS相关的插件(比如CORS Everywhere)
⚠️ 注意:这个方法只能用于本地开发,绝对不能在生产环境使用,会带来安全风险。
修正你的代码异步问题
把原来的代码调整一下,把数据处理逻辑放到fetch的异步流程里,确保能拿到返回的数据:
const URL_SOURCE = 'https://example.source.host'; const doGetMetaDataEvent = async () => { setInterval(async () => { try { const response = await fetch(URL_SOURCE, { method: 'GET', headers: { // some headers } }); const data = await response.json(); console.log('JSON response:', data); const nowData = data?.response?.informationjson?.getNowData; console.log('Listening to:', nowData?.songtitle); } catch (error) { console.error('Error data source or processing:', error); } }, 10000); } doGetMetaDataEvent() .then(() => console.log("Render meta data successful")) .catch(e => console.log('error response ', e.message));
内容的提问来源于stack exchange,提问作者haoz
相关产品推荐
相关产品推荐

