Sep 28, 2017

Aggregate Services into a Single Swagger

By now most companies that have pointed their ship towards some sort of service architecture (in buzz words, microservices) have also discovered an API explorer to ease the pains of developers that are trying to consume services that they know nothing about. Swagger is a popular option when it comes to self-documenting API explorers. In Spring Boot, with a matter of two dependencies and a little configuration you can be running with a “Swagger” endpoint to hit that exposes all available REST endpoints.

This is great, no doubt. However, when you start to expand to more than a handful of services it can become cumbersome to keep track of each service’s Swagger page. Also, depending on how your load balancer is set up it may be hard to target an individual service’s Swagger page from behind the load balancer. For these reasons and a bit of curiosity, I decided to explore aggregating multiple swaggers into their own service. The rest of this post will illustrate how to go about doing this so that you can have a single Swagger that looks something like the image below.

Swagger Aggregate

Swagger service aggregating 4 different services.

Swagger already has support for aggregating multiple service’s API documentation, which they call “resources”. It’s just a matter of knowing where to look and what to override. To get started I stood up a very basic Spring Boot service that includes the normal swagger dependencies (shown below). The snippets throughout the post are pulled from my full project on GitHub, swagger-aggregate.

The only piece that is absolutely necessary to make this work is to create a class that overrides the SwaggerResourcesProvider. It expects an implementation of get() that returns a set of SwaggerResource objects. These point the aggregate to the various Swagger endpoints by providing the service name, url of the api-docs, and the version of Swagger it’s running. In my sample application, I pushed these definitions into the application.yml file and pulled them into a custom object using the @ConfigurationProperties annotation. This is not needed but felt like a good chance to push the configuration out of the code.

To add a new service to the aggregate you simply update the application.yml file with the details of the service’s Swagger. You can define absolute urls pointing to the api-docs or relative if they share the same domain. The example project is pointing directly at the Swagger’s Petstore example docs so that the project actually has some content if you run it.

With services behind a load balancer, it’s possible all of their api-docs might be at the same /v2/api-docs endpoint. If you need to get around this you can customize the api-docs path to be more specific to the service.

The last thing you may notice in the example project is a small redirect endpoint that points /swagger to /swagger-ui.html. It’s always felt unneeded to type that extra ‘-ui.html’, so this fixes that.

Are there ways you’d improve this? Hook it up to service discovery? Enable authentication at the aggregate level?

The source for this project can be found on GitHub.

About the Author

Matt Schroeder profile.

Matt Schroeder

Principal Technologist

A wide range of professional experience and a Master’s Degree in Software Engineering have become the foundation that enables Matt to lead teams to the best solution for every problem.

One thought on “Aggregate Services into a Single Swagger

  1. Roman says:

    First of all, thank you for sharing this post. I am trying to emulate it and you say that we can define absolute urls pointing to the api-docs. However, when I execute it using absolute urls, the output is “Failed to load API definition -> undefined http://localhost:8070/apihttp://localhost:8081/api“, i.e., it is composing the original api gateway URL (http://localhost:8070/api) with the resource url (http://localhost:8081/api) instead of replacing it. Do you know why?

    Best regards.

  2. Ganesh says:

    Can we add custom header like Authorization Header to all aggregated Swaggers?

  3. Declan Treanor says:

    SwaggerServicesConfig: where can I find this?

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Blog Posts
Android Development for iOS Developers
Android development has greatly improved since the early days. Maybe you tried it out when Android development was done in Eclipse, emulators were slow and buggy, and Java was the required language. Things have changed […]
Add a custom object to your Liquibase diff
Adding a custom object to your liquibase diff is a pretty simple two step process. Create an implementation of DatabaseObject Create an implementation of SnapshotGenerator In my case I wanted to add tracking of Stored […]
Keeping Secrets Out of Terraform State
There are many instances where you will want to create resources via Terraform with secrets that you just don’t want anyone to see. These could be IAM credentials, certificates, RDS DB credentials, etc. One problem […]
Validating Terraform Plans using Open Policy Agent
When developing infrastructure as code using terraform, it can be difficult to test and validate changes without executing the code against a real environment. The feedback loop between writing a line of code and understanding […]