const Ws = use('Ws')
Ws.channel('news', ({ socket }) => {
console.log('a new subscription for news topic')
})
You are viewing the legacy version of AdonisJS. Visit https://adonisjs.com for newer docs. This version will receive security patches until the end of 2021.
In this guide we dive deeper into channels, authentication and exchanging real time messages.
WebSocket channels are registered in the start/socket.js
file:
const Ws = use('Ws')
Ws.channel('news', ({ socket }) => {
console.log('a new subscription for news topic')
})
Channel handlers receive a context
object, similar to HTTP route handlers.
By default, channel context
objects contain socket
and request
properties (with more added by optional middleware like Auth
, Session
, etc).
Once a subscription is made, use the socket
instance to exchange messages:
socket.on('message', (data) => {
})
// emit events
socket.emit('message', 'Hello world')
socket.emit('typing', true)
Channels can be registered to accept dynamic topic subscriptions:
Ws.channel('chat:*', ({ socket }) => {
console.log(socket.topic)
})
In the example above, *
sets the channel to accept any subscriptions to topics beginning with chat:
(e.g. chat:watercooler
, chat:intro
, etc).
Subscriptions to dynamic topics are made via the Client API:
const watercooler = ws.subscribe('chat:watercooler')
const intro = ws.subscribe('chat:intro')
const news = ws.subscribe('chat:news')
In the example above, our different topic subscriptions all point to the same channel, but when topic specific events are emitted, they will be delivered to their specific topic subscribers only.
Middleware is registered inside the start/wsKernel.js
file:
const globalMiddleware = [
'Adonis/Middleware/Session',
'Adonis/Middleware/AuthInit'
]
const namedMiddleware = {
auth: 'Adonis/Middleware/Auth'
}
Named middleware is applied per channel in the start/socket.js
file:
Ws
.channel('chat', 'ChatController')
.middleware(['auth'])
WebSocket middleware require a wsHandle
method.
You can share HTTP and WebSocket middleware by ensuring both handle
(for HTTP requests) and wsHandle
methods are defined on your middleware class:
'use strict'
class CustomMiddleware {
// for HTTP
async handle (ctx, next) {
}
// for WebSocket
async wsHandle (ctx, next) {
}
}
module.exports = CustomMiddleware
As pre-registered WebSocket channels can be accessed from anywhere inside your application, WebSocket communication isn’t limited to the socket lifecycle.
Emit WebSocket events during the HTTP lifecycle like so:
const Ws = use('Ws')
class UserController {
async register () {
// ...
const topic = Ws.getChannel('subscriptions').topic('subscriptions')
// if no one is listening, so the `topic('subscriptions')` method will return `null`
if(topic){
topic.broadcast('new:user')
}
}
}
In the example above, we:
Select the channel via the getChannel(name)
method
Select the channel topic via the topic(name)
method
Broadcast to topic subscribers via the broadcast(event)
message
topic()
returns an object containing the following methods:
const chat = Ws.getChannel('chat:*')
const { broadcast, emitTo } = chat.topic('chat:watercooler')
// broadcast: send to everyone (except the caller)
// emitTo: send to selected socket ids
For more info, see the list of socket methods below. |
The following events are reserved and must not be emitted.
The following methods can be called on the socket instance.
Emit event to the connected client:
socket.emit('id', socket.id)
This method only sends a message to your own connection. |
Emit event to an array of socket ids:
socket.emitTo('greeting', 'hello', [someIds])
Emit event to everyone except yourself:
socket.broadcast('message', 'hello everyone!')
Emit event to everyone including yourself:
socket.broadcastToAll('message', 'hello everyone!')
The following read-only properties can be accessed on the socket instance.
Reference to the TCP connection (shared across multiple sockets for a single client for multiplexing):
socket.connection