跨域这个问题还得单独揪出来说一下

跨域,一个说腻了的话题,今天遇到一个新的情况,单独拎出来说说;

情景再现

b.site有一个ajax请求a.site的某一个地址,post请求+自定义header(假设,header头为X-Application-Token),ok,妥妥的跨域,那么自然加上以下代码(以express.js为例):

app.options('*', (req, res, next) => {
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Headers", "X-Application-Token")
    // call the path service
})
app.post('/a-cors-request-path', (req, res) => {
    res.header("Access-Control-Allow-Origin", "*")
    res.header("Access-Control-Allow-Headers", "X-Application-Token")
    // call the path service
})

反复确认了相关配置已经设置好,但浏览器仍报错:

Access to XMLHttpRequest at 'a.site' from origin 'b.site' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.

排查

  1. 返回说"not have HTTP ok status"

那么说明option请求没有返回200,打开postman发送请求尝试看看,成功返回...

  1. 自己启动一个Express Server,尝试复现

已经能够确认,option不通过和状态码有关,那么为什么浏览器内非200,而postman发送option请求正常返回200 ?

打印headers,一口老血...

cors-with-verify-header

结论

除了常见的跨域问题,也要考虑实现时的业务逻辑,比如本情境下,错误的在option中也调用相关服务验证了X-Application-Token,而option请求在浏览器内是不会携带额外的header信息的,这才导致了浏览器内 not HTTP ok status,而postman正常的原因.

额外

后来利用老的Microsoft Edge浏览器(Edge legacy)调试,发现会清楚的返回400 Bad Request,所以如果option请求能够返回精确的HTTP code,也会更利于开发人员排查问题,后续修改后完美解决.

跨域这个问题还得单独揪出来说一下
本文作者
spark1e
发布于
2020-09-23
许可协议
转载或引用本文时请遵守许可协议,注明出处、不得用于商业用途!
评论区 - Powered by Giscus