最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

node.js - Socket.io doesn't work on secure (tlsssl) connection - Stack Overflow

programmeradmin0浏览0评论

I am developing an web app that utilize Socket.io for communication between client's browser and backend. For the environment, I ran both backend and frontend under single container, and it works without issue on local environment (both under docker and not under docket). BUT, when I deploy them on production that uses https, the socket.io doesn't work any more. For context :

backend setup

import { createServer } from 'http'
const app = express()
const server = createServer(app)
const allowedOrigins = [
    '',
    'http://my-frontendip:5177',
    'http://localhost:5173',
    'http://localhost',
    'http://127.0.0.1:8080',
    'http://127.0.0.1:8000',
    'http://127.0.0.1:5713',

]
const io = new Server(server, {
    transports: ['websocket'],
    cors: {
        origin: function (origin, callback) {
            if (!origin) return callback(null, true); // Allow non-browser requests (e.g., Postman)
            if (allowedOrigins.indexOf(origin) === -1) {
                const msg = 'The CORS policy for this site does not allow access from the specified Origin.';
                return callback(new Error(msg), false); // Pass error to callback
            }
            return callback(null, true);
        },
        credentials: true,
    },
    pingTimeout: 25000,
    pingInterval: 60000
})
app.use(cors({
    origin: function (origin, callback) {
        if (!origin) return callback(null, true); // Allow non-browser requests (e.g., Postman)
        if (allowedOrigins.indexOf(origin) === -1) {
            const msg = 'The CORS policy for this site does not allow access from the specified Origin.';
            return callback(new Error(msg), false); // Pass error to callback
        }
        return callback(null, true);
    },
    credentials: true,
}))
io.use((socket, next) => {
    console.log('Socket Handshake Query:', socket.handshake.query);
    console.log('Socket Handshake Auth:', socket.handshake.auth);
    next();
});

io.use(Mid.socketToken)
mongoose.connect(process.env.MONGO_URI)
.then(() => {
    socketCycle(io)
})

server.listen(PORT, '0.0.0.0', () => {
    console.log(`Socket & Server is running on port ${PORT}`)
})

This is my socketCycle

export const socketCycle = (io) => {

    io.on('connection', (socket) => {
        console.log('A user connected', new Date().toISOString());
        const connectionCount = io.sockets.sockets.size;
        console.log(`Total connections: ${connectionCount}`, new Date().toISOString());

        socket.on('greet', (data, callback) => {
            console.log('greet', data)
            callback({ status: 'hello' })
        })

        socket.on('room/join', (room, callback) => {
            socket.join(room);
            callback({ status: 'ok' });
            console.log('Room joined:', room, new Date().toISOString());
        })
        socket.on('disconnect', () => {
            console.log('A user disconnected', new Date().toISOString());
        })
    })
    io.engine.on("connection_error", (err) => {
        console.log("Header Socket", err.req.headers);
        console.error('Connection Error:', err.code, err.message, err.context);
    });
    io.engine.on('initial_headers', (headers, req) => {
        console.log('Initial Headers:', headers);
    });
    
    io.engine.on('headers', (headers, req) => {
        console.log('Response Headers:', headers);
    });
}

frontend

      const newSocket = io(import.meta.env.VITE_SOCKET_URL, {
        transports: ['websocket'],
        withCredentials: true,
        auth: { token },
        secure: true,
      });

Both end use socket.io(-client for frontend) version 4.8.1. And again, the app works fine when communicating over https. BUT the socket isn't. Somehow it the connection keep failing.

This is the log from io.engine.on('connection_error')

Header Socket {
  host: 'localhost:8088',
  'cf-ray': '90d768df3d1cfdbe-SIN',
  'x-forwarded-for': '103.166.234.12, 172.70.208.141',
  'cf-connecting-ip': '103.166.234.12',
  'accept-encoding': 'gzip, br',
  'x-forwarded-proto': 'https',
  'sec-websocket-extensions': 'permessage-deflate; client_max_window_bits',
  'cf-ipcountry': 'ID',
  'cf-visitor': '{"scheme":"https"}',
  'sec-websocket-key': 'BE1glAV94/gHYG4Ritwy/g==',
  'sec-websocket-version': '13',
  'cdn-loop': 'cloudflare; loops=1',
  authorization: 'Bearer <jwt bearer>',
  'x-forwarded-host': '<backend-host>',
  'x-forwarded-server': '<backend-host>',
  connection: 'Keep-Alive'
}
Connection Error: 3 Bad request { name: 'TRANSPORT_HANDSHAKE_ERROR' }

The only similar issue I found online is from socket.io's github issue. .io/issues/4916#issuecomment-1881453706 But I think the asker has different deployment environment from me. So I don't know where to go.

Other alternative I found is to run the socket on different port than the app itself, and then connect it via ws. I have tried that and it works (via Postman), but if possible I want to prioritize using secure connection for this app, not to mention somehow I cannot force the frontend to use ws instead of wss, so it keep fail when trying to connect to socket connection because it ran on ws.

I hope my explanation is easy to understand, Thank you in advance

TL;DR Socket.io connection keep failing with error TRANSPORT_HANDSHAKE_ERROR in secure (tls/ssl) environment

发布评论

评论列表(0)

  1. 暂无评论