egg plugin for socket.io
$ npm i egg-socket.io --save
Change ${app_root}/config/plugin.js
to enable Socket.IO plugin:
// {app_root}/config/plugin.js
exports.io = {
enable: true,
package: 'egg-socket.io',
};
Configure Socket.IO in ${app_root}/config/config.default.js
:
exports.io = {
init: { }, // passed to engine.io
namespace: {
'/': {
connectionMiddleware: [],
packetMiddleware: [],
},
},
redis: {
host: '127.0.0.1',
port: 6379
}
};
If you want to replace the default us
with uws, you can config like this:
exports.io = {
init: { wsEngine: 'uws' },
};
read more about init config at: engine.io .
see config/config.default.js for more detail.
Because of socket.io's design, the multi process socket.io server must work at sticky
mode.
So, you must start cluster server with sticky
set to true, otherwise it will cause handshake exception.
$ # modify your package.json - npm scripts
$ egg-bin dev --sticky
$ egg-scripts start --sticky
which will start egg cluster with:
startCluster({
sticky: true,
...
});
if you use a nginx proxy server:
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_pass http://127.0.0.1:{ your node server port };
}
app
├── io
│ ├── controller
│ │ └── chat.js
│ └── middleware
│ ├── auth.js
│ ├── filter.js
├── router.js
config
├── config.default.js
└── plugin.js
middleware are functions which every connection or packet will be processed by.
- Write your connection middleware
app/io/middleware/auth.js
module.exports = app => {
return function* (next) {
this.socket.emit('res', 'connected!');
yield* next;
// execute when disconnect.
console.log('disconnection!');
};
};
- then config this middleware to make it works.
config/config.default.js
exports.io = {
namespace: {
'/': {
connectionMiddleware: ['auth'],
},
},
};
pay attention to the namespace, the config will only work for a specific namespace.
- Write your packet middleware
app/io/middleware/filter.js
module.exports = app => {
return function* (next) {
this.socket.emit('res', 'packet received!');
console.log('packet:', this.packet);
yield* next;
};
};
- then config this middleware to make it works.
config/config.default.js
exports.io = {
namespace: {
'/': {
packetMiddleware: ['filter'],
},
},
};
pay attention to the namespace, the config will only work for a specific namespace.
controller is designed to handle the emit
event from the client.
example:
app/io/controller/chat.js
module.exports = app => {
return function* () {
const message = this.args[0];
console.log(message);
this.socket.emit('res', `Hi! I've got your message: ${message}`);
};
};
You can also use async/await
in controller:
app/io/controller/chat.js
module.exports = app => {
return async function() {
const message = this.args[0];
console.log(message);
await this.socket.emit('res', `Hi! I've got your message: ${message}`);
};
};
next, config the router at app/router.js
module.exports = app => {
// or app.io.of('/')
app.io.route('chat', app.io.controllers.chat);
};
If your Socket.IO service is powered by mutil server, you must think about cluster solution.It can't work without cluster like broadcast ,rooms and so on.
It's very easy to implement sharing source and event dispatch with with socket.io-redis built in.
config at config/config.${env}.js
:
exports.io = {
redis: {
host: { redis server host },
port: { redis server prot },
auth_pass: { redis server password },
db: 0,
}
};
Application will try to connect the redis server when booting.
Please open an issue here.