Middleware
A Middleware runs code before and/or after route resolution, for every request whose path matches its pattern. Like Route, it extends Pattern (see Route patterns), so it has a pattern and a priority.
Defining a middleware
import { Middleware } from '@chialab/synapse';
const logger = new Middleware({
pattern: '*',
priority: 100,
before: (request, response, params, router) => {
console.log('navigating to', request.path.href);
},
after: (request, response, params, router) => {
console.log('rendered', response.title);
},
});before(MiddlewareBeforeHandler) runs before any route is matched.after(MiddlewareAfterHandler) runs after a route has produced a response.- Both receive
(request, response, params, router), whereparamsare the values extracted by matching the middleware's ownpatternagainst the current path (independent of any route's params). - Either hook can return a new
Response(or mutate and return the given one) to replace what continues through the pipeline; returning nothing keeps the current response. Callingresponse.redirect(path)from a hook short-circuits the rest of the pipeline in favor of areplace()topath.
Connecting a middleware
Directly on a Router:
router.middleware(logger);
// or inline:
router.middleware('*', undefined, (request, response) => {
/* before */
});Or declared statically on an App:
class DemoApp extends App {
static middlewares = [logger, new DocumentMetaMiddleware()];
}Connected middlewares are sorted by descending priority (default 20) and, for each request, Router#handle runs every matching middleware's before hook (highest priority first), then the matched route, then every matching middleware's after hook.
DocumentMetaMiddleware
A built-in middleware that keeps document.title and <meta> tags in sync with the current Response's title and meta:
import { DocumentMetaMiddleware } from '@chialab/synapse';
class DemoApp extends App {
static middlewares = [new DocumentMetaMiddleware()];
}Its constructor is (doc = document, titleBuilder?, metaBuilder?):
titleBuilder: (title: string | undefined, response: Response) => string— defaults to(title) => title || ''; use it to add a suffix, e.g.(title) => title ?${title} · My App: 'My App'.metaBuilder: (meta: Meta | undefined, response: Response) => Meta— defaults to(meta) => meta || {}; use it to inject metadata shared across pages.
On its hookAfter, it calls the builders with response.title/response.meta and writes the result to the document: existing <meta name="..."> tags are updated in place, new ones are appended to <head>, and tags that are no longer present in the new Meta object are removed.
new DocumentMetaMiddleware(document, (title) => (title ? `${title} · Demo` : 'Demo'), (meta) => ({
...meta,
'og:site_name': 'Demo',
}));Set response.setTitle(...) and response.setMeta(...) from your route handlers (see Request & Response) — DocumentMetaMiddleware only reads and applies them.