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

Centralized API Documentation #108

Closed
octopus-prime opened this issue Oct 6, 2019 · 8 comments
Closed

Centralized API Documentation #108

octopus-prime opened this issue Oct 6, 2019 · 8 comments
Labels
question Further information is requested

Comments

@octopus-prime
Copy link

Assume more than one micro-service, all implemeting APIs and providing a swagger-ui.
To access all this API documentation from a single URL, a solution can be implemented using the SpringFox library.

See https://dzone.com/articles/centralized-documentation-in-microservice-spring-b

As you can see the implementation uses the classes

  • springfox.documentation.swagger.web.SwaggerResource
  • springfox.documentation.swagger.web.SwaggerResourcesProvider

which of course are not provided by spingdoc.

So how can i achieve this goal with springdoc?

@springdoc springdoc added the enhancement New feature or request label Oct 10, 2019
@springdoc
Copy link
Collaborator

Hi,

This is an interesting feature, but we don't consider it as a a top priority, as this will require to change the behaviour of the official swagger-ui jars.
In addition, this behaviour is very specific to services that relies on Eureka.
If you need to achieve it with springdoc-openapi.

  • You can have your back-end services to ship only the springdoc-openapi-core or springdoc-openapi-weblfux depending on your project APIs.
  • This way, all your back-end services will expose their documentation using the following path by default; /v3/api-docs
  • Then, you will need the swagger-ui to retrieve the documentation from the registred endepoints on Eureka.

@octopus-prime
Copy link
Author

In addition, this behaviour is very specific to services that relies on Eureka.

Or Zuul, or Kubernetes, etc.
There are a lot of service-discovery implementations in spring.

Then, you will need the swagger-ui to retrieve the documentation from the registred endpoints

That's the part of question. How to?
Without SwaggerResource and SwaggerResourcesProvider...

@bnasslahsen
Copy link
Contributor

Hi @octopus-prime,

Its now possible to agregate multiple OpenAPI definitions using springdoc-openapi.
Here is a sample in a microservices architecture:

@kyle18th
Copy link

kyle18th commented Jun 9, 2020

@bnasslahsen I noticed that it is a spring-cloud-gateway implementation, have you ever thought about zuul?

@bnasslahsen
Copy link
Contributor

bnasslahsen commented Jun 9, 2020

@kyle18th,

springdoc is about the integration with spring. There is nothing different about using spring-cloud-gateway and a spring-boot application...

The integration principle should be the same with between spring-cloud-gateway and Zuul..

Note that Zuul, is now deprecated and most of projects using zuul, migrate to spring-cloud-gateway...

@paolodedo
Copy link

Hello,

Zuul and Eureka are just service-discovery products like other ones, as stated by @octopus-prime , so if you want to use it with Kubernetes (as my case) you are free to do.

The problem is another one: springdoc-openapi is very powerful but unfortunately, it relies on swagger UI for the presentation part, instead of having its own.

So, as for now, it is basically impossible to provide another implementation of springfox.documentation.swagger.web.SwaggerResource &
springfox.documentation.swagger.web.SwaggerResourcesProvider to io.springfox.springfox-swagger2.2.9.2.

For now, we have to make it work this way, waiting for the team to upgrade:

  • springdoc-openapi: create spring-doc models;
  • swagger-ui : accept spring-doc models.

So, when will this improvement be available?

Thanks

@danielgatis-mb
Copy link

danielgatis-mb commented Jul 29, 2020

This works for me:

public class Application {

  private final String servicePattern = "myproject\\-(?<name>.*?)\\-service";

  @Autowired
  private EurekaClient discoveryClient;

  @Bean
  public PatternServiceRouteMapper serviceRouteMapper() {
    return new PatternServiceRouteMapper(servicePattern, "${name}");
  }

  @GetMapping("/swagger-config.json")
  public Map<String, Object> swaggerConfig() {
    Map<String, Object> rtn = new LinkedHashMap<>();
    List<Map<String,String>> urls = new LinkedList<>();

    discoveryClient
      .getApplications()
      .getRegisteredApplications()
      .forEach(application -> {
        Pattern p = Pattern.compile(servicePattern, Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher(application.getName());

        if (m.find()) {
          String g = m.group(1);
          String serviceName = g.toLowerCase();

          Map<String, String> url = new LinkedHashMap<>();
          url.put("url", "/" + serviceName + "/v3/api-docs");
          url.put("name", serviceName);
          urls.add(url);
        }
      });

    rtn.put("urls", urls);
    return rtn;
}

  public static void main(String[] args) {
    SpringApplication.run(Application.class, args);
  }
}

application.properties

springdoc.swagger-ui.configUrl=/swagger-config.json

swagger-config.json sample

{
  "urls": [
    {
      "url": "http://localhost:8088/v3/api-docs/users",
      "name": "users"
    },
    {
      "url": "http://localhost:8088/v3/api-docs/stores",
      "name": "stores"
    }
  ]
}

@daniel-schel
Copy link

A simpler solution based on the reply from @danielgatis-mb using spring cloud discovery abstraction:

@RestController
public class SwaggerUiConfig {

    @Autowired
    private DiscoveryClient discoveryClient;

    @GetMapping("/swagger-config.json")
    public Map<String, Object> swaggerConfig() {
        Map<String, Object> config = new LinkedHashMap<>();
        List<SwaggerUrl> urls = new LinkedList<>();
        discoveryClient.getServices().forEach(serviceName -> 
                        discoveryClient.getInstances(serviceName).forEach(serviceInstance ->
                                urls.add(new SwaggerUrl(serviceName, serviceInstance.getUri() + "/v3/api-docs"))
                        )
        );
        config.put("urls", urls);
        return config;
    }
}

@bnasslahsen bnasslahsen added question Further information is requested and removed enhancement New feature or request labels Jan 21, 2022
@springdoc springdoc locked as resolved and limited conversation to collaborators Jan 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

6 participants