Restivus非200状态码时缺失Access-Control-Allow-Origin跨域头问题
200状态码下请求正常,是因为这类请求走完了Restivus完整的路由处理流程,你配置的defaultHeaders会被自动追加到响应上;而无效Token触发的401、参数校验失败触发的400/422这类错误,是在请求进入你定义的业务处理逻辑之前,就被Restivus内置的鉴权、校验层直接拦截返回了,这部分响应不会自动套用你配置的defaultHeaders,也不会触发你写的仅处理OPTIONS请求的defaultOptionsEndpoint逻辑,最终返回给浏览器的错误响应里没有CORS必需的响应头,就触发了跨域拦截报错。
另外你的配置存在一处不符合CORS规范的问题:Access-Control-Allow-Origin: *和Access-Control-Allow-Credentials: true不能同时使用,携带凭证(包括Authorization头、Cookie)的跨域请求不允许将允许源设置为通配符,如果后续需要做带凭证的请求,需要将该值动态设置为当前请求的源地址。
1. 新增全局响应钩子统一注入CORS头
Restivus没有提供全局错误响应头的配置能力,你需要通过Meteor内置的WebApp模块,在API路径的最前置处理逻辑里统一设置CORS头,保证不管后续返回什么状态码,头信息都已经被写入响应。将以下代码添加到服务端入口文件中:
import { WebApp } from 'meteor/webapp'; WebApp.connectHandlers.use('/api/', (req, res, next) => { // 统一写入CORS头 const corsHeaders = { "Access-Control-Allow-Origin": "*", // 若需要支持带凭证的请求,注释掉上一行,启用下面的动态源配置 // "Access-Control-Allow-Origin": req.headers.origin || "", "Access-Control-Allow-Credentials": "true", "Access-Control-Allow-Headers": "Origin, X-Requested-With, Content-Type, Accept, Authorization, client-id, client-secret, client_id, client_secret", "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS" }; Object.entries(corsHeaders).forEach(([key, value]) => res.setHeader(key, value)); // 统一处理OPTIONS预检请求,直接返回204状态码,无需进入后续路由逻辑 if (req.method === 'OPTIONS') { res.writeHead(204); res.end(); return; } next(); });
2. 清理Restivus中的冗余配置
- 删除Restivus配置中的
defaultOptionsEndpoint项:你原来配置的OPTIONS请求返回201状态码不符合规范,且全局钩子已经统一处理了预检请求,保留会产生冲突。 - 删除
defaultHeaders中重复的CORS相关配置,避免重复设置响应头产生冲突。
修改完成后重启服务,无论是正常200响应,还是401/400/422等错误响应,响应头中都会携带Access-Control-Allow-Origin字段,浏览器不会再报CORS头缺失的错误。
内容的提问来源于stack exchange,提问作者StormTrooper

