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

Director, Modern API

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
An Exploration in Rust: Musings From a Java/C++ Developer
Why Rust? It’s fast (runtime performance) It’s small (binary size) It’s safe (no memory leaks) It’s modern (build system, language features, etc) When Is It Worth It? Embedded systems (where it is implied that interpreted […]
Getting Started with CSS Container Queries
For as long as I’ve been working full-time on the front-end, I’ve heard about the promise of container queries and their potential to solve the majority of our responsive web design needs. And, for as […]
Simple improvements to making decisions in teams
Software development teams need to make a lot of decisions. Functional requirements, non-functional requirements, user experience, API contracts, tech stack, architecture, database schemas, cloud providers, deployment strategy, test strategy, security, and the list goes on. […]
JavaScript Bundle Optimization – Polyfills
If you are lucky enough to only support a small subset of browsers (for example, you are targeting a controlled set of users), feel free to move along. However, if your website is open to […]