[]
The middleware mechanism in js-collaboration-ot
allows developers to intercept and customize logic in the server-side OT (Operational Transformation) processing flow, such as permission validation or logging. This document explains how to use middleware, including its lifecycle, registration methods, and practical examples.
Middleware is a core extension feature of DocumentServices
, used to add custom logic during the processing stages of operations (op
) and snapshots (snapshot
).
Purpose:
Intercept and validate the operation flow
Modify the context or abort processing
Applicable Scenarios: User authentication, data validation, logging, performance monitoring, etc.
Difference from hooks: Middleware can interrupt the flow and return errors, whereas hooks only listen to events.
Middleware covers multiple stages of the OT processing flow, with each stage corresponding to an action. Developers can selectively intervene in these stages. The following are the supported middleware actions and their trigger timings:
Action | Description |
---|---|
| Triggered when the server receives a client message, used for initial validation or logging. |
| Triggered when an operation ( |
| Triggered when an operation is about to be committed to the database, after the operation has been transformed, allowing final validation. |
| Triggered after an operation is successfully written to the database, used for subsequent processing or notifications. |
| Triggered when a snapshot submission begins, allowing control over snapshot update logic. |
| Triggered when an operation is about to be applied to a snapshot, with the snapshot still in its old state. |
| Triggered when a snapshot is about to be committed to the database. |
| Triggered when one or more snapshots are loaded from the database (e.g., during |
| Triggered when an operation is loaded from the database, allowing rejection of operation reads. |
| Triggered when the document is about to send a non-error reply to the client. |
Middleware is an asynchronous function that receives context
and next
parameters:
context
: Contains contextual information for the current action (e.g., connection
, request
).
next
: A function to continue execution, which can be called with an error to abort the flow.
await next()
: Continues executing subsequent middleware or processing logic.
await next(error)
: Aborts the flow and returns an error.
docService.use('submit', async (context, next) => {
const user = context.connection.tags.get('user');
if (user.role === 'editor') {
console.log('Submitting operation:', context.request.op);
await next(); // Continue
} else {
await next('No permission'); // Abort
}
});
Middleware is registered using the use method of DocumentServices
.
import { DocumentServices } from '@mescius/js-collaboration-ot';
const docService = new DocumentServices();
docService.use('receive', async (context, next) => {
console.log('Message received:', context.request);
await next();
});
Multiple middleware for the same action are executed in the order of registration. If a middleware calls next(error)
, subsequent middleware will be skipped.
docService.use('submit', async (context, next) => {
console.log('Middleware 1');
await next();
});
docService.use('submit', async (context, next) => {
console.log('Middleware 2');
await next();
});
docService.use('submit', async (context, next) => {
console.log('Middleware 3');
await next();
});
// Output:
// Middleware 1
// Middleware 2
// Middleware 3
docService.use('submit', async (context, next) => {
console.log('Middleware 1');
await next();
});
docService.use('submit', async (context, next) => {
console.log('Middleware 2');
await next('Test error');
});
docService.use('submit', async (context, next) => {
console.log('Middleware 3'); // Will not be executed
await next();
});
// Output:
// Middleware 1
// Middleware 2
// Error returned to the client, triggering the client-side error event
The following are common middleware use cases and their implementations:
docService.use('submit', async (context, next) => {
const user = context.connection.tags.get('user');
if (user.role === 'editor') {
console.log('Submitting operation:', context.request.op);
await next(); // Continue
} else {
await next('No permission'); // Abort
}
});
docService.use('afterWrite', async (context, next) => {
console.log('Operation written to database:', context.request.op);
await next();
});
Middleware provides powerful flow control capabilities for the server-side of js-collaboration-ot
. By registering middleware at different lifecycle stages, you can implement validation, logging and other functionalities.