mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
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) <noreply@anthropic.com>
This commit is contained in:
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user