Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow to disable Swagger UI #2840

Merged

Conversation

lucas-gregoire
Copy link
Contributor

PR Checklist

Please check if your PR fulfills the following requirements:

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build related changes
  • CI related changes
  • Other... Please describe:

What is the current behavior?

Issue Number: none

Currently when using SwaggerModule.setup it serves all files of Swagger UI and API definitions generated on the fly (JSON and YAML). It isn't possible for now to only serve API definitions.

I see two uses-cases for this feature:

  • You want to serve multiple API definitions in your Nest application, so you might want to enable the UI only for the "default" API and disable it for other ones.
  • You already have a Swagger UI served somewhere else in your infrastructure and just want to make it point the API definition of your Nest app. So the UI might be disabled to reduce noise.

What is the new behavior?

This PR introduces a way to disable the Swagger UI to only generate API definitions.
A new flag swaggerUiEnabled is available in SwaggerModule.setup options.

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

In this PR, I also improved some documentation and removed dead code


httpAdapter.get(
normalizeRelPath(`${finalPath}/swagger-ui-init.js`),
(req, res) => {
res.type('application/javascript');
const document = getBuiltDocument();
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getBuiltDocument handles internally a kind of "cache" of the document, to avoid rebuilding it for each request

Comment on lines -179 to -200
if (!document) {
document = lazyBuildDocument();
if (!swaggerUiHtml) {
swaggerUiHtml = buildSwaggerHTML(baseUrlForSwaggerUI, swaggerOptions);
}

if (options.swaggerOptions.patchDocumentOnRequest) {
const documentToSerialize =
options.swaggerOptions.patchDocumentOnRequest(req, res, document);
const htmlPerRequest = buildSwaggerHTML(
baseUrlForSwaggerUI,
documentToSerialize,
options.swaggerOptions
);
return res.send(htmlPerRequest);
}

if (!html) {
html = buildSwaggerHTML(
baseUrlForSwaggerUI,
document,
options.swaggerOptions
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildSwaggerHTML was not using the document internally, so I simplified this part

Comment on lines -210 to -231
if (!document) {
document = lazyBuildDocument();
}

if (options.swaggerOptions.patchDocumentOnRequest) {
const documentToSerialize =
options.swaggerOptions.patchDocumentOnRequest(req, res, document);
const htmlPerRequest = buildSwaggerHTML(
baseUrlForSwaggerUI,
documentToSerialize,
options.swaggerOptions
);
return res.send(htmlPerRequest);
if (!swaggerUiHtml) {
swaggerUiHtml = buildSwaggerHTML(baseUrlForSwaggerUI, swaggerOptions);
}

if (!html) {
html = buildSwaggerHTML(
baseUrlForSwaggerUI,
document,
options.swaggerOptions
);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

buildSwaggerHTML was not using the document internally, so I simplified this part

@@ -66,7 +66,6 @@ function toTags(
*/
export function buildSwaggerHTML(
baseUrl: string,
swaggerDoc: OpenAPIObject,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was dead code

Comment on lines +154 to +163
it.each([
'/apidoc',
'/apidoc/',
'/apidoc/swagger-ui-bundle.js',
'/apidoc/swagger-ui-init.js'
])('should not serve "%s"', async (file) => {
const response = await request(app.getHttpServer()).get(file);

expect(response.status).toEqual(404);
});
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All Swagger UI resources are throwing 404 when disabled

@lucas-gregoire lucas-gregoire changed the title feat: allow to disable swagger UI feat: allow to disable Swagger UI Feb 15, 2024
@lucas-gregoire
Copy link
Contributor Author

@kamilmysliwiec Would it be possible to review and/or merge this PR please ?

Copy link

@ulidtko ulidtko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM; not tested.

Formatting-wise, I'd ask to undo gratuitous changes (removing trailing comma, quotes, semicolons, line-splitting, etc) to minimize diff, preserve git blame, and simplify review — IF I was maintainer of this code, who I'm not.

I've landed here at all, because was investigating a breakage of Swagger-UI in a Nest app, caused by switching to a server-side bundler (esbuild), caused by other reasons.

Comment on lines +12 to +17
/**
* If `false`, only API definitions (JSON and YAML) will be served (on `/{path}-json` and `/{path}-yaml`).
* This is particularly useful if you are already hosting a Swagger UI somewhere else and just want to serve API definitions.
* Default: `true`.
*/
swaggerUiEnabled?: boolean;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for aligning the code with what's actually documented at https://docs.nestjs.com/openapi/introduction#setup-options

Copy link

@motabass motabass May 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is it in the docs but not in the code? Made me scratch my head for half an hour..

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ulidtko @kamilmysliwiec

agreeing to @motabass, the docs are live already, can this be merged please?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, would be nice if this would be merged, it's quite confusing that it's in the docs but you can't actually use it 😬

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i agree merge it, the docs are live already, i want use selfdefine openapi-ui

Copy link
Contributor Author

@lucas-gregoire lucas-gregoire Jun 12, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry that both PRs haven't been merged simultaneously (or at least the code before the docs). The PR for the docs was merged in 1 day, while this one has been waiting (and ready) for 4 months 😿

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For those who want to try this feature before its release, I've published a forked package @lsge/swagger that you can install as a replacement for @nestjs/swagger:

Change this in your package.json:

-    "@nestjs/swagger": "7.4.0",
+    "@nestjs/swagger": "npm:@lsge/[email protected]",

@rookie-luochao
Copy link

i support merge it, the docs are live already, i want use selfdefine openapi-ui

@UXabre
Copy link

UXabre commented Jun 4, 2024

Yes, came here because the docs already mention the flag swaggerUiEnabled and I was confused that it didn't work until I saw this PR...

@mehulbaid
Copy link

@kamilmysliwiec can you merge?

@kamilmysliwiec kamilmysliwiec merged commit c541886 into nestjs:master Jul 1, 2024
1 check passed
@kamilmysliwiec
Copy link
Member

lgtm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants