Skip to content

Commit

Permalink
Merge pull request #2505 from botflux/master
Browse files Browse the repository at this point in the history
Support changing the OpenAPI document based on the request
  • Loading branch information
kamilmysliwiec authored Jul 4, 2023
2 parents 045aa4b + 83c3e8d commit dcfdf1b
Show file tree
Hide file tree
Showing 5 changed files with 183 additions and 4 deletions.
74 changes: 72 additions & 2 deletions e2e/express.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,14 @@ describe('Express Swagger', () => {
);
SwaggerModule.setup('api', app, swaggerDocument, {
jsonDocumentUrl: JSON_CUSTOM_URL,
yamlDocumentUrl: YAML_CUSTOM_URL
yamlDocumentUrl: YAML_CUSTOM_URL,
patchDocumentOnRequest: (req, res, document) => ({
...document,
info: {
...document.info,
description: (req as Record<string, any>).query.description
}
})
});

await app.init();
Expand All @@ -130,12 +137,27 @@ describe('Express Swagger', () => {
expect(Object.keys(response.body).length).toBeGreaterThan(0);
});

it('patched JSON document should be served', async () => {
const response = await request(app.getHttpServer()).get(
`${JSON_CUSTOM_URL}?description=My%20custom%20description`
);

expect(response.body.info.description).toBe("My custom description");
});

it('yaml document should be server in the custom url', async () => {
const response = await request(app.getHttpServer()).get(YAML_CUSTOM_URL);

expect(response.status).toEqual(200);
expect(response.text.length).toBeGreaterThan(0);
});

it('patched YAML document should be served', async () => {
const response = await request(app.getHttpServer()).get(
`${YAML_CUSTOM_URL}?description=My%20custom%20description`
);
expect(response.text).toContain("My custom description");
});
});

describe('custom documents endpoints with global prefix', () => {
Expand Down Expand Up @@ -209,7 +231,15 @@ describe('Express Swagger', () => {
customJsStr: CUSTOM_JS_STR,
customfavIcon: CUSTOM_FAVICON,
customSiteTitle: CUSTOM_SITE_TITLE,
customCssUrl: CUSTOM_CSS_URL
customCssUrl: CUSTOM_CSS_URL,
patchDocumentOnRequest<ExpressRequest, ExpressResponse> (req, res, document) {
return {
...document,
info: {
description: req.query.description
}
}
}
});

await app.init();
Expand Down Expand Up @@ -249,6 +279,46 @@ describe('Express Swagger', () => {
);
});

it('should patch the OpenAPI document', async () => {
const response: Response = await request(app.getHttpServer()).get(
'/swagger-ui-init.js?description=Custom%20Swagger%20description%20passed%20by%20query%20param'
);
expect(response.text).toContain(
`"description": "Custom Swagger description passed by query param"`
);
});

it('should patch the OpenAPI document based on path param of the swagger prefix', async () => {
const app = await NestFactory.create<NestExpressApplication>(
ApplicationModule,
new ExpressAdapter(),
{ logger: false }
);

const swaggerDocument = SwaggerModule.createDocument(
app,
builder.build()
);

SwaggerModule.setup('/:customer/', app, swaggerDocument, {
patchDocumentOnRequest<ExpressRequest, ExpressResponse> (req, res, document) {
return {
...document,
info: {
description: `${req.params.customer}'s API documentation`
}
}
}
});

await app.init();

const response: Response = await request(app.getHttpServer()).get('/customer-1/swagger-ui-init.js');

await app.close();
expect(response.text).toContain("customer-1's API documentation");
})

afterEach(async () => {
await app.close();
});
Expand Down
74 changes: 72 additions & 2 deletions e2e/fastify.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,14 @@ describe('Fastify Swagger', () => {
);
SwaggerModule.setup('api', app, swaggerDocument, {
jsonDocumentUrl: JSON_CUSTOM_URL,
yamlDocumentUrl: YAML_CUSTOM_URL
yamlDocumentUrl: YAML_CUSTOM_URL,
patchDocumentOnRequest: (req, res, document) => ({
...document,
info: {
...document.info,
description: (req as Record<string, any>).query.description
}
})
});

await app.init();
Expand All @@ -134,12 +141,27 @@ describe('Fastify Swagger', () => {
expect(Object.keys(response.body).length).toBeGreaterThan(0);
});

it('patched JSON document should be served', async () => {
const response = await request(app.getHttpServer()).get(
`${JSON_CUSTOM_URL}?description=My%20custom%20description`
);

expect(response.body.info.description).toBe("My custom description");
});

it('yaml document should be server in the custom url', async () => {
const response = await request(app.getHttpServer()).get(YAML_CUSTOM_URL);

expect(response.status).toEqual(200);
expect(response.text.length).toBeGreaterThan(0);
});

it('patched YAML document should be served', async () => {
const response = await request(app.getHttpServer()).get(
`${YAML_CUSTOM_URL}?description=My%20custom%20description`
);
expect(response.text).toContain("My custom description");
});
});

