案例
今天在做全棧的練習項目時,發現在發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() })