2

Is it possible to expose some selected endpoints only in Swagger UI, but make them unavailable at the server otherwise via direct HTTP call?

There is @Operation(hidden=true) to not to expose the endpoint in Swagger UI but still have it available on the server. I need just the "inverted behavior".

Use case: we have Swagger UI normally forbidden in production. I want to have some endpoints available only in Swagger UI for testing purposes during development.

Versions: Spring Boot 2.6.2, springdoc-openapi-ui 1.6.3.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118

2 Answers2

1

Use case:

  • we have Swagger UI normally forbidden in production.
  • I want to have some endpoints available only in Swagger UI for testing purposes during development.

The "springiest" solution to this (type of requirement) is probably Profiles!

We could:

@SpringBootApplication(exclude = {
  SpringDocWebMvcConfiguration.class,
  SpringDocConfiguration.class
})
public class MySpringApp {...

exclude openapi configuration from our main config (default profile) (since it is forbidden anyways).

Then we would introduce:

@Configuration
@Profile("documented") // ! this gets only activated/loaded, when "documented" is (one of) spring.aprofiles.active
@Import({
  SpringDocWebMvcConfiguration.class,
  SpringDocConfiguration.class
})
// customize API here ...
class DocConfig {
  // ...and/or here
}

All the controllers we want to "swagger", we also annotate with:

@Profile("documented") 
@[Rest]Controller public class MyDevController {
...

Unfortunately we can use @Profile on bean methods/classes only, to use it per "request mapping" (method), we'd have to copy & segregate the controllers:

One with:

@Profile("documented") // work in progress

and the orignal controller with:

@Profile("!documented") // as in prod

We have to mutually exclude them ("documented" vs "!documented"), since otherwise the (path) mapping won't be distinct.


With this, running our app in production (without "documented" profile), would:

  • skip the springdoc configuration
  • expose no:
    • swagger-ui
    • no api-endpoints
  • not load any controllers with profile "documented".

Running our app in dev/loaclly, we would set spring.profiles.active=documented, and springdoc will:

  • expose ui and endpoints of:
  • the "documented" (& default !) controllers.
xerx593
  • 12,237
  • 5
  • 33
  • 64
  • 1
    Thanks! I suspected something like this :) The key issue probably is "*Unfortunately we can use @Profile on bean methods/classes only, to use it per "request mapping" (method), we'd have to copy & segregate the controllers:", but we can live with it. I already have profiles for each environment, so I may just reuse them. By the way, I am giving you an extra credit for the word "the springiest" :) – Honza Zidek Jan 11 '22 at 13:04
0

I will leave @xerx593's answer as accepted, because it is indeed "the springiest", but finally we solved it differently. Here is our solution:

  1. All the public endpoints, which we want to expose in all the environments, have the URL starting with /api/....

  2. All the other endpoints, which we want to have accessible only via Swagger UI, have the URL starting with something else.

  3. We configured the server (via NGINX rules) so that only the URLs starting with /api/... are visible from the outside world.

Honza Zidek
  • 9,204
  • 4
  • 72
  • 118