博客 / 詳情

返回

node server響應頭設置允許跨域,卻仍然存在跨域問題的解決方案

案例

今天在做全棧的練習項目時,發現在發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文檔發現有這三種情況會發送預請求:

  1. 請求方法不是GET/POST/HEAD
  2. 設置了默認請求頭意外的自定義請求頭
  3. POST請求中的content-type不是

    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

然而我們所用的axios發送的請求默認的content-type是application/json,所以理所當然需要去發送這個預請求,那麼只需要讓這個預請求跨域通過就好了

解決方案

  1. 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')
    })
  2. 添加一個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()
    })
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.