describe('custom documents endpoints with global prefix', () => {
Expand Down Expand Up @@ -214,7 +236,14 @@ describe('Fastify Swagger', () => {
customJsStr: CUSTOM_JS_STR,
customfavIcon: CUSTOM_FAVICON,
customSiteTitle: CUSTOM_SITE_TITLE,
customCssUrl: CUSTOM_CSS_URL
customCssUrl: CUSTOM_CSS_URL,
patchDocumentOnRequest: (req, res, document) => ({
...document,
info: {
...document.info,
description: (req as Record<string, any>).query.description
}
})
});

await app.init();
Expand Down Expand Up @@ -267,6 +296,47 @@ describe('Fastify Swagger', () => {
);
});

it('should patch the OpenAPI document', async function () {
const response: Response = await request(app.getHttpServer()).get(
"/custom/swagger-ui-init.js?description=Custom%20Swagger%20description%20passed%20by%20query%20param"
);
expect(response.text).toContain(
`"description": "Custom Swagger description passed by query param"`
);
});

it('should patch the OpenAPI document based on path param of the swagger prefix', async () => {
const app = await NestFactory.create<NestFastifyApplication>(
ApplicationModule,
new FastifyAdapter(),
{ logger: false }
);

const swaggerDocument = SwaggerModule.createDocument(
app,
builder.build()
);

SwaggerModule.setup('/:tenantId/', app, swaggerDocument, {
patchDocumentOnRequest<ExpressRequest, ExpressResponse> (req, res, document) {
return {
...document,
info: {
description: `${req.params.tenantId}'s API documentation`
}
}
}
});

await app.init();
await app.getHttpAdapter().getInstance().ready();

const response: Response = await request(app.getHttpServer()).get('/tenant-1/swagger-ui-init.js');

await app.close();
expect(response.text).toContain("tenant-1's API documentation");
})

afterEach(async () => {
await app.close();
});
Expand Down
10 changes: 10 additions & 0 deletions e2e/manual-e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ async function bootstrap() {
}
});

SwaggerModule.setup("/:tenantId/api-docs", app, document, {
patchDocumentOnRequest: (req, res, document1) => ({
...document1,
info: {
...document1.info,
title: `${(req as Record<string, any>).params.tenantId}'s API document`
}
})
})

USE_FASTIFY
? (app as NestFastifyApplication).useStaticAssets({
root: publicFolderPath,
Expand Down
1 change: 1 addition & 0 deletions lib/interfaces/swagger-custom-options.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ export interface SwaggerCustomOptions {
urls?: Record<'url' | 'name', string>[];
jsonDocumentUrl?: string;
yamlDocumentUrl?: string;
patchDocumentOnRequest?: <TRequest = any, TResponse = any> (req: TRequest, res: TResponse, document: OpenAPIObject) => OpenAPIObject;
}
28 changes: 28 additions & 0 deletions lib/swagger-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,10 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(req, res, document);
}
}

if (!swaggerInitJS) {
Expand All @@ -126,6 +130,14 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(
req,
res,
document
);
}
}

if (!swaggerInitJS) {
Expand All @@ -150,6 +162,10 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(req, res, document);
}
}

if (!html) {
Expand All @@ -170,6 +186,10 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(req, res, document);
}
}

if (!html) {
Expand Down Expand Up @@ -199,6 +219,10 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(req, res, document);
}
}

if (!jsonDocument) {
Expand All @@ -213,6 +237,10 @@ export class SwaggerModule {

if (!document) {
document = lazyBuildDocument();

if (options.swaggerOptions.patchDocumentOnRequest) {
document = options.swaggerOptions.patchDocumentOnRequest(req, res, document);
}
}

if (!yamlDocument) {
Expand Down

0 comments on commit dcfdf1b

Please sign in to comment.