[]
        
(Showing Draft Content)

Server Middleware

Middleware is a key mechanism for the server to process connections and messages, used to execute custom logic before events (such as connection establishment or message reception) reach hooks. The server itself has no business logic and relies on middleware to implement specific functionality.

The middleware mechanism provided by the server allows developers to customize the logic for handling connections and messages. This document introduces its usage and features.

Use Cases

  • User authentication

  • Permission validation

  • Log management

Registration

The server.use API is used to register middleware. It supports two usages:

  1. Single Registration

    server.use('connect', async (context, next) => {
        console.log('Client connecting:', context.connection.id);
        await next();
    });
    server.use('message', async (context, next) => {
        console.log('Message received:', context.data);
        await next();
    });
  2. Batch Registration

    server.use({
        connect: async (context, next) => {
            console.log('Client connecting:', context.connection.id);
            await next();
        },
        message: async (context, next) => {
            console.log('Message received:', context.data);
            await next();
        }
    });

Execution Order

Multiple registered middleware will be executed in the order of registration.

server.use('connect', (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('connect', (context, next) => {
    console.log('Middleware2');
    await next();
});
server.use('connect', (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('connect', () => {
    console.log('Hook');
});
// output
//Middleware1
//Middleware2
//Middleware3
// Hook

Errors

If the next method is called with an error parameter, the following occurs:

  • Subsequent middleware execution is stopped.

  • The server’s built-in error handler is triggered, the error is returned to the client, triggering the client's error event.

  • For connect middleware, the connection request is rejected (since the connection is not yet established, the connect hook will not be triggered).

// server side
server.use('connect', async (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('connect', async (context, next) => {
    console.log('Middleware2');
    await next(new Error('test middleware error'));
});
server.use('connect', async (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('connect', () => {
    console.log('Hook');
});

// Output:
//Middleware1
//Middleware2

Client Receives Error

// client side
connection.on('error', (error) => {
    console.log(error.message); // will output "test middleware error"
});

Short-Circuiting

If the next() function is not called within a middleware:

  • Subsequent middleware execution is stopped and the event handling process will not execute.

  • For connect middleware, ensure next() is always called; otherwise, the connection request will remain pending until it times out and is closed.

  • For message middleware, short-circuiting can be used to terminate the processing flow early.

// Server side
server.use('message', async (context, next) => {
    console.log('Middleware1');
    await next();
});
server.use('message', async (context, next) => {
    console.log('Middleware2');
    // Short-circuit: next() is not called
});
server.use('message', async (context, next) => {
    console.log('Middleware3');
    await next();
});
server.on('message', () => {
    console.log('Hook');
});

// Output:
// Middleware1
// Middleware2

Interface

export interface IMiddlewares {
    connect?: IMiddleware<IConnectMiddlewareContext>;  // When connecting
    message?: IMiddleware<IMessageMiddlewareContext>;  // When receive messages from clients
}

Next Steps

Use Middleware for Authentication and Permission Validation, see User Authentication and Permissions.