案例
明天在做全栈的练习我的项目时,发现在发 POST 申请时,存在跨域问题(server 的 header 设置了容许跨域),server 大略如下
const express = require('express')
const app = express()
app.use(express.json());
app.use(express.urlencoded({ extended: false}));
app.post('/login', (request, response) => {
// 容许跨域
response.setHeader('Access-Control-Allow-Origin','*')
response.setHeader('Access-Control-Allow-Headers','*');
response.send('Hello')
})
前端是用 axios
发送的 ajax
申请,这里会有一点影响,然而重点不在这,所以这里不贴代码。
起因剖析
点开浏览器的 network
调试界面,发现除了 post
申请还有一个 options
申请,而后看看 console
里的报错信息
Access to XMLHttpRequest at 'http://127.0.0.1:8000/login' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No'Access-Control-Allow-Origin' header is present on the requested resource.
果然发现是 preflight request
的问题,也就是这个 options
申请的跨域没有通过。
那又为什么会有这个 preflight
呢?参考 CORS 文档发现有这三种状况会发送预申请:
- 申请办法不是 GET/POST/HEAD
- 设置了默认申请头意外的自定义申请头
-
POST 申请中的
content-type
不是- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
然而咱们所用的 axios 发送的申请默认的 content-type 是application/json
,所以天经地义须要去发送这个预申请,那么只须要让这个预申请跨域通过就好了
解决方案
-
server 改路由规定(post->all)
最暴力的办法,间接将跨域给到 all 申请类型,所以预申请的 options 必定是可能跨域的app.all('/login', (request, response) => { // 容许跨域 response.setHeader('Access-Control-Allow-Origin','*') response.setHeader('Access-Control-Allow-Headers','*'); response.send('Hello') })
-
增加一个 options 的路由规定
这个就是隔靴搔痒的办法,在下方独自增加一条新的规定,应用 options 申请类型app.post('/login', (request, response) => { // 容许跨域 response.setHeader('Access-Control-Allow-Origin','*') response.setHeader('Access-Control-Allow-Headers','*'); response.send('Hello') }) app.options('/login', (request,response) => {response.setHeader("Access-Control-Allow-Origin","*") response.setHeader("Access-Control-Allow-Headers", "*"); response.end()})