Proxying WebSockets with Express and node-http-proxy

Hello. It took me more than 2 minutes to find the relevant info online so I decided to put it here for others for a quick reference. I am using Express and node-http-proxy to make a gateway that will also authenticate players for my game and then proxy their WebSocket traffic to the dedicated game server.

tl;dr: Express returns the Node HTTP server instance on which you can listen to an upgrade event and use the proxy's ws method.


I'll just share the whole thing:

import process from "process";
import express from "express";
import proxy from "http-proxy";
import cors from "cors";
import { logger } from "./logger.js";

import {
} from "./config.js";

const app = express();

app.use(cors({ origin: ALLOWED_ORIGIN }));

app.get("/", (req, res) => {
  res.send({ hi: "hello" });

const gameProxy = proxy.createProxyServer({});

app.all("/game/*", (req, res) => {
  // This is for proxying regular traffic. The option { ws: true } did not work :shrug:
  gameProxy.web(req, res, { target: UPSTREAM_GAME_SERVER });

// This is probably a bad idea, I should check for IS_PRODUCTION for binding to
const HOST = IS_DEVELOPMENT ? "" : "";

const http = app.listen(PORT, HOST);

http.on("upgrade", (req, socket) => {
  // Papam! Proxy the WebSockets., socket, { target: UPSTREAM_GAME_SERVER });

function shutdown(signal: NodeJS.Signals) {`Caught signal ${signal}`);
  http.close(() => {"The HTTP server was closed");

process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);`Gateway proxy listening on port ${PORT}, host: ${HOST}`);`Proxying /game to ${UPSTREAM_GAME_SERVER}`);`Allowed origin: ${ALLOWED_ORIGIN}`);

Easy, right?

Some words about the game I'm developing: It's an online persistent-universe single player/cooperative gameplay 4X/resource-management space game targeting an audience that can't afford playing games for long sessions.

I want to separate the game server's logic from the authentication logic and all that, so creating a gateway server that authenticates players and proxies their traffic to the game server under a decorated route seems the way to go.