Reputation: 309
I have built a nestjs webapi and implemented versioning at controller and action level as per https://docs.nestjs.com/techniques/versioning
The solution i am looking into is, i want to generate 2 different swagger based on the controller version. For example, i have 2 controller defined for 2 different version. if i hit [example.com/v1/swagger] , it should load only v1 version controller swagger doc and similarly for v2
Upvotes: 9
Views: 7056
Reputation: 11
I was recently looking into how to separate out the API versions into separate swagger documents and wanted to post my solution to the issue on GitHub, but it's been locked so I'll leave the solution here.
If you look at the SwaggerModule.setup()
method documentation, it accepts a SwaggerCustomOptions
object as the 4th parameter. Inside the options object, there is a property for patchDocumentOnRequest
that allows you to define a custom function that will be executed on every request for the documentation and allows you to manipulate the document before it is served.
Using this function, we can filter out the paths that do not match the requested version.
SwaggerModule.setup(':version/swagger', app, swaggerDocument, {
patchDocumentOnRequest: (req, _res, document) => {
// NOTE: Make a deep copy of the original document or it will be modified on subsequent calls!
const copyDocument = JSON.parse(JSON.stringify(document));
const version = (req as Request).params.version;
const isValidVersion = /^v[0-9]+$/;
if (!version || !isValidVersion.test(version)) {
return;
}
for (const route in document.paths) {
if (route.startsWith(`/${version}`)) {
continue;
}
delete copyDocument.paths[route];
}
return copyDocument;
},
});
Note: This solution will only work for URI versioned APIs.
Upvotes: 1
Reputation: 135
app.enableVersioning(); should be called before SwaggerModule.createDocument(...)
Source: https://github.com/nestjs/swagger/issues/1495#issuecomment-898311614
Upvotes: 6
Reputation: 714
I recently updated my API to support versioning. I couldn't get the Swagger docs to load correctly. Here is my solution, I hope it helps!
Before, we had used app.setGlobalPrefix(APP_ROUTE_PREFIX)
to define the prefix.
const APP_ROUTE_PREFIX = 'api/v2';
app.setGlobalPrefix(APP_ROUTE_PREFIX);
Swagger docs were mounted as:
SwaggerModule.setup(`${APP_ROUTE_PREFIX}/docs`, app, document);
To adopt versioning, the following was changed.
const APP_ROUTE_PREFIX = 'api';
app
.enableVersioning({ type: VersioningType.URI, defaultVersion: '2' })
.setGlobalPrefix(APP_ROUTE_PREFIX);
:version
in the path. SwaggerModule.setup(`${APP_ROUTE_PREFIX}/:version/docs`, app, document);
@Controller({ path: 'objects/:id', version: ['2', '3'] })
@Version('2')
getPageV2(): Promise<Observable<unknown>> {
return this.service.getOkayData();
}
@Version('3')
getPageV3(): Promise<Observable<unknown>> {
return this.service.getBetterData();
}
Upvotes: 5