Skip to content

Commit

Permalink
Merge pull request #11650 from nestjs/fix/global-prefix-exclude-with-…
Browse files Browse the repository at this point in the history
…versioning

fix(core): global prefix exclude when versioning is turned on
  • Loading branch information
kamilmysliwiec committed May 24, 2023
2 parents 974c946 + 0faddb4 commit b1be7a3
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 3 deletions.
66 changes: 66 additions & 0 deletions integration/versioning/e2e/uri-versioning.spec.ts
Expand Up @@ -352,4 +352,70 @@ describe('URI Versioning', () => {
await app.close();
});
});

// ======================================================================== //
describe('with the global prefix enabled and an excluded route', () => {
before(async () => {
const moduleRef = await Test.createTestingModule({
imports: [AppModule],
}).compile();

app = moduleRef.createNestApplication();
app.setGlobalPrefix('api', { exclude: ['/foo/bar'] });
app.enableVersioning({
type: VersioningType.URI,
defaultVersion: '1',
});
await app.init();
});

describe('GET /', () => {
it('V1', () => {
return request(app.getHttpServer())
.get('/api/v1')
.expect(200)
.expect('Hello World V1!');
});

it('V2', () => {
return request(app.getHttpServer())
.get('/api/v2')
.expect(200)
.expect('Hello World V2!');
});

it('V3', () => {
return request(app.getHttpServer()).get('/api/v3').expect(404);
});

it('No Version', () => {
return request(app.getHttpServer()).get('/api').expect(404);
});
});

describe('GET /foo/bar (excluded from the API prefix)', () => {
it('V1', () => {
return request(app.getHttpServer())
.get('/v1/foo/bar')
.expect(200)
.expect('Hello FooBar!');
});

it('V2', () => {
return request(app.getHttpServer()).get('/v2/foo/bar').expect(404);
});

it('V3', () => {
return request(app.getHttpServer()).get('/v3/foo/bar').expect(404);
});

it('No Version', () => {
return request(app.getHttpServer()).get('/foo/bar').expect(404);
});
});

after(async () => {
await app.close();
});
});
});
53 changes: 50 additions & 3 deletions packages/core/router/route-path-factory.ts
@@ -1,10 +1,11 @@
import {
flatten,
RequestMethod,
VERSION_NEUTRAL,
VersioningOptions,
VersioningType,
VERSION_NEUTRAL,
flatten,
} from '@nestjs/common';
import { VersionValue } from '@nestjs/common/interfaces';
import {
addLeadingSlash,
isUndefined,
Expand Down Expand Up @@ -57,7 +58,14 @@ export class RoutePathFactory {

if (metadata.globalPrefix) {
paths = paths.map(path => {
if (this.isExcludedFromGlobalPrefix(path, requestMethod)) {
if (
this.isExcludedFromGlobalPrefix(
path,
requestMethod,
versionOrVersions,
metadata.versioningOptions,
)
) {
return path;
}
return stripEndSlash(metadata.globalPrefix || '') + path;
Expand Down Expand Up @@ -109,15 +117,54 @@ export class RoutePathFactory {
public isExcludedFromGlobalPrefix(
path: string,
requestMethod?: RequestMethod,
versionOrVersions?: VersionValue,
versioningOptions?: VersioningOptions,
) {
if (isUndefined(requestMethod)) {
return false;
}
const options = this.applicationConfig.getGlobalPrefixOptions();
const excludedRoutes = options.exclude;

if (
versionOrVersions &&
versionOrVersions !== VERSION_NEUTRAL &&
versioningOptions?.type === VersioningType.URI
) {
path = this.truncateVersionPrefixFromPath(
path,
versionOrVersions,
versioningOptions,
);
}
return (
Array.isArray(excludedRoutes) &&
isRouteExcluded(excludedRoutes, path, requestMethod)
);
}

private truncateVersionPrefixFromPath(
path: string,
versionValue: Exclude<VersionValue, typeof VERSION_NEUTRAL>,
versioningOptions: VersioningOptions,
) {
if (typeof versionValue !== 'string') {
versionValue.forEach(version => {
if (typeof version === 'string') {
path = this.truncateVersionPrefixFromPath(
path,
version,
versioningOptions,
);
}
});
return path;
}

const prefix = `/${this.getVersionPrefix(
versioningOptions,
)}${versionValue}`;

return path.startsWith(prefix) ? path.replace(prefix, '') : path;
}
}

0 comments on commit b1be7a3

Please sign in to comment.