Пространства имён
Пространство имён — это канал связи, который позволяет разделить логику вашего приложения на отдельном общем соединении.
Возможные варианты использования:
- вы хотите создать пространство имён администратора, к которому имеют доступ только авторизованные пользователи, чтобы логика, связанная с этими пользователями, была отделена от остальной части приложения
const adminNamespace = io.of('/admin');adminNamespace.use((socket, next) => { // ensure the user has sufficient rights next();});adminNamespace.on('connection', socket => { socket.on('delete user', () => { // ... });}); |
- ваше приложение имеет нескольких арендаторов, поэтому вы хотите динамически создать по одному пространству имён на каждого арендатора
const workspaces = io.of(/^\/\w+$/);workspaces.on('connection', socket => { const workspace = socket.nsp; workspace.emit('hello');});// this middleware will be assigned to each namespaceworkspaces.use((socket, next) => { // ensure the user has access to the workspace next();}); |
Пространство имён по умолчанию
Мы называем пространство имён по умолчанию / и оно является тем, к которому клиенты Socket.IO подключаются по умолчанию, и к которому сервер прослушивает по умолчанию.
Это пространство имён идентифицируется по io.sockets или просто io:
// the following two will emit to all the sockets connected to `/`io.sockets.emit('hi', 'everyone');io.emit('hi', 'everyone'); // short form |
Каждое пространство имён излучает событие connection, которое получает каждый экземпляр Socket в качестве параметра
io.on('connection', socket => { socket.on('disconnect', () => {});}); |
Пользовательские пространства имён
Для настройки пользовательского пространства имён можно вызвать функцию of на стороне сервера:
const nsp = io.of('/my-namespace');nsp.on('connection', socket => { console.log('someone connected');});nsp.emit('hi', 'everyone!'); |
На стороне клиента вы указываете клиенту Socket.IO подключиться к этому пространству имён:
const socket = io('/my-namespace'); |
Важное примечание: Пространство имён — это деталь реализации протокола Socket.IO, и не связано с фактическим URL базового транспорта, который по умолчанию /socket.io/….
Прослойки пространства имён
Прослойка — это функция, которая выполняется для каждого входящего сокета и получает в качестве параметров сокет и функцию для необязательного отложенного выполнения в следующем зарегистрированном прослойке. Прослойка Socket.IO очень похожа на то, что можно найти в Express.
// registers a middleware for the default namespaceio.use((socket, next) => { if (isValid(socket.request)) { next(); } else { next(new Error('invalid')); }});// registers a middleware for a custom namespaceio.of('/admin').use(async (socket, next) => { const user = await fetchUser(socket.handshake.query); if (user.isAdmin) { socket.user = user; next(); } else { next(new Error('forbidden')); }}); |
Вы можете зарегистрировать несколько функций прослойки для одного пространства имён. Они будут выполняться последовательно:
io.use((socket, next) => { next();});io.use((socket, next) => { next(new Error('thou shall not pass'));});io.use((socket, next) => { // not executed, since the previous middleware has returned an error next();}); |
Обработка ошибки прослойки
Если метод next вызывается с объектом Error, клиент получит событие error.
import io from 'socket.io-client';const socket = io();socket.on('error', (reason) => { console.log(reason); // prints the message associated with the error, e.g. "thou shall not pass" in the example above}); |
Совместимость с прослойками Express
Большинство существующих модулей прослоек Express должны быть совместимы с Socket.IO, вам просто нужна небольшая оберточная функция, чтобы соответствовать сигнатурам методов:
const wrap = middleware => (socket, next) => middleware(socket.request, {}, next); |
Функции прослойки, которые завершают цикл запроса-ответа и не вызывают next() , не будут работать.
Пример с express-session:
const session = require('express-session');io.use(wrap(session({ secret: 'cats' })));io.on('connection', (socket) => { const session = socket.request.session;}); |
Пример с Passport:
const session = require('express-session');const passport = require('passport');io.use(wrap(session({ secret: 'cats' })));io.use(wrap(passport.initialize()));io.use(wrap(passport.session()));io.use((socket, next) => { if (socket.request.user) { next(); } else { next(new Error('unauthorized')) }}); |
Полный пример с Passport можно найти здесь.
© 2014–2020 Automattic
Licensed under the MIT License.
https://socket.io/docs/v2/namespaces