From b700e0aa5326e9a8889aefdcfcd8c17ba034fe7a Mon Sep 17 00:00:00 2001 From: dupontbertrand Date: Wed, 18 Mar 2026 08:48:31 +0100 Subject: [PATCH] refactor: keep only sockjs and uws transports Remove faye and ws transports as agreed with maintainer. DISABLE_SOCKJS=1 now resolves to uws instead of faye. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/ddp-server/package.js | 4 - packages/ddp-server/transports/faye.js | 62 -------------- packages/ddp-server/transports/index.js | 10 +-- .../ddp-server/transports/raw_connection.js | 4 +- packages/ddp-server/transports/ws.js | 85 ------------------- 5 files changed, 5 insertions(+), 160 deletions(-) delete mode 100644 packages/ddp-server/transports/faye.js delete mode 100644 packages/ddp-server/transports/ws.js diff --git a/packages/ddp-server/package.js b/packages/ddp-server/package.js index bc5222723b..d10b31effb 100644 --- a/packages/ddp-server/package.js +++ b/packages/ddp-server/package.js @@ -5,8 +5,6 @@ Package.describe({ }); Npm.depends({ - "faye-websocket": "0.11.4", - "ws": "8.18.1", "uWebSockets.js": "git+https://github.com/unetworking/uWebSockets.js#v20.58.0", "permessage-deflate2": "0.1.8", sockjs: "0.3.24", @@ -55,8 +53,6 @@ Package.onUse(function (api) { api.addFiles("transports/raw_connection.js", "server"); api.addFiles("transports/sockjs.js", "server"); - api.addFiles("transports/faye.js", "server"); - api.addFiles("transports/ws.js", "server"); api.addFiles("transports/uws.js", "server"); api.addFiles("transports/index.js", "server"); api.addFiles("stream_server.js", "server"); diff --git a/packages/ddp-server/transports/faye.js b/packages/ddp-server/transports/faye.js deleted file mode 100644 index 68fc95a37c..0000000000 --- a/packages/ddp-server/transports/faye.js +++ /dev/null @@ -1,62 +0,0 @@ -import { EventEmitter } from 'events'; -import { RawWebSocketConnection } from './raw_connection.js'; - -/** - * faye-websocket transport — raw WebSocket via faye-websocket library. - * No SockJS, no polling transports, no /sockjs/info endpoint. - */ -export function createFayeTransport() { - return { - name: 'faye', - setup(httpServer, pathPrefix, options) { - var emitter = new EventEmitter(); - var FayeWebSocket = Npm.require('faye-websocket'); - - RoutePolicy.declare(pathPrefix + '/websocket/', 'network'); - - // Reject plain HTTP requests to /websocket with a clear error message - // (same behavior as SockJS). Without this, they'd fall through to the - // app and return the main HTML page. - WebApp.rawConnectHandlers.use(function (req, res, next) { - var pathname = new URL(req.url, 'http://localhost').pathname; - if (pathname === pathPrefix + '/websocket' || - pathname === pathPrefix + '/websocket/') { - res.writeHead(400, { 'Content-Type': 'text/plain' }); - res.end('Not a valid websocket request'); - } else { - next(); - } - }); - - // We must take over existing 'upgrade' listeners (similar to what SockJS - // does via overshadowListeners) so that our handler runs first for the - // /websocket path, and other handlers (HMR, etc.) get the rest. - var oldUpgradeListeners = httpServer.listeners('upgrade').slice(0); - httpServer.removeAllListeners('upgrade'); - - httpServer.on('upgrade', function (req, rawSocket, head) { - var pathname = new URL(req.url, 'http://localhost').pathname; - - if (FayeWebSocket.isWebSocket(req) && - (pathname === pathPrefix + '/websocket' || - pathname === pathPrefix + '/websocket/')) { - - var wsOptions = { extensions: options.websocketExtensions() }; - var ws = new FayeWebSocket(req, rawSocket, head, null, wsOptions); - var meteorSocket = new RawWebSocketConnection(ws, req, rawSocket, - // faye-websocket wraps message data in an event object - (event) => event.data - ); - emitter.emit('connection', meteorSocket); - } else { - // Pass to other upgrade handlers (HMR, etc.) - for (var i = 0; i < oldUpgradeListeners.length; i++) { - oldUpgradeListeners[i].call(httpServer, req, rawSocket, head); - } - } - }); - - return emitter; - } - }; -} diff --git a/packages/ddp-server/transports/index.js b/packages/ddp-server/transports/index.js index f63e867615..c21877d0e3 100644 --- a/packages/ddp-server/transports/index.js +++ b/packages/ddp-server/transports/index.js @@ -1,12 +1,8 @@ import { createSockJSTransport } from './sockjs.js'; -import { createFayeTransport } from './faye.js'; -import { createWsTransport } from './ws.js'; import { createUwsTransport } from './uws.js'; const TRANSPORTS = { sockjs: createSockJSTransport, - faye: createFayeTransport, - ws: createWsTransport, uws: createUwsTransport, }; @@ -16,7 +12,7 @@ const VALID_NAMES = Object.keys(TRANSPORTS); * Resolve which transport to use. Priority: * 1. Meteor.settings.packages['ddp-server'].transport * 2. DDP_TRANSPORT env var - * 3. DISABLE_SOCKJS=1 → 'faye' (backward compat) + * 3. DISABLE_SOCKJS=1 → 'uws' (backward compat) * 4. default: 'sockjs' * * Also sets __meteor_runtime_config__.DDP_TRANSPORT so the client @@ -51,9 +47,9 @@ function resolveTransportName() { return process.env.DDP_TRANSPORT; } - // 3. Backward compat: DISABLE_SOCKJS=1 → faye + // 3. Backward compat: DISABLE_SOCKJS=1 → uws if (process.env.DISABLE_SOCKJS) { - return 'faye'; + return 'uws'; } // 4. Default diff --git a/packages/ddp-server/transports/raw_connection.js b/packages/ddp-server/transports/raw_connection.js index 5f04b47d75..f7ba6cfee1 100644 --- a/packages/ddp-server/transports/raw_connection.js +++ b/packages/ddp-server/transports/raw_connection.js @@ -5,8 +5,8 @@ import { EventEmitter } from 'events'; * interface as a SockJS connection, as expected by _onConnection * and livedata_server.js. * - * Used by the faye and ws transports. The uws transport implements - * its own socket interface directly. + * Used by non-SockJS transports that provide a standard WebSocket + * object. The uws transport implements its own socket interface directly. */ export class RawWebSocketConnection extends EventEmitter { constructor(ws, req, rawSocket, messageAdapter) { diff --git a/packages/ddp-server/transports/ws.js b/packages/ddp-server/transports/ws.js deleted file mode 100644 index 409babda14..0000000000 --- a/packages/ddp-server/transports/ws.js +++ /dev/null @@ -1,85 +0,0 @@ -import { EventEmitter } from 'events'; -import zlib from 'node:zlib'; -import { RawWebSocketConnection } from './raw_connection.js'; - -/** - * ws transport — raw WebSocket via the `ws` npm package. - * No SockJS, no polling transports, no /sockjs/info endpoint. - */ -export function createWsTransport() { - return { - name: 'ws', - setup(httpServer, pathPrefix, options) { - var emitter = new EventEmitter(); - var WebSocket = Npm.require('ws'); - - // Determine compression config from websocketExtensions(). - // If extensions are configured, enable perMessageDeflate. - var extensions = options.websocketExtensions(); - var perMessageDeflate = extensions.length > 0 - ? { - zlibDeflateOptions: { - level: zlib.constants.Z_BEST_SPEED, - memLevel: zlib.constants.Z_MIN_MEMLEVEL, - windowBits: zlib.constants.Z_MIN_WINDOWBITS - }, - threshold: 1024 - } - : false; - - // Create a ws server in noServer mode — we handle upgrade manually so - // that non-/websocket upgrades (HMR, etc.) reach their own handlers. - var wss = new WebSocket.Server({ - noServer: true, - perMessageDeflate: perMessageDeflate - }); - - RoutePolicy.declare(pathPrefix + '/websocket/', 'network'); - - // Reject plain HTTP requests to /websocket with a clear error message - WebApp.rawConnectHandlers.use(function (req, res, next) { - var pathname = new URL(req.url, 'http://localhost').pathname; - if (pathname === pathPrefix + '/websocket' || - pathname === pathPrefix + '/websocket/') { - res.writeHead(400, { 'Content-Type': 'text/plain' }); - res.end('Not a valid websocket request'); - } else { - next(); - } - }); - - // Take over existing 'upgrade' listeners so our handler runs first - // for the /websocket path, and other handlers (HMR, etc.) get the rest. - var oldUpgradeListeners = httpServer.listeners('upgrade').slice(0); - httpServer.removeAllListeners('upgrade'); - - httpServer.on('upgrade', function (req, rawSocket, head) { - var pathname = new URL(req.url, 'http://localhost').pathname; - - if (req.headers.upgrade && - req.headers.upgrade.toLowerCase() === 'websocket' && - (pathname === pathPrefix + '/websocket' || - pathname === pathPrefix + '/websocket/')) { - - wss.handleUpgrade(req, rawSocket, head, function (ws) { - var meteorSocket = new RawWebSocketConnection(ws, req, rawSocket, - // ws passes data directly (no event wrapper like faye) - (data, isBinary) => { - if (isBinary) return null; - return typeof data === 'string' ? data : data.toString(); - } - ); - emitter.emit('connection', meteorSocket); - }); - } else { - // Pass to other upgrade handlers (HMR, etc.) - for (var i = 0; i < oldUpgradeListeners.length; i++) { - oldUpgradeListeners[i].call(httpServer, req, rawSocket, head); - } - } - }); - - return emitter; - } - }; -}