Socket.IO WebSocket upgrade 與負載平衡分流示意圖

← INSIGHTS & PERSPECTIVES | 後端開發

Socket.IO 自行增加 Header:Server CORS 與 Client extraHeaders 設定

說明 Socket.IO 如何在 server 設定 CORS header,並在 Node.js client 用 extraHeaders 帶自訂 Origin。

Socket.IO 要自行增加 header,server 端通常要先處理 CORS 與 preflight 回應,Node.js client 則可用 `extraHeaders` 帶入自訂 header。若 client 跑在瀏覽器,而且只啟用 WebSocket transport,瀏覽器 WebSocket API 不允許任意設定自訂 header,因此 `extraHeaders` 會被忽略。

Socket.IO 自行增加 Header 要先分清楚 server 與 client

Socket.IO 自訂 header 分成兩個方向:server 回應瀏覽器跨來源請求的 CORS header,以及 client 連線時送到 server 的 request header。兩者設定位置不同,不能混在同一段程式碼判斷。

我當時的筆記把問題拆成「伺服器端」與「socket io client」兩段,這個拆法是對的。實作時可以先問兩件事:

問題應該處理的位置
瀏覽器因 CORS 被擋,要允許來源、header 或 credentialsSocket.IO server 的 CORS 設定
Node.js client 要在握手或 polling request 帶自訂 headerSocket.IO client 的 `extraHeaders`
瀏覽器 client 要帶 cookie同源 cookie、CORS `credentials` 與 `withCredentials`
瀏覽器 WebSocket 要帶任意自訂 header通常不可行,需改用 query、auth 或 cookie

Socket.IO v4 官方文件說明,`extraHeaders` 會出現在 server 端的 `socket.handshake.headers`;但瀏覽器只用 WebSocket transport 時,因 WebSocket API 限制,`extraHeaders` 會被忽略(Socket.IO Docs,Client options,存取日期 2026-08-28)。

伺服器端如何回應 CORS header?

Socket.IO server 若要允許跨來源連線,應明確設定允許的 origin、headers 與 credentials。Socket.IO v3 之後需要顯式啟用 CORS,不建議在正式環境直接放開所有來源。

當時的伺服器端範例程式碼如下:

```js

import express from "express";

import http from "http";

const app = express();

const server = http.createServer(app);

const sio = require("socket.io")(server, {

handlePreflightRequest: (req, res) => {

const headers = {

"Access-Control-Allow-Headers": "Content-Type, Authorization",

"Access-Control-Allow-Origin": req.headers.origin, //or the specific origin you want to give access to,

"Access-Control-Allow-Credentials": true

};

res.writeHead(200, headers);

res.end();

}

});

sio.on("connection", () => {

console.log("Connected!");

});

server.listen(3000);

```

如果是 Socket.IO v4,比較建議改成 `cors` 選項,並列出允許的來源與 header:

```js

import { createServer } from "http";

import { Server } from "socket.io";

const httpServer = createServer();

const io = new Server(httpServer, {

cors: {

origin: ["https://example.com"],

allowedHeaders: ["Content-Type", "Authorization"],

credentials: true,

},

});

```

Socket.IO 官方文件提醒,啟用 `credentials: true` 時不能搭配 `origin: "*"`,否則瀏覽器會因 CORS credentials 規則拒絕請求(Socket.IO Docs,Server options,存取日期 2026-08-28)。

`origins: ':'` 與 `io.set('origins')` 還適合使用嗎?

`origins: ':'` 與 `io.set('origins', ':')` 屬於舊版 Socket.IO 常見寫法。整理舊專案時可以保留作為遷移線索,但新專案應優先使用 v4 的 `cors.origin`。

我當時的筆記保留的兩種寫法如下:

```js

var io = require('socket.io')(server, { origins: ':'});

```

或者:

```js

io.set('origins', ':');

```

如果只是本機測試,放開 origin 可以快速排除 CORS 問題;如果是正式環境,建議改成白名單。Socket.IO v4 的 server options 文件也特別標示選項名稱是 `origin`,不是 `origins`,即使允許多個網域也一樣使用 `origin: [...]`。

