Leveraging OpenAPI for Foxglove Development

Generating server routes and accurate documentation from an OpenAPI spec
Roman ShtylmanRoman Shtylman ·
Esther WeonEsther Weon ·
5 min read
Published
Leveraging OpenAPI for Foxglove Development

Foxglove now leverages OpenAPI to generate routes and documentation for our REST API.

Though Foxglove primarily focuses on building tools to accelerate robotics development, we also like to think about ways to streamline our own workflows. Integrating OpenAPI helps us ship software more efficiently and deliver consistent value to our users.

Experiencing developer friction

Foxglove provides a set of REST APIs to help robotics teams organize and access their data. We initially wrote our APIs with Typescript to minimize context-switching between the front-end and back-end. Each route lived as a separate file in our codebase, with the logic for its supported HTTP verbs. Routes used common modules for authentication, but typically implemented their own unique validation rules.

While this approach was easy to bootstrap, we ran into several points of friction as our team grew and the API evolved. Development slowed significantly as we added more server routes – each new route required an engineer to hand-author Typescript types and corresponding JSON schemas to feed into our validation library (AJV).

It was also increasingly difficult to keep our documentation updated and accurate. Since routes were implemented and then documented separately – often by different engineers – many nuances about route behavior and user impact were lost in translation. It was also painful to validate that a route’s behavior aligned with its documentation, since each route was responsible for its own authentication and response types.

We had to find a way to reduce boilerplate server code and automatically generate accurate documentation that could evolve with our routes.

Integrating with OpenAPI

To solve these problems, we decided to generate server code from a hand-authored spec file. To avoid reinventing parsers and validators, we decided to use a standard format like OpenAPI, we hoped to avoid reinventing parsers and validators.

Our generator uses @apidevtools/swagger-parser to read a YAML file, validates that it conforms to the OpenAPI spec, and resolves references. It then converts each path’s query and body parameters into TypeScript types using json-schema-to-typescript, and finally generates that route’s source code as a string output:

process diagram

As a final step, our generator formats the generated code with prettier for easier reading.

Using our generated output

To more easily leverage our generated types and schemas (index.generated.ts), we stored those files alongside their corresponding business logic files (index.ts) and unit tests (index.test.ts).

Our generated files each provide a controller function that accepts one argument – the HTTP verbs that need to be implemented for that route. We import this function from our hand-authored business logic, thus effectively checking types and validating both requests and responses:

import { controller } from./index.generated.ts

controller({
	get: async (req, res) => {
    res.json({
      hello: “world!// hand-authored code
    });
  },
  post: async (req, res) => {
    // req.body.myField
  },
});

Realizing the benefits of OpenAPI

With OpenAPI, we’ve reduced the amount of boilerplate code we write, kept our automatically deployed documentation up-to-date with minimal effort, and even set up linting to enforce consistent formatting in our spec files.

We’ve also leveraged the OpenAPI spec’s security feature. Our API keys have role-based access controls to limit their access. Once we specify the role required under each path’s HTTP verb, the generator verifies that the authorization is applied before invoking the hand-authored business logic. This offloads route security, so that engineers can now write business logic and review changes without worrying about this overhead.

We’re excited to continue leaning on spec files for generating client libraries in different languages. By streamlining our own development workflows, we’ve been able to deliver higher quality software and more features faster for our users.


Read more:

How to Configure Vercel with Cloudflare
tutorial
How to Configure Vercel with Cloudflare

Understanding the ACME protocol and SSL/TLS Encryption settings

Adrian MacneilAdrian MacneilAdrian Macneil
5 min read
Introducing Text Annotations in Foxglove’s Image Panel
tutorial
visualization
Introducing Text Annotations in Foxglove’s Image Panel

Annotate your robots’ images with metadata for easier debugging

Sam NosenzoSam NosenzoSam Nosenzo
Esther WeonEsther WeonEsther Weon
3 min read

Get blog posts sent directly to your inbox.

Ready to try Foxglove?

Get started for free