Feathers.js Request Id Middleware
Bervianto Leo Pratama
Posted on October 31, 2021
Prepare your project
Generate the app (if you don't have existing app), please see here. Basically you need to install the generator with:
npm install @feathersjs/cli -g
You can follow the step-by-step in the generate app page. Some notes: I use Typescript for the codebase.
Generate and write the Middleware
- Use
feathers generate middleware
. You can see how I generate the middleware here.
I want to use
uuidv4
as my request id. So please install the uuid use:npm install uuid @types/uuid
oryarn install uuid @types/uuid
(if you use yarn).Write the middleware. We put the requestId at feathers object. You can found the file at
src/middleware/request-id.ts
.
import { v4 as uuidv4 } from 'uuid';
import { Request, Response, NextFunction } from 'express';
export default () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/explicit-module-boundary-types
return (req: Request, res: Response, next: NextFunction) => {
const requestId= uuidv4();
if (!req.feathers) {
req.feathers = {};
}
req.feathers.requestId = requestId;
next();
};
};
- Update log hooks for capture our
requestId
. I update thesrc/hooks/log.ts
.
// A hook that logs service method before, after and error
// See https://github.com/winstonjs/winston for documentation
// about the logger.
import logger from '../logger';
import util from 'util';
import { HookContext, Hook } from '@feathersjs/feathers';
// To see more detailed messages, uncomment the following line:
logger.level = 'debug';
export default function (): Hook {
return (context: HookContext) => {
const { params } = context;
const requestId = params.requestId;
logger.debug(`Request Id: ${requestId}`);
// This debugs the service call and a stringified version of the hook context
// You can customize the message (and logger) to your needs
logger.debug(
`${context.type} app.service('${context.path}').${context.method}()`,
);
if (
// eslint-disable-next-line @typescript-eslint/no-explicit-any
typeof (context as any).toJSON === 'function' &&
logger.level === 'debug'
) {
logger.debug('Hook Context', util.inspect(context, { colors: false }));
}
if (context.error && !context.result) {
logger.error(context.error.stack);
}
};
}
- I want to use error handler and bring the request id. First I will disable html output for error handler. Because I don't want to handle HTML output. You can update the
src/app.ts
like this.
// another code...
// Configure a middleware for 404s and the error handler
app.use(express.notFound());
app.use(express.errorHandler({ html: false }));
app.hooks(appHooks);
export default app;
- Generate application wide error hooks. You can see picture below. For more information. You can check this.
- Write the hooks. You can found at
src/hooks/common-error.ts
.
// Use this hook to manipulate incoming or outgoing data.
// For more information on hooks see: http://docs.feathersjs.com/api/hooks.html
import { Hook, HookContext } from '@feathersjs/feathers';
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export default (options = {}): Hook => {
return async (context: HookContext): Promise<HookContext> => {
if (context.error) {
console.log(context);
const { params } = context;
const requestId = params.requestId;
const requestIdObject = {
requestId,
};
context.error.errors = Object.assign(
context.error.errors,
requestIdObject,
);
}
return context;
};
};
- After we write that, we will see the
requestId
under errors property like this. This will help to trace the error.
Thank you
That is it. If you have another suggestions. Please feel free to comment here.
Thank you. :)
💖 💪 🙅 🚩
Bervianto Leo Pratama
Posted on October 31, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.