Documenting API for Actix-web

Romain Lebran
Netwo
Published in
5 min readJan 18, 2024

Looking to generate an OpenAPI 3.0 documentation for an API running with actix-web and Rust ? There is a solution !

REST API has become a standard when it comes to API communication and the OpenAPI Specification (OAS) defines a standard to document and discover the capabilities of an API.

In mainstream languages like Java, Python, PHP… multiple proven solutions exist to generate OpenAPI 3 files but the Rust ecosystem is still young and needs more tooling around web services.

Today, multiple solutions exist when it comes to OpenAPI generation for actix-web, each with its advantages and drawbacks. In this article, we will list these solutions and see what drove us away from them to create a new crate to document our API.

We aim at closing the gap between Rust and other languages when it comes to web services documentation.

Current solutions

Paperclip:

Paperclip served us well for nearly 3 years. We used it to document our API’s and loved its interface.
Sadly, the project currently only supports Swagger v2 and OpenAPI 3.0 support is available via a conversion from Swagger v2. This lack of native OAS3 support didn’t allow us to document polymorphic endpoints and algebraic enums the way we wanted to.
We tried to work on OpenAPI 3.0 support for paperclip but sadly failed to find a way to integrate it without a complete re-write.

As said by the previous project owner:

Paperclip codegen is written for v2. Having a separate v3 module will require significant changes in the codegen modules.

Utoipa:

Utoipa works great when it comes to OpenAPI 3.0 with actix.
But it was not for us. Actix exposes two ways for user to define routing (via manual routing definition or via routing macros). Utoipa works with the routing macros while we prefer the explicit manual registration method.

Utoipa simple example (from utoipa Readme)

Utoipa also required too much boilerplate and duplication of information for us. We didn’t want a solution in which we had to manually register our operations and components (paths and components parameter of the openapi attribute in the example above).

We planned on building our solution on top of Utoipa for schema derivation but some issues (especially with generic struct which was a requirement for us, the alias solution was not enough) pushed us away from this solution.

Okapi:

Okapi looks promising but it doesn’t support actix which was a no go for us.

Oasgen:

Oasgen is pretty new, we haven’t had the chance to try it. It wasn’t available when we started our project and it still looks pretty early stage for now.

Introducing a new solution: Apistos

Apistos aims to be almost a drop in replacement for Paperclip with OpenAPI 3.0 support.

It is based on schemars which is widely used when it comes to json schema generation. Okapi is built on top of it.

We created this projet primarily for us to meet our need to provide our customers with a well-documented API. Since we deployed this projet, our customer are more and more autonomous with our API.

It supports the basics features of Paperclip plus few improvements:

  • All the things OpenAPI 3.0 brings compared to Swagger v2 (documentation of algebraic enums allowing documentation of polymorphic endpoints, links to reference external documentation, multiple examples…)
  • The ability to register default global parameter (Query, Header or Cookie). This is useful to document a parameter which might be present for all your operations and which might not be necessary in your code (because a middleware needs it or because it is extracted by another way) for example.
Defining default global parameters
  • The ability to tag all operations with the same set of tags.
Defining default global tag for all operations
  • The ability to tag operations at scope or resource level
Tag all operation for a scope (same applies for resource)

Example

The best way to present Apistos is to build a step by step example. Let’s do it together.

You can either follow this example or directly jump to our repository.

Creating a simple actix-web app:

First, lets generate a new cargo project with cargo

cargo new simple-todo

We then add our dependencies to the generated Cargo.toml file.

We create a new api.rs file in which we implement two simple handlers.

We can now edit our main.rs file to create a simple server to expose these handlers.

This service can now be run using

cargo run

Adding apistos to document our app:

First we update our Cargo.toml to add apistos and schemars dependencies (for now we rely on apistos_schemars, a temporary fork of schemars fixing an issue with multiple flatten on enums):

Adding apistos and schemars as dependencies

Then, we update our handlers to document them

We have something pretty close to what we are used to do with actix with 2 differences:

  • Our handler needs to be decorated with api_operation
  • All of the structs or enums used as input or output of our handlers must ApiComponent and JsonSchema.

We can now edit our main.rs file to wrap actix-web with apistos and expose our OpenAPI file

As we can see, most of the imports come from apistos instead of actix_web. The reason behind it is because apistos wraps the actix_web API to generate an OpenAPI file.

In the build method, we specify the /openapi.json path to expose our generated file. Let’s retrieve it !

First of all we need to run our app:

cargo run

Then we can curl our API documentation:

curl localhost:8080/openapi.json

If we feed the response to swagger for example, we have a simple valid OpenAPI 3.0.3 documentation ! 🎉

Swagger editor screen capture for our generated documentation

All code for this simple example can be found here.

Of course this example is pretty simple and doesn’t cover all the features exposed by apistos. To learn more, please have a look at our Github repository and our more complete yet simple petstore example.

About Netwo

Netwo is a France based full-remote company operating in the telecom sector.

If you are interested in learning more, feel free to visit our career page.

--

--

Romain Lebran
Netwo
Writer for

Scala and Rust software engineer. Pushing stuff to production.