是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口)
浏览器限制脚本内发起的跨源 HTTP 请求
,一般来说就考虑js引起的跨域,当然其他情况也会发生cors
比如
Web 字体(CSS 中通过 @font-face 使用跨源字体资源)
来源于MDN
如果在a源下访问b源,如果这两者的协议、域名(包括子域名)
、端口有任何一个不一样,那么浏览器就认为这是跨域请求,如果后端有处理,则可以cors
比如这样:我在https:goole.com
的控制台中,通过fetch访问fetch('https://myaccount.google.com')
他的子域名,这同样是一个cors请求,并且https://myaccount.google.com
不允许cors
CORS 预检请求用于检查服务器是否支持 CORS 协议,并且是否允许使用特定的方法和标头。当进行cors访问时,浏览器会对一些非简单请求
自动发送一个options请求
它一般是用了以下几个 HTTP 请求标头的 OPTIONS 请求:Access-Control-Request-Method 和 Access-Control-Request-Headers,以及可选的 Origin 标头。
当options的响应头反馈能够继续的时候,真正的请求才会成功的响应,既允许cors,当然这个请求本身还得支持cors
app.options('/{*any}', (req, res) => {
const allowedMethods = ['GET', 'POST', 'PUT', 'DELETE']
const allowedHeaders = ['Content-Type', 'Authorization', 'fx']
res.header('Access-Control-Allow-Headers', /* allowedHeaders.join(',') */ '*')
const origin = req.headers.origin // 发起请求的源{协议+域名+端口}
// 判断请求的 Origin 是否在允许的列表中
res.header('Access-Control-Allow-Origin', '*')
// 设置允许的请求方法
res.header('Access-Control-Allow-Methods', allowedMethods.join(','))
// 允许浏览器缓存 OPTIONS 请求的响应, 这不同于http缓存(强缓存和协商缓存)
// 当过期前,浏览器都不会自动发送options请求了
res.header('Access-Control-Max-Age', 0)
return res.sendStatus(200)
})
// 即使对options的响应头进行了设置,那么还是得对真正的请求也进行cors设置
// 但如果只对真正的请求进行了cors设置,没有对options进行设置,这么也会导致发生跨域错误
app.put('/foo', cors(), (req, res) => {
res.send('Hello World!')
})
当服务器向上面这样处理后,发送跨域请求时options请求就会拉到如下的响应头
fetch('http://localhost:3000/foo', {
method: 'put',
// 复杂请求,当跨域时,浏览器会自动发送一个options请求
headers: {
fx: 'xxxx',
},
})
并且真正的请求也能够正常访问了
这也是一种方案用于解决cors,本质是通过服务器去访问领一个源的请求,从而避免了cors,因为cors只在浏览器才会发生,如果是服务器去访问另一个服务器的请求是能够正常访问的,不存在cors
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:3000/',
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
})