前端日志上报时为什么总是触发跨域错误?
我在页面里用fetch发送错误日志到后端,但总是被浏览器拦截,显示跨域错误。尝试过加mode:’no-cors’和设置headers,但后端还是收不到数据…
<img src="broken.jpg"
onload="logEvent('image_loaded')"
onerror="logError('image_failed')">
<script>
function logError(msg) {
fetch('http://api.example.com/log', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ error: msg })
})
}
</script>
测试时发现图片加载失败会触发logError,但控制台报错”Failed to load response data”,后端日志也完全没有记录。用postman直接发同样的请求却没问题,到底是哪里设置错了?
这里有几个关键点要改:
1. 后端必须正确配置CORS响应头,至少包含
Access-Control-Allow-Origin2. 前端的mode要用'cors'(或者干脆不写,默认就是cors)
3. 记得处理错误响应
我帮你重构下代码:
至于后端,如果是Node.js的话至少要加这些响应头:
另外建议把日志上报改用
navigator.sendBeacon方案,这样即使页面卸载也能保证上报成功。不过要注意这个API不能自定义请求头,得和后端约定好数据格式。调试的时候记得先看浏览器Network面板里的Preflight请求(OPTIONS方法)是否通过,这才是跨域问题的关键。
前端代码改成这样:
关键点在mode: 'cors',浏览器会先发OPTIONS预检请求,然后根据后端返回的CORS头决定是否允许请求。
后端必须设置这些响应头(以Node.js为例):
这几个头告诉浏览器:我允许跨域、允许POST、允许Content-Type头。你要是用其他后端框架,比如Java/Python/PHP,也照着这三个头配就行。
要是还收不到请求,先看浏览器Network面板里有没有OPTIONS请求,没有的话说明请求根本没发出去。有的话看下后端有没有收到OPTIONS请求,根据响应码判断CORS有没有配好。