Node.js自學筆記 (11/12):CORS

使用CORS

安裝套件CORS

npm install cors

使用方式:

var cors = require('cors')
app.use(cors())

建立一html檔:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <div class="" id="info"></div>
    <script>
        fetch('http://localhost:3000/address-book/api/list/2')
        .then(r=>r.json())
        .then(obj=>{
            console.log(obj);
            info.innerHTML = JSON.stringify(obj);
        })
    </script>
</body>
</html>

從live-server開啟此html檔去讀取address book API資料,若沒有設定CORS,就會無法讀取。設定CORS後,才可以正常讀取。

Session議題

將上述的html檔的fetch目標從 http://localhost:3000/address-book/api/list/2 改為 http://localhost:3000/try-session

會發現session無法正常,因為每次fetch進去,對方server都將我視為不同的使用者。

解決方法,在fetch的第二個引數加上:

{credentials: 'include'}

重新測試後,得到另一個錯誤訊息:

錯誤訊息:Access to fetch at 'http://localhost:3000/try-session' from origin 'http://127.0.0.1:5500' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

意思是說,當 credentials modeinclude 的時候,CORS的設定不可以是所有主機 *,只能指定特定的主機。

解決方法:使用白名單

可以到CORS的NPM官網,搜尋關鍵字「whitelist」。

參考範例:

var express = require('express')
var cors = require('cors')
var app = express()
 
var whitelist = ['http://example1.com', 'http://example2.com'] // 設定允許的主機
var corsOptions = {
  origin: function (origin, callback) {
    if (whitelist.indexOf(origin) !== -1) {
      callback(null, true)
    } else {
      callback(new Error('Not allowed by CORS'))
    }
  }
}
 
app.get('/products/:id', cors(corsOptions), function (req, res, next) {
  res.json({msg: 'This is CORS-enabled for a whitelisted domain.'})
})
 
app.listen(80, function () {
  console.log('CORS-enabled web server listening on port 80')
})

indes.js 的cors相關的程式改為:

const whitelist = [undefined, 'http://127.0.0.1:5500', 'http://localhost:5500'];
const corsOptions={
    credentials:true,
    origin: function(origin, cb){
        console.log(origin);
        if (whitelist.indexOf(origin) !== -1){
            cb(null, true);
        }else{
            cb(null, false); // 設定檔頭,不要噴錯
        }
    }
}
app.use(cors(corsOptions));