• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

b3nsn0w/koa-easy-ws: Simple Koa middleware for websocket handling

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

b3nsn0w/koa-easy-ws

开源软件地址:

https://github.com/b3nsn0w/koa-easy-ws

开源编程语言:

JavaScript 100.0%

开源软件介绍:

Simple, easy to use, composable middleware for websocket handling in Koa

Usage

const Koa = require('koa')
const websocket = require('koa-easy-ws')

const app = new Koa()

app.use(websocket())
app.use(async (ctx, next) => {
  // check if the current request is websocket
  if (ctx.ws) {
    const ws = await ctx.ws() // retrieve socket

    // now you have a ws instance, you can use it as you see fit
    return ws.send('hello there')
  }
  
  // we're back to regular old http here
  ctx.body = 'general kenobi'
})

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.

Features

  • No magic. This is a middleware, it doesn't turn your Koa app into a KoaMagicWebSocketServer. It knows its place.
  • Integrates ws, one of the fastest and most popular websocket libraries.
  • Full composability. Since this is just a middleware, it's not picky on what other libraries you use.
  • Minimal, unopinionated 44 SLOC codebase. Seriously, this readme alone contains more code than what's imported into your project. (sorry about the tests though)
  • Two dependencies only, and it's the ws library and debug (because apparently logs are not a bad idea). No need for more clutter in your node_modules.

Examples and advanced configuration

You can easily compose koa-easy-ws with a routing library:

const Koa = require('koa')
const Router = require('koa-router')
const websocket = require('koa-easy-ws')

const app = new Koa()
const router = new Router()

app
  .use(websocket())
  .use(router.routes())
  .use(router.allowedMethods())

router.get('/pow/obi', async (ctx, next) => {
  if (ctx.ws) {
    const ws = await ctx.ws()
    ws.send('chancellor palpatine is evil')
  }
})

router.get('/pow/ani', async (ctx, next) => {
  if (ctx.ws) {
    const ws = await ctx.ws()
    ws.send('the jedi are evil')
    ws.send('404')
  }
})

If ctx.ws() isn't enough for you, the websocket server instance is also exposed:

const Koa = require('koa')
const websocket = require('koa-easy-ws')

const app = new Koa()
const websocketMiddleware = websocket()
const websocketServer = websocketMiddleware.server // this is where the fun begins

app.use(websocketMiddleware) // we already have the instance here

// <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:

app.use(websocket('ws', {
  wsOptions: {
    clientTracking: false,
    maxPayload: 69420
  }
}))

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:

const Koa = require('koa')
const websocket = require('koa-easy-ws')

const app = new Koa()

app.use(websocket('sidious')) // we just renamed ctx.ws to ctx.sidious
app.use(websocket('maul')) // attach another one for no good reason

app.use(async (ctx, next) => {
  // the first middleware detected an upgrade request
  if (ctx.sidious) {
    const socket = await ctx.sidious()
    return socket.send('this is getting out of hand')
  }

  // the second middleware detected the same upgrade request
  if (ctx.maul) {
    const socket = await ctx.maul()
    return socket.send('now there are two of them')
  }
})

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:

const Koa = require('koa')
const websocket = require('koa-easy-ws')

const app = new Koa()

app.use(websocket('ws', { exposeServerOn: 'wss' }))

app.use(async (ctx, next) => {
  if (ctx.ws) {
    console.log('found the server', ctx.wss)
  }
})

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.

Version 2 changelog

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).

Special usage for Node 9 or earlier

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:

const server = http.createServer(app.callback())

app.use(websocket('ws', server))

// alternatively, you can pass it as part of the options object:
app.use(websocket('ws2', {
  server: server
}))

server.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:

app.use(websocket('ws', {
  noServerWorkaround: true
}))

Contributing

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.




鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap