Metaswitch Swagger Codegen for Rust accepted upstream

As big proponents of the Rust programming language, we were pleased to get our Swagger code generator for Rust clients and servers accepted upstream last Friday.



Swagger (also known as OpenAPI) is a specification for defining APIs (generally "RESTful" APIs, although it's not too opinionated about what that means).  You can take a YAML file that looks a bit like...


...and automatically generate clients (which make requests over the API) and servers (which handle requests) in a variety of programming languages, as well as documentation.

We use Swagger to specify the APIs between the microservices that make up our telephony products.  By leaving the details of how to encode/decode HTTP and JSON to the Swagger code generator, we can focus more on the "business logic" - the application-specific code that adds function (and value) to our products.  These products are written in a variety of programming languages - historically C++ and Java but we're now focussing on Rust for its expressiveness, performance and reliability.

There has been a Swagger Rust code generator for just the client available for a few months, but our generator generates both the client and the server.  The key benefit of generating the client and server together is that this means they can implement precisely the same functional API (defined by a Rust trait, which makes it easy to compose our clients and servers in new ways.  For example, if we found that one API hop is so heavily-used that invoking it remotely over HTTP is a performance issue, we could replace it with a direct function call.

As this is Rust, all validation of input data (or at least all that can be expressed by the Swagger schema) is performed before it reaches the business logic and from that point on, the data is strongly-typed (serialized/deserialized using Serde).   Errors in input validation and incorrect assumptions within business logic are common sources of error, so auto-generated validation and strong typing removes these whole classes of bugs.  We made the decision to be opinionated about hiding the underlying HTTP(S) details from the business logic as this improves encapsulation and portability.  It also makes it easier to write robust unit tests - as well as generating an HTTP-backed client, we also generate a mock client (based on mockers), which helps further with this.

The generated code uses the standard Hyper HTTP stack  for both the client and the server.  Currently, it's using v0.10, which is synchronous, but we're shortly going to move to Hyper v0.11, which is asynchronous (using Tokio, Futures, etc.) and will give better scalability.  Fortunately, even the current API is built around Futures, so business logic written today won't need modification when this becomes available.

As well as simple JSON/HTTP APIs, our code generator also supports authorization (combined with authentication using pluggable modules), XML/HTTP APIs, multipart bodies and "file" types that can contain large binary blobs.

Rust code using our Swagger code generator is already in production at a small number of customers, and we look forward to developing this further and it becoming more widely deployed, both at our customers and across the open-source ecosystem.