mirror of
https://github.com/nestjs/nest.git
synced 2026-02-21 23:11:44 +00:00
fix(platform-fastify): FastifyAdapter Middleware no run
This commit is contained in:
@@ -1,4 +1,11 @@
|
||||
import { Controller, Get, MiddlewareConsumer, Module } from '@nestjs/common';
|
||||
import {
|
||||
Controller,
|
||||
Get,
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
Query,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
FastifyAdapter,
|
||||
NestFastifyApplication,
|
||||
@@ -7,36 +14,74 @@ import { Test } from '@nestjs/testing';
|
||||
import { expect } from 'chai';
|
||||
import { ApplicationModule } from '../src/app.module';
|
||||
|
||||
const INCLUDED_VALUE = 'test_included';
|
||||
const QUERY_VALUE = 'test_query';
|
||||
const REQ_URL_VALUE = 'test_req_url';
|
||||
const RETURN_VALUE = 'test';
|
||||
const SCOPED_VALUE = 'test_scoped';
|
||||
const WILDCARD_VALUE = 'test_wildcard';
|
||||
|
||||
@Controller()
|
||||
class TestController {
|
||||
@Get('express_style_wildcard/wildcard_nested')
|
||||
express_style_wildcard() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('test')
|
||||
test() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('query')
|
||||
query() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/wildcard_nested')
|
||||
wildcard_nested() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
|
||||
@Get('tests/included')
|
||||
included() {
|
||||
return RETURN_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Controller(QUERY_VALUE)
|
||||
class TestQueryController {
|
||||
@Get()
|
||||
[QUERY_VALUE](@Query('test') test: string) {
|
||||
return test;
|
||||
}
|
||||
}
|
||||
|
||||
@Module({
|
||||
imports: [ApplicationModule],
|
||||
controllers: [TestController],
|
||||
controllers: [TestController, TestQueryController],
|
||||
})
|
||||
class TestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply((req, res, next) => res.end(INCLUDED_VALUE))
|
||||
.forRoutes({ path: 'tests/included', method: RequestMethod.POST })
|
||||
.apply((req, res, next) => res.end(`${REQ_URL_VALUE}${req.url}`))
|
||||
.forRoutes('req/url/')
|
||||
.apply((req, res, next) => res.end(WILDCARD_VALUE))
|
||||
.forRoutes('express_style_wildcard/*')
|
||||
.apply((req, res, next) => res.end(WILDCARD_VALUE))
|
||||
.forRoutes('tests/(.*)')
|
||||
.apply((req, res, next) => res.end(QUERY_VALUE))
|
||||
.forRoutes('query')
|
||||
.apply((req, res, next) => next())
|
||||
.forRoutes(TestQueryController)
|
||||
.apply((req, res, next) => res.end(SCOPED_VALUE))
|
||||
.forRoutes(TestController)
|
||||
.apply((req, res, next) => res.end(RETURN_VALUE))
|
||||
.exclude({ path: QUERY_VALUE, method: -1 })
|
||||
.forRoutes('(.*)');
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +98,7 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
await app.init();
|
||||
});
|
||||
|
||||
it(`forRoutes(*)`, () => {
|
||||
it(`forRoutes((.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
@@ -71,15 +116,76 @@ describe('Middleware (FastifyAdapter)', () => {
|
||||
.then(({ payload }) => expect(payload).to.be.eql(SCOPED_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/*)`, () => {
|
||||
it(`query?test=${QUERY_VALUE} forRoutes(query)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard',
|
||||
url: '/query',
|
||||
query: {
|
||||
test: QUERY_VALUE
|
||||
}
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`${QUERY_VALUE}?test=${QUERY_VALUE} forRoutes(${QUERY_VALUE})`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: QUERY_VALUE,
|
||||
query: {
|
||||
test: QUERY_VALUE
|
||||
}
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(QUERY_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(tests/(.*))`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(express_style_wildcard/*)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/express_style_wildcard/wildcard_nested',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`forRoutes(req/url/)`, () => {
|
||||
const reqUrl = '/test'
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: `/req/url${reqUrl}`,
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(`${REQ_URL_VALUE}${reqUrl}`));
|
||||
});
|
||||
|
||||
it(`GET forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'GET',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(WILDCARD_VALUE));
|
||||
});
|
||||
|
||||
it(`POST forRoutes(POST tests/included)`, () => {
|
||||
return app
|
||||
.inject({
|
||||
method: 'POST',
|
||||
url: '/tests/included',
|
||||
})
|
||||
.then(({ payload }) => expect(payload).to.be.eql(INCLUDED_VALUE));
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await app.close();
|
||||
});
|
||||
|
||||
@@ -36,7 +36,6 @@ import {
|
||||
InjectOptions,
|
||||
Response as LightMyRequestResponse,
|
||||
} from 'light-my-request';
|
||||
import * as pathToRegexp from 'path-to-regexp';
|
||||
import {
|
||||
FastifyStaticOptions,
|
||||
PointOfViewOptions,
|
||||
@@ -65,15 +64,30 @@ type FastifyHttpsOptions<
|
||||
https: https.ServerOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
* The following type assertion is valid as we enforce "middie" plugin registration
|
||||
* which enhances the FastifyRequest.RawRequest with the "originalUrl" property.
|
||||
* ref https://github.com/fastify/middie/pull/16
|
||||
* ref https://github.com/fastify/fastify/pull/559
|
||||
*/
|
||||
type FastifyRawRequest<TServer extends RawServerBase> =
|
||||
RawRequestDefaultExpression<TServer> & { originalUrl?: string };
|
||||
|
||||
export class FastifyAdapter<
|
||||
TServer extends RawServerBase = RawServerDefault,
|
||||
TRawRequest extends RawRequestDefaultExpression<TServer> = RawRequestDefaultExpression<TServer>,
|
||||
TRawRequest extends FastifyRawRequest<TServer> = FastifyRawRequest<TServer>,
|
||||
TRawResponse extends RawReplyDefaultExpression<TServer> = RawReplyDefaultExpression<TServer>,
|
||||
> extends AbstractHttpAdapter<
|
||||
TServer,
|
||||
FastifyRequest<RequestGenericInterface, TServer, TRawRequest>,
|
||||
FastifyReply<TServer, TRawRequest, TRawResponse>
|
||||
> {
|
||||
TRequest extends FastifyRequest<
|
||||
RequestGenericInterface,
|
||||
TServer,
|
||||
TRawRequest
|
||||
> = FastifyRequest<RequestGenericInterface, TServer, TRawRequest>,
|
||||
TReply extends FastifyReply<
|
||||
TServer,
|
||||
TRawRequest,
|
||||
TRawResponse
|
||||
> = FastifyReply<TServer, TRawRequest, TRawResponse>,
|
||||
> extends AbstractHttpAdapter<TServer, TRequest, TReply> {
|
||||
protected readonly instance: FastifyInstance<
|
||||
TServer,
|
||||
TRawRequest,
|
||||
@@ -121,11 +135,11 @@ export class FastifyAdapter<
|
||||
}
|
||||
|
||||
public reply(
|
||||
response: TRawResponse | FastifyReply,
|
||||
response: TRawResponse | TReply,
|
||||
body: any,
|
||||
statusCode?: number,
|
||||
) {
|
||||
const fastifyReply: FastifyReply = this.isNativeResponse(response)
|
||||
const fastifyReply: TReply = this.isNativeResponse(response)
|
||||
? new Reply(
|
||||
response,
|
||||
{
|
||||
@@ -150,23 +164,23 @@ export class FastifyAdapter<
|
||||
return fastifyReply.send(body);
|
||||
}
|
||||
|
||||
public status(response: TRawResponse | FastifyReply, statusCode: number) {
|
||||
public status(response: TRawResponse | TReply, statusCode: number) {
|
||||
if (this.isNativeResponse(response)) {
|
||||
response.statusCode = statusCode;
|
||||
return response;
|
||||
}
|
||||
return (response as FastifyReply).code(statusCode);
|
||||
return (response as TReply).code(statusCode);
|
||||
}
|
||||
|
||||
public render(
|
||||
response: FastifyReply & { view: Function },
|
||||
response: TReply & { view: Function },
|
||||
view: string,
|
||||
options: any,
|
||||
) {
|
||||
return response && response.view(view, options);
|
||||
}
|
||||
|
||||
public redirect(response: FastifyReply, statusCode: number, url: string) {
|
||||
public redirect(response: TReply, statusCode: number, url: string) {
|
||||
const code = statusCode ?? HttpStatus.FOUND;
|
||||
return response.status(code).redirect(url);
|
||||
}
|
||||
@@ -248,29 +262,25 @@ export class FastifyAdapter<
|
||||
);
|
||||
}
|
||||
|
||||
public setHeader(response: FastifyReply, name: string, value: string) {
|
||||
public setHeader(response: TReply, name: string, value: string) {
|
||||
return response.header(name, value);
|
||||
}
|
||||
|
||||
public getRequestHostname(request: FastifyRequest): string {
|
||||
public getRequestHostname(request: TRequest): string {
|
||||
return request.hostname;
|
||||
}
|
||||
|
||||
public getRequestMethod(request: FastifyRequest): string {
|
||||
public getRequestMethod(request: TRequest): string {
|
||||
return request.raw ? request.raw.method : request.method;
|
||||
}
|
||||
|
||||
public getRequestUrl(request: FastifyRequest): string {
|
||||
return request.raw ? request.raw.url : request.url;
|
||||
public getRequestUrl(request: TRequest): string;
|
||||
public getRequestUrl(request: TRawRequest): string;
|
||||
public getRequestUrl(request: TRequest & TRawRequest): string {
|
||||
return this.getRequestOriginalUrl(request.raw || request);
|
||||
}
|
||||
|
||||
public enableCors(
|
||||
options:
|
||||
| CorsOptions
|
||||
| CorsOptionsDelegate<
|
||||
FastifyRequest<RequestGenericInterface, TServer, TRawRequest>
|
||||
>,
|
||||
) {
|
||||
public enableCors(options: CorsOptions | CorsOptionsDelegate<TRequest>) {
|
||||
if (typeof options === 'function') {
|
||||
this.register(require('fastify-cors'), () => options);
|
||||
} else {
|
||||
@@ -293,28 +303,15 @@ export class FastifyAdapter<
|
||||
await this.registerMiddie();
|
||||
}
|
||||
return (path: string, callback: Function) => {
|
||||
const re = pathToRegexp(path);
|
||||
const normalizedPath = path === '/*' ? '' : path;
|
||||
const normalizedPath = path.endsWith('/*')
|
||||
? `${path.slice(0, -1)}(.*)`
|
||||
: path;
|
||||
|
||||
// The following type assertion is valid as we enforce "middie" plugin registration
|
||||
// which enhances the FastifyInstance with the "use()" method.
|
||||
// The following type assertion is valid as we use import('middie') rather than require('middie')
|
||||
// ref https://github.com/fastify/middie/pull/55
|
||||
const instanceWithUseFn = this.instance as unknown as FastifyInstance & {
|
||||
use: Function;
|
||||
};
|
||||
|
||||
instanceWithUseFn.use(
|
||||
this.instance.use(
|
||||
normalizedPath,
|
||||
(req: any, res: any, next: Function) => {
|
||||
const queryParamsIndex = req.originalUrl.indexOf('?');
|
||||
const pathname =
|
||||
queryParamsIndex >= 0
|
||||
? req.originalUrl.slice(0, queryParamsIndex)
|
||||
: req.originalUrl;
|
||||
|
||||
if (!re.exec(pathname + '/') && normalizedPath) {
|
||||
return next();
|
||||
}
|
||||
if (
|
||||
requestMethod === RequestMethod.ALL ||
|
||||
req.method === RequestMethod[requestMethod] ||
|
||||
@@ -344,13 +341,17 @@ export class FastifyAdapter<
|
||||
}
|
||||
|
||||
private isNativeResponse(
|
||||
response: TRawResponse | FastifyReply,
|
||||
response: TRawResponse | TReply,
|
||||
): response is TRawResponse {
|
||||
return !('status' in response);
|
||||
}
|
||||
|
||||
private async registerMiddie() {
|
||||
this.isMiddieRegistered = true;
|
||||
await this.register(require('middie'));
|
||||
await this.register(import('middie'));
|
||||
}
|
||||
|
||||
private getRequestOriginalUrl(rawRequest: TRawRequest) {
|
||||
return rawRequest.originalUrl || rawRequest.url;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user