Say your Node app sits behind a proxy or a load balancer. How do you get the real client IP without getting spoofed, and how does a WebSocket upgrade survive that hop?
Good candidates treat forwarded headers as untrusted until a proxy they control rewrites them, and can walk a WebSocket upgrade through the stack.
Behind a proxy the TCP connection Node sees is coming from the proxy, so req.socket.remoteAddress is going to hold the proxy's address, not the client's. The real client IP shows up in the X-Forwarded-For header, which proxies add to record the original client address. In Express you set trust proxy and then req.ip reads from that header. For WebSockets, they start out as a normal HTTP request that carries an Upgrade: websocket header, and the server answers with a 101 status to switch protocols. After that the same TCP connection just carries WebSocket frames. Libraries like ws do the handshake for you by listening on the server's upgrade event. Your proxy has to pass those upgrade headers through or the WebSocket connection fails. And you should only trust the forwarded headers when they come from your own proxy, I think that's the main gotcha.