{"id":20852388,"url":"https://github.com/dimdengd/ultimate-ws","last_synced_at":"2025-04-30T04:39:54.304Z","repository":{"id":257809923,"uuid":"864468399","full_name":"dimdenGD/ultimate-ws","owner":"dimdenGD","description":"The Ultimate WebSocket server. Fastest ws-compatible server, based on µWebSockets.","archived":false,"fork":false,"pushed_at":"2024-11-28T13:51:04.000Z","size":153,"stargazers_count":43,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-30T04:38:53.143Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dimdenGD.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-28T09:52:14.000Z","updated_at":"2025-04-28T21:00:20.000Z","dependencies_parsed_at":null,"dependency_job_id":"451eda11-b4a5-478f-98fc-60a409825ab5","html_url":"https://github.com/dimdenGD/ultimate-ws","commit_stats":null,"previous_names":["dimdengd/ultimate-ws"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdenGD%2Fultimate-ws","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdenGD%2Fultimate-ws/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdenGD%2Fultimate-ws/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dimdenGD%2Fultimate-ws/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dimdenGD","download_url":"https://codeload.github.com/dimdenGD/ultimate-ws/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251644823,"owners_count":21620629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T03:17:30.863Z","updated_at":"2025-04-30T04:39:54.271Z","avatar_url":"https://github.com/dimdenGD.png","language":"JavaScript","funding_links":["https://patreon.com/dimdendev"],"categories":[],"sub_categories":[],"readme":"# Ultimate WS\n\nThe *Ultimate* WebSocket server. Ultimate WS is an extremely fast, drop-in replacement for `ws` module, with support for [Ultimate Express](https://github.com/dimdenGD/ultimate-express) http upgrades. It uses [uWebSockets.js](https://github.com/uNetworking/uWebSockets.js) under the hood.  \n  \nIt's useful when:\n- You want same API as `ws` module, but the speed of `uWebSockets.js`\n- You want to convert your Express app with `ws` to use [Ultimate Express](https://github.com/dimdenGD/ultimate-express) instead\n    \n[![Node.js \u003e= 16.0.0](https://img.shields.io/badge/Node.js-%3E=16.0.0-green)](https://nodejs.org)\n[![npm](https://img.shields.io/npm/v/ultimate-ws?label=last+version)](https://npmjs.com/package/ultimate-ws)\n[![Patreon](https://img.shields.io/badge/donate-Patreon-orange)](https://patreon.com/dimdendev)\n\n## Installation\n\n1.\n```bash\nnpm install ultimate-ws\n```\n2. Replace `ws` with `ultimate-ws` in your code\n3. Check compatibility and differences below\n\n## Performance\n\nEcho test using `artillery` (duration: 20, arrivalRate: 10000):\n\n| Module            | Send rate     | Mean Session length | Median Session length |\n|-------------------|---------------|---------------------|-----------------------|\n| `ws`              | 2709/sec      | 2535ms              | 127ms                 |\n| **`ultimate-ws`** | **10046/sec** | **45ms**            | **12ms**              |\n\n## Usage\n\n### Use with [Ultimate Express](https://github.com/dimdenGD/ultimate-express)\n\nSince you don't create `http` server for `ws` or `express`, you can't really use `server.on(\"upgrade\", ...)` to upgrade to Ultimate WS. Instead, you can pass Ultimate Express or uWS app to `WebSocketServer` as option. So **instead** of doing this:\n```js\nconst http = require(\"http\");\nconst express = require(\"express\");\nconst ws = require(\"ws\");\n\nconst app = express();\nconst wsServer = new ws.WebSocketServer({ noServer: true });\n\napp.get(\"/\", (_, res) =\u003e res.send(\"Hello, world!\"));\n\nconst server = http.createServer(app);\nserver.on(\"upgrade\", (request, socket, head) =\u003e {\n    const { pathname } = url.parse(request.url);\n    if(pathname !== \"/wspath\") return request.socket.destroy();\n    \n    wsServer.handleUpgrade(request, socket, head, (ws) =\u003e {\n        wsServer.emit(\"connection\", ws, request);\n    });\n});\n\nserver.listen(3000);\n```\nYou need to do this:\n```js\nconst express = require(\"ultimate-express\");\nconst app = express();\nconst { WebSocketServer } = require(\"ultimate-ws\");\n\napp.get(\"/\", (_, res) =\u003e res.send(\"Hello, world!\"));\n\nconst wsServer = new WebSocketServer({ server: app, path: \"/wspath\" }); // path is optional\n\n// your usual `ws` server code ...\n\napp.listen(3000);\n```\n\n[Ultimate Express](https://github.com/dimdenGD/ultimate-express) is fully compatible, much faster `express` implementation.\n\n### Stand-alone usage\n\nIf you want to use Ultimate WS without any existing http server, you can do this:\n```js\nconst { WebSocketServer } = require(\"ultimate-ws\");\n\nconst wsServer = new WebSocketServer({ port: 3000 });\n\n// your usual `ws` server code ...\nwsServer.on(\"connection\", (ws) =\u003e {\n    ws.on(\"message\", (message) =\u003e {\n        ws.send(message);\n    });\n});\n```\n\n### Use with existing uWS server\n\nYou can also pass existing uWS server to `WebSocketServer`:\n```js\nconst { WebSocketServer } = require(\"ultimate-ws\");\nconst uws = require(\"uWebSockets.js\");\n\nconst server = uws.App();\nconst wsServer = new WebSocketServer({ server: server });\n\n// your usual `ws` server code ...\n\nserver.listen(3000);\n```\n\n## HTTPS\n\nUltimate WS supports HTTPS. You can pass `uwsOptions` to `WebSocketServer` to configure it:\n```js\nconst { WebSocketServer } = require(\"ultimate-ws\");\n\nconst wsServer = new WebSocketServer({\n    port: 3000,\n    uwsOptions: {\n        // https://unetworking.github.io/uWebSockets.js/generated/interfaces/AppOptions.html\n        key_file_name: \"path/to/key.pem\",\n        cert_file_name: \"path/to/cert.pem\",\n    }\n});\n```\n\n## Handling requests before connection\n\nInstead of this:\n\n```js\nconst http = require(\"http\");\nconst express = require(\"express\");\nconst ws = require(\"ws\");\n\nconst app = express();\nconst wsServer = new ws.WebSocketServer({ noServer: true, path: \"/wspath\" });\n\napp.get(\"/\", (_, res) =\u003e res.send(\"Hello, world!\"));\n\nconst server = http.createServer(app);\nserver.on(\"upgrade\", async (request, socket, head) =\u003e {\n    // your auth logic\n    const user = await getUserFromDatabase(request.headers['authorization']);\n    if(!user) return socket.destroy();\n    \n    wsServer.handleUpgrade(request, socket, head, (ws) =\u003e {\n        ws.user = user;\n        wsServer.emit(\"connection\", ws, request);\n    });\n});\n\nserver.listen(3000);\n```\n\nYou should do this:\n```js\nconst { WebSocketServer } = require(\"ultimate-ws\");\nconst express = require(\"ultimate-express\");\n\nconst app = express();\n\nconst wsServer = new WebSocketServer({\n    server: app,\n    path: \"/wspath\",\n    handleUpgrade: async (request) =\u003e {\n        // your auth logic\n        const user = await getUserFromDatabase(request.headers['authorization']);\n        if(!user) {\n            // request has `req` and `res` properties\n            // which are instances of `uws.HttpRequest` and `uws.HttpResponse`\n            request.res.cork(() =\u003e {\n                request.res.writeStatus(\"401 Unauthorized\");\n                request.res.end();\n            });\n            return false;\n        }\n        \n        return (ws, request) =\u003e {\n            ws.user = user;\n            wsServer.emit(\"connection\", ws, request);\n        }\n    }\n});\n\napp.get(\"/\", (_, res) =\u003e res.send(\"Hello, world!\"));\n\napp.listen(3000);\n```\n\n- if `handleUpgrade` returns a function, it will be called with the new `WebSocket` instance and original request. \"connection\" will not be emitted automatically.\n- if it returns `false`, the connection will not be upgraded. It's your responsibility to destroy the socket.\n- if it returns nothing or anything else, the connection will be handled as usual, and \"connection\" event will be emitted.\n- By default (`handleUpgrade: undefined`), the connection will be handled as usual, and \"connection\" event will be emitted.\n  \n## Compatibility\n\nAll commonly used `ws` features are supported. Almost all ws servers should work, as it's built with maximum compatibility in mind.\nPlease refer to [ws module documentation](https://github.com/websockets/ws) for API reference.\nBelow is the list of supported features and their compatibility:  \n\n✅ - Full support (all features and options are supported)  \n🚧 - Partial support (some features are not supported)  \n❌ - Not supported  \n\n#### WebSocket\n\n- ✅ WebSocket\n- ✅ WebSocket.Server\n- ✅ WebSocket.WebSocket\n- ✅ WebSocket.WebSocketServer\n- ✅ WebSocket.CONNECTING\n- ✅ WebSocket.OPEN\n- ✅ WebSocket.CLOSING\n- ✅ WebSocket.CLOSED\n- ✅ WebSocket.createWebSocketStream\n\n### Server\n\n#### Server options\n\n`ws` options:\n\n- ✅ autoPong (maps to uWS `sendPingsAutomatically`, default `true`)\n- ✅ allowSynchronousEvents (may lower performance when `false`, default `true`)\n- ✅ clientTracking\n- ✅ handleProtocols\n- ✅ host\n- ✅ maxPayload (default 100mb)\n- ✅ path\n- 🚧 perMessageDeflate - pass `true` for `DEDICATED_COMPRESSOR_4KB | DEDICATED_DECOMPRESSOR` or your own [`CompressOptions`](https://unetworking.github.io/uWebSockets.js/generated/types/CompressOptions.html) number. Options are not supported and if this is an object it will be treated as `true`.\n- ✅ port\n- ✅ server\n- ✅ verifyClient\n- ✅ WebSocket\n- ✅ callback\n- ❌ noServer - see examples above for alternatives\n- ❌ skipUTF8Validation - uWS always validates UTF-8 when message is a string\n- ❌ backlog\n\n`uWS` options (additional options that `ws` doesn't have):  \n\n- ✅ maxBackpressure (default `maxPayload`)\n- ✅ idleTimeout (default 120)\n- ✅ maxLifetime (default 0)\n- ✅ closeOnBackpressureLimit (default `false`)\n\n#### Server events\n\n- ✅ close\n- ✅ connection\n- ✅ headers\n- ✅ listening\n- ✅ error - µWS never throws errors\n- ✅ wsClientError - µWS never throws errors\n\n#### Server properties\n\n- ✅ server.address()\n- ✅ server.clients\n- ✅ server.close(callback)\n- ✅ server.shouldHandle(request)\n- ❌ server.handleUpgrade(request, socket, head, callback) - see examples above for alternatives\n\n### Client\n\nThis category only describes server clients. Client-side (`new ws.WebSocket()`) just uses original `ws` module, and therefore supports everything.\n\n#### Client events\n\n- ✅ close\n- ✅ message\n- ✅ ping\n- ✅ pong\n- ✅ dropped - this event only exists in Ultimate WS for handling dropped messages\n- ✅ drain - this event only exists in Ultimate WS for handling backpressure draining\n- ✅ error - µWS never throws errors\n\n#### Client properties\n\n- ✅ client.addEventListener(type, listener, options)\n- ✅ client.binaryType\n- ✅ client.bufferedAmount\n- ✅ client.close(code, reason)\n- ✅ client.isPaused\n- ✅ client.extensions\n- ✅ client.onclose\n- ✅ client.onerror\n- ✅ client.onmessage\n- ✅ client.onopen\n- ✅ client.pause()\n- 🚧 client.ping()\n- ❌ client.pong(data, mask, callback) - pongs are handled automatically, method does nothing\n- ✅ client.protocol\n- ✅ client.resume()\n- ✅ client.readyState\n- ✅ client.removeEventListener(type, listener)\n- 🚧 client.send(data, options, callback) - returns 1 for success, 2 for dropped due to backpressure limit, 0 for built up backpressure that will drain over time. Callback will only get error if it returns 2.\n- - ✅ options.binary\n- - ✅ options.compress\n- - ❌ options.fin\n- - ❌ options.mask\n- ✅ client.terminate()\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimdengd%2Fultimate-ws","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdimdengd%2Fultimate-ws","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdimdengd%2Fultimate-ws/lists"}