Gathering detailed insights and metrics for koa-easy-ws
Gathering detailed insights and metrics for koa-easy-ws
Gathering detailed insights and metrics for koa-easy-ws
Gathering detailed insights and metrics for koa-easy-ws
npm install koa-easy-ws
Typescript
Module System
Node Version
NPM Version
JavaScript (100%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
76 Stars
53 Commits
14 Forks
1 Watchers
3 Branches
7 Contributors
Updated on Jun 17, 2025
Latest Version
2.1.0
Package Id
koa-easy-ws@2.1.0
Unpacked Size
20.54 kB
Size
6.05 kB
File Count
10
NPM Version
8.1.2
Node Version
16.6.2
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
1
10
Simple, easy to use, composable middleware for websocket handling in Koa
1const Koa = require('koa') 2const websocket = require('koa-easy-ws') 3 4const app = new Koa() 5 6app.use(websocket()) 7app.use(async (ctx, next) => { 8 // check if the current request is websocket 9 if (ctx.ws) { 10 const ws = await ctx.ws() // retrieve socket 11 12 // now you have a ws instance, you can use it as you see fit 13 return ws.send('hello there') 14 } 15 16 // we're back to regular old http here 17 ctx.body = 'general kenobi' 18})
Note: you will also need to install the ws
package (npm install --save ws
or yarn add ws
), it is linked only as a peer dependency.
First, you need to pass the koa-easy-ws middleware before the one handling your request. Remember to call it as a function, app.use(websocket())
, not app.use(websocket)
. This sets up on-demand websocket handling for the rest of the middleware chain.
The middleware adds the ctx.ws()
function whenever it detects an upgrade request, calling which handles the websocket and returns a ws instance. If not called, regular Koa flow continues, likely resulting in a client-side error.
You can easily compose koa-easy-ws with a routing library:
1const Koa = require('koa') 2const Router = require('koa-router') 3const websocket = require('koa-easy-ws') 4 5const app = new Koa() 6const router = new Router() 7 8app 9 .use(websocket()) 10 .use(router.routes()) 11 .use(router.allowedMethods()) 12 13router.get('/pow/obi', async (ctx, next) => { 14 if (ctx.ws) { 15 const ws = await ctx.ws() 16 ws.send('chancellor palpatine is evil') 17 } 18}) 19 20router.get('/pow/ani', async (ctx, next) => { 21 if (ctx.ws) { 22 const ws = await ctx.ws() 23 ws.send('the jedi are evil') 24 ws.send('404') 25 } 26})
If ctx.ws()
isn't enough for you, the websocket server instance is also exposed:
1const Koa = require('koa') 2const websocket = require('koa-easy-ws') 3 4const app = new Koa() 5const websocketMiddleware = websocket() 6const websocketServer = websocketMiddleware.server // this is where the fun begins 7 8app.use(websocketMiddleware) // we already have the instance here 9 10// <insert rest of the app>
This gives you access to the ws server object, allowing to pass down custom listeners, connection validators, etc.
Alternatively, you can pass options to the underlying ws server as part of the options object:
1app.use(websocket('ws', { 2 wsOptions: { 3 clientTracking: false, 4 maxPayload: 69420 5 } 6}))
The wsOptions
object will be forwarded to ws unchanged, you can check its documentation for the available options.
In case ctx.ws
conflicts with something else in your code, koa-easy-ws doesn't mind changing the property name, just pass it as a property. This also lets you use multiple websocket middlewares if you ever find a reason to do so:
1const Koa = require('koa') 2const websocket = require('koa-easy-ws') 3 4const app = new Koa() 5 6app.use(websocket('sidious')) // we just renamed ctx.ws to ctx.sidious 7app.use(websocket('maul')) // attach another one for no good reason 8 9app.use(async (ctx, next) => { 10 // the first middleware detected an upgrade request 11 if (ctx.sidious) { 12 const socket = await ctx.sidious() 13 return socket.send('this is getting out of hand') 14 } 15 16 // the second middleware detected the same upgrade request 17 if (ctx.maul) { 18 const socket = await ctx.maul() 19 return socket.send('now there are two of them') 20 } 21})
Note: in this example ctx.maul
is never used because there is no limit on the authority of ctx.sidious
. However, if you define custom logic this technique could sort incoming requests to separate websocket servers.
If needed, you can also expose the websocket server on a context property, which can itself be renamed:
1const Koa = require('koa') 2const websocket = require('koa-easy-ws') 3 4const app = new Koa() 5 6app.use(websocket('ws', { exposeServerOn: 'wss' })) 7 8app.use(async (ctx, next) => { 9 if (ctx.ws) { 10 console.log('found the server', ctx.wss) 11 } 12})
In the above example, ctx.ws
behaves as normal, but you also have the server instance available on ctx.wss
. This saves you the trouble of having to access websocket().server
as seen in a prior example.
From here, the sky is the limit, unless you work for SpaceX.
In version 2, ws
has been moved to a peer dependency, which is a breaking change with the way dependency resolution works. It will technically work if you just upgrade to v2 with no changes, especially because of the package-lock.json
or yarn.lock
keeping ws
there, but it would most likely inject a weird bug. To avoid unpredictable issues in the future, add ws
to your own package's dependencies.
On top of that, the peer dependency is for ws@8, not ws@7 which koa-easy-ws previously used, so refer to ws@8's breaking changes for that (but if you're fine with a warning ws@7 should continue to work).
Node's HTTP server doesn't send upgrade requests through the normal callback (and thus your Koa middleware chain) prior to version 10, preventing koa-easy-ws from handling them. Because of this, if you target Node 9 or earlier, you must pass your HTTP server to the middleware which handles the workaround:
1const server = http.createServer(app.callback()) 2 3app.use(websocket('ws', server)) 4 5// alternatively, you can pass it as part of the options object: 6app.use(websocket('ws2', { 7 server: server 8})) 9 10server.listen(process.env.PORT) // use this function instead of your app.listen() call
koa-easy-ws then automatically feeds any upgrade request into your regular middleware chain. If you wish to opt out and do this yourself, use the noServerWorkaround
option:
1app.use(websocket('ws', { 2 noServerWorkaround: true 3}))
Pull requests are welcome. As always, be respectful towards each other and maybe run or create tests, as appropriate. It's on npm test
, as usual.
koa-easy-ws uses the MIT license. Was considering the WTFPL, but I like the "no warranty" clause.
No vulnerabilities found.
Reason
no binaries found in the repo
Reason
license file detected
Details
Reason
Found 6/20 approved changesets -- score normalized to 3
Reason
0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
project is not fuzzed
Details
Reason
security policy file not detected
Details
Reason
branch protection not enabled on development/release branches
Details
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
Reason
17 existing vulnerabilities detected
Details
Score
Last Scanned on 2025-07-07
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn More