Search code examples
node.jstypescriptmiddlewareclean-architecturefastify

Using Fastify preHandler middleware


Passing a middleware to authenticate user before accessing this route.

When I'm passing tokenController.authUser as a middleware tokenService inside tokenController is undefined. However when I run this method as a function inside the route instead of a middleware it works fine.

server.post('/api/admin/test', { preHandler: [tokenController.authUser] }, async (request: any, reply: any) => {
    return null
});

Token Controller :-

import { Users } from "@prisma/client";
import ITokenService from "../../services/tokenService/ITokenService";
import ITokenController from "./ITokenController";

export default class TokenController implements ITokenController {
    private readonly tokenService: ITokenService;
    constructor(_tokenService: ITokenService) {
        this.tokenService = _tokenService;
    }

    async authUser(request: any, reply: any): Promise<Users | Error> {
        const authHeader = request.headers['authorization'];
        const token = authHeader && authHeader.split(' ')[1];
        if (token === null)
            return reply.code(401);
        try {
            const result = await this.tokenService.verifyToken(token);
            console.log(result);
            return result;
        }
        catch (e) {
            reply.code(401);
            return new Error("Error");
        }
    }
}

Token Service :-

import { Users } from "@prisma/client";
import ITokenService from "./ITokenService";

export default class TokenService implements ITokenService {
    private readonly sign: Function;
    private readonly verify: Function;
    private readonly secretKey: string;
    constructor(sign: Function, verify: Function, _secretKey: string) {
        this.sign = sign;
        this.verify = verify;
        this.secretKey = _secretKey;
    }

    public async generateToken(user: Users): Promise<string> {
        return await this.sign({ user }, this.secretKey);
    }

    public async verifyToken(token: string): Promise<Users | Error> {
        const result = await this.verify(token, this.secretKey);
        return result;
    }
}


Solution

  • For some reason making a separate middleware function and calling tokenController.authUser inside that method works fine.

    const middleware = (_req, _res, next) => {
      console.log('middleware');
      next()
    }
    
    
    server.post('/api/admin/test', { preHandler: [middleware] }, async (request: any, reply: any) => {
        return null
    });