Middleware
Middleware in Foxx refers to functions that can be mounted like routes and can
manipulate the request and response objects before and after the route itself
is invoked. They can also be used to control access or to provide common logic
like logging etc. Unlike routes, middleware is mounted with the use
method
like a router.
Instead of a function the use
method can also accept an object with a
register
function that will take a parameter endpoint
, the middleware will
be mounted at and returns the actual middleware function. This allows
manipulating the endpoint before creating the middleware (e.g. to document
headers, request bodies, path parameters or query parameters).
Examples
Restrict access to ArangoDB-authenticated users:
module.context.use(function (req, res, next) {
if (!req.arangoUser) {
res.throw(401, 'Not authenticated with ArangoDB');
}
next();
});
Any truthy argument passed to the next
function will be thrown as an error:
module.context.use(function (req, res, next) {
let err = null;
if (!req.arangoUser) {
err = new Error('This should never happen');
}
next(err); // throws if the error was set
})
Trivial logging middleware:
module.context.use(function (req, res, next) {
const start = Date.now();
try {
next();
} finally {
console.log(`Handled request in ${Date.now() - start}ms`);
}
});
More complex example for header-based sessions:
const sessions = module.context.collection('sessions');
module.context.use({
register (endpoint) {
endpoint.header('x-session-id', joi.string().optional(), 'The session ID.');
return function (req, res, next) {
const sid = req.get('x-session-id');
if (sid) {
try {
req.session = sessions.document(sid);
} catch (e) {
delete req.headers['x-session-id'];
}
}
next();
if (req.session) {
if (req.session._rev) {
sessions.replace(req.session, req.session);
res.set('x-session-id', req.session._key);
} else {
const meta = sessions.save(req.session);
res.set('x-session-id', meta._key);
}
}
};
}
});