Node.js Socket.IO client 如何用 extraHeaders?

Node.js Socket.IO client 可以用 `extraHeaders` 送出自訂 request header。這個方法適合後端服務、CLI 工具、React Native 或測試程式,不適合拿來突破瀏覽器安全限制。

當時的 socket io client 範例保留如下:

```js

const socket = require('socket.io-client')(host,{

forceNode:true,

transports: ['websocket'],

extraHeaders: {

Origin: Origindata

},

transportOptions: {

polling: {

extraHeaders: {

Origin: Origindata

}

}

}

});

```

這段程式的重點有兩個:

  1. `extraHeaders` 會套用在底層連線請求。
  2. `transportOptions.polling.extraHeaders` 可以只針對 polling transport 設定 header。

若需要跨站攜帶 cookie,Socket.IO v4 client 另有 `withCredentials: true`;官方文件也註明,從 Socket.IO v4.7.0 開始,Node.js client 設定 `withCredentials` 後會在 HTTP request 中包含 cookies,較容易搭配 cookie-based sticky session(Socket.IO Docs,Client options,存取日期 2026-08-28)。

瀏覽器端為什麼不能任意加 WebSocket header?

瀏覽器端 Socket.IO client 不能把 `extraHeaders` 當成萬用解法。當瀏覽器只啟用 `transports: ['websocket']` 時,WebSocket API 不開放自訂 request headers。

如果前端需要傳遞身份或來源資訊,可以改用這些方式:

需求建議做法
傳遞登入狀態使用 cookie 搭配 `withCredentials` 與 server `credentials: true`
傳遞 token使用 Socket.IO `auth` 或安全的短期 token
傳遞非敏感參數使用 `query`,但不要放機密資訊
控制可連線來源在 server 設定 CORS `origin` 或 `allowRequest`

資訊增益:如果問題是在瀏覽器連線失敗,不要只照 Node.js client 範例加 `extraHeaders`。先打開瀏覽器 Network 面板,確認實際 request 是否是 polling 還是 websocket,再看 header 是否真的送出。

延伸閱讀

常見問題

Socket.IO 自訂 header 常見問題多半卡在執行環境差異:Node.js client 可以加 header,瀏覽器 client 則受 WebSocket API 與 CORS 規則限制。先確認環境,再選設定方式。

QSocket.IO client 的 `extraHeaders` 在瀏覽器可以用嗎?

Socket.IO client 的 `extraHeaders` 在瀏覽器不是完整可用。若瀏覽器只使用 WebSocket transport,自訂 header 會被忽略;Node.js、React Native 等非瀏覽器環境才適合用 `extraHeaders`。

QSocket.IO v4 要怎麼設定允許跨來源?

Socket.IO v4 建議在 server 使用 `cors` 選項,例如 `origin`、`allowedHeaders` 與 `credentials`。如果需要帶 cookie,不可以把 `origin` 設成 `"*"`。

Q`Access-Control-Allow-Origin` 可以直接回傳 request origin 嗎?

技術上可以,但正式環境應先檢查 request origin 是否在白名單內。直接反射所有來源等於降低 CORS 保護,適合臨時除錯,不適合長期上線。

Q`transports: ['websocket']` 會影響 header 嗎?

會。瀏覽器 WebSocket API 不允許設定任意自訂 header,所以只用 `websocket` 時,瀏覽器端的 `extraHeaders` 會被忽略;Node.js client 不受同樣限制。

Q要傳 token 給 Socket.IO server,應該用 header、query 還是 auth?

瀏覽器應優先考慮 Socket.IO `auth` 或 cookie;非敏感資料可用 `query`。Node.js client 才適合用 `extraHeaders` 傳 header,機密 token 仍要注意 log、proxy 與錯誤追蹤系統是否會外洩。

參考資料

本文參考 Socket.IO v4 官方文件與當時的 WordPress 匯出稿。外部來源皆為 HTTPS,並以 2026-08-28 存取內容為準。

關於作者 {#author}

Claire Chang | 企業 AI 導入與流程轉型顧問。專注於 AI Agent 架構設計、ERP 系統整合與企業 AI 治理。

首次發布:2020-03-13