I have a Nestjs
app with Fastify
. I want to apply the fastifySession
middleware using the MiddlewareConsumer
. Usually, it works like below:
configure(consumer: MiddlewareConsumer) {
consumer
.apply(
fastifySession,
)
.forRoutes({
path: '*',
method: RequestMethod.ALL,
});
}
}
The problem is that fastifySession
needs an options
object. In a regular app, it is called using the register
method like below:
app.register(fastifySession, {
secret: '',
cookie: {
secure: false,
domain: 'localhost',
},
store: new SessionStore(new SessionService()),
});
I don't want to use the register
method in main.ts
as I want to make use of the Nestjs dependency injection
. So, I need to apply the middleware in the AppModule. Is there a way to do this?
UPDATE
I thought I can develop a Nestjs middleware to register the fastify plugins that I need.
I created this middleware:
@Injectable()
class FastifySession implements NestMiddleware {
private options;
private fastifyPassport;
constructor(
private adapterHost: HttpAdapterHost,
private sessionStore: SessionStore,
private userService: UserService,
) {
this.fastifyPassport = new Authenticator();
this.options = {
cookie: {
secure: false,
maxAge: 50000,
path: '/',
httpOnly: true,
sameSite: false,
domain: 'localhost',
},
store: this.sessionStore,
};
}
use(req: any, res: any, next: (error?: any) => void) {
const httpAdapter = this.adapterHost.httpAdapter;
const instance = httpAdapter.getInstance();
instance.register(fastifyCookie);
instance.register(fastifySession, this.options);
instance.register(this.fastifyPassport.initialize());
instance.register(this.fastifyPassport.secureSession());
this.fastifyPassport.registerUserSerializer(async (user: User, request) => {
console.log(user.id);
return user.id;
});
this.fastifyPassport.registerUserDeserializer(async (id, request) => {
const user = await this.userService.getUser(+id);
console.log('user ', user);
return user;
});
next();
}
}
I added the middleware to my AppModule
export class AppModule implements NestModule {
constructor() {
}
configure(consumer: MiddlewareConsumer) {
consumer
.apply(FastifySession)
.forRoutes({
path: '*',
method: RequestMethod.ALL,
});
}
}
But I get his error
ERROR [ExceptionsHandler] Root plugin has already booted
AvvioError: Root plugin has already booted
I came across this GitHub Issue
https://github.com/nestjs/nest/issues/1462
As stated in the GitHub issue, I think It is not possible to register Fastify plugins outside main.ts.
I will appreciate anyone helping me! or at least guide me in the right direction.
To register a plugin inside a module, I would use
onModuleInit
and a module that injects theHttpAdapterHost
. Something like this:This way, the adapter registers the middleware at application startup and you don't accidentally end up registering it multiple times on each route call (
use
will be called on each matching route and you end up callinginstance.register()
a lot with the current code in the question)