mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
Merge pull request #15385 from mag123c/fix/fastify-adapter-middleware-init
fix(testing): auto-init fastify adapter for middleware registration
This commit is contained in:
@@ -0,0 +1,135 @@
|
|||||||
|
import {
|
||||||
|
Controller,
|
||||||
|
Get,
|
||||||
|
Injectable,
|
||||||
|
MiddlewareConsumer,
|
||||||
|
Module,
|
||||||
|
NestModule,
|
||||||
|
} from '@nestjs/common';
|
||||||
|
import {
|
||||||
|
FastifyAdapter,
|
||||||
|
NestFastifyApplication,
|
||||||
|
} from '@nestjs/platform-fastify';
|
||||||
|
import { Test } from '@nestjs/testing';
|
||||||
|
import { expect } from 'chai';
|
||||||
|
|
||||||
|
describe('Middleware before init (FastifyAdapter)', () => {
|
||||||
|
let app: NestFastifyApplication;
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
class TestService {
|
||||||
|
getData(): string {
|
||||||
|
return 'test_data';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
class TestController {
|
||||||
|
constructor(private readonly testService: TestService) {}
|
||||||
|
|
||||||
|
@Get('test')
|
||||||
|
test() {
|
||||||
|
return { data: this.testService.getData() };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('health')
|
||||||
|
health() {
|
||||||
|
return { status: 'ok' };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
controllers: [TestController],
|
||||||
|
providers: [TestService],
|
||||||
|
})
|
||||||
|
class TestModule implements NestModule {
|
||||||
|
configure(consumer: MiddlewareConsumer) {
|
||||||
|
consumer
|
||||||
|
.apply((req, res, next) => {
|
||||||
|
res.setHeader('x-middleware', 'applied');
|
||||||
|
next();
|
||||||
|
})
|
||||||
|
.forRoutes('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('should queue middleware when registered before init', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module = await Test.createTestingModule({
|
||||||
|
imports: [TestModule],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
app = module.createNestApplication<NestFastifyApplication>(
|
||||||
|
new FastifyAdapter(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register middleware before init - should be queued
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
res.setHeader('x-global-middleware', 'applied');
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Now init the app - queued middleware should be registered
|
||||||
|
await app.init();
|
||||||
|
await app.getHttpAdapter().getInstance().ready();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should apply queued middleware after init', () => {
|
||||||
|
return app
|
||||||
|
.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test',
|
||||||
|
})
|
||||||
|
.then(({ statusCode, payload, headers }) => {
|
||||||
|
expect(statusCode).to.equal(200);
|
||||||
|
expect(JSON.parse(payload)).to.deep.equal({ data: 'test_data' });
|
||||||
|
// Verify both module-level and global middleware were applied
|
||||||
|
expect(headers['x-middleware']).to.equal('applied');
|
||||||
|
expect(headers['x-global-middleware']).to.equal('applied');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('should work when app is initialized before middleware registration', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module = await Test.createTestingModule({
|
||||||
|
imports: [TestModule],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
app = module.createNestApplication<NestFastifyApplication>(
|
||||||
|
new FastifyAdapter(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Initialize app first
|
||||||
|
await app.init();
|
||||||
|
|
||||||
|
// Now middleware registration should work
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
res.setHeader('x-global-middleware', 'applied');
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.getHttpAdapter().getInstance().ready();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should register middleware successfully after init', () => {
|
||||||
|
return app
|
||||||
|
.inject({
|
||||||
|
method: 'GET',
|
||||||
|
url: '/test',
|
||||||
|
})
|
||||||
|
.then(({ statusCode, payload }) => {
|
||||||
|
expect(statusCode).to.equal(200);
|
||||||
|
expect(JSON.parse(payload)).to.deep.equal({ data: 'test_data' });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(async () => {
|
||||||
|
await app.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -157,6 +157,7 @@ export class FastifyAdapter<
|
|||||||
done: (err?: Error) => void,
|
done: (err?: Error) => void,
|
||||||
) => void | Promise<void>;
|
) => void | Promise<void>;
|
||||||
private isMiddieRegistered: boolean;
|
private isMiddieRegistered: boolean;
|
||||||
|
private pendingMiddlewares: Array<{ args: any[] }> = [];
|
||||||
private versioningOptions?: VersioningOptions;
|
private versioningOptions?: VersioningOptions;
|
||||||
private readonly versionConstraint = {
|
private readonly versionConstraint = {
|
||||||
name: 'version',
|
name: 'version',
|
||||||
@@ -303,6 +304,14 @@ export class FastifyAdapter<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await this.registerMiddie();
|
await this.registerMiddie();
|
||||||
|
|
||||||
|
// Register any pending middlewares that were added before init
|
||||||
|
if (this.pendingMiddlewares.length > 0) {
|
||||||
|
for (const { args } of this.pendingMiddlewares) {
|
||||||
|
(this.instance.use as any)(...args);
|
||||||
|
}
|
||||||
|
this.pendingMiddlewares = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public listen(port: string | number, callback?: () => void): void;
|
public listen(port: string | number, callback?: () => void): void;
|
||||||
@@ -717,6 +726,16 @@ export class FastifyAdapter<
|
|||||||
return 'fastify';
|
return 'fastify';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public use(...args: any[]) {
|
||||||
|
// Fastify requires @fastify/middie plugin to be registered before middleware can be used.
|
||||||
|
// If middie is not registered yet, we queue the middleware and register it later during init.
|
||||||
|
if (!this.isMiddieRegistered) {
|
||||||
|
this.pendingMiddlewares.push({ args });
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
return (this.instance.use as any)(...args);
|
||||||
|
}
|
||||||
|
|
||||||
protected registerWithPrefix(
|
protected registerWithPrefix(
|
||||||
factory:
|
factory:
|
||||||
| FastifyPluginCallback<any>
|
| FastifyPluginCallback<any>
|
||||||
|
|||||||
Reference in New Issue
Block a user