Why document a REST API as code?
Tags: aws, serverless, devops, beginners
Published: 2020-01-19 13:02:23

# TL;DR

If you're already familiar with OpenAPI and its place in the application life-cycle, skip to the [tooling](#tooling) chapter which is the core of this blog post.

Stay tuned for the next article. I'll discuss implementation with OpenAPI, and Terraform support tooling.

Thanks for reading!

# Topic break-down

- [TL;DR](#tldr)
- [Topic break-down](#topic-break-down)
- [Why document a REST API as code?](#why-document-a-rest-api-as-code)
- [What is OpenAPI?](#what-is-openapi)
- [Where does OpenAPI fit in?](#where-does-openapi-fit-in)
  - [Requirements, Analysis and Design](#requirements-analysis-and-design)
  - [Code and Test](#code-and-test)
  - [Production and Maintenance](#production-and-maintenance)
- [Tooling?](#tooling)
  - [Design and Development](#design-and-development)
  - [Implementation frameworks](#implementation-frameworks)
  - [Code generation](#code-generation)
  - [Validation and Testing](#validation-and-testing)
- [What's next?](#whats-next)
- [Further reading](#further-reading)

# Why document a REST API as code?

There are many ways to create API's these days, through the use of frameworks such as [Express](https://expressjs.com/) (Node environment), [Java Spring](https://spring.io/), or Cloud native solutions such as [API Gateway](https://aws.amazon.com/api-gateway/) from Amazon Web Services.

The overarching problem I see with using these solutions __solely__ is that they do not describe __"API as Code"__. You might wonder, why should I care? here's a few reasons why:

- The ability to __generate server and client__ side code from a programming language agnostic REST API definition file (OpenAPI).
- As a __communication tool__, it is the basis of documentation that is readable by both front-end, business, third parties (public API's), and back-end developers alike.
- Follows the __Infrastructure as Code paradigm__, we can test and validate our REST API definitions (endpoint, models, security, and input & output) more easily. We can _version control_ our API definitions.
- __Development environment friendly__, easy to generate REST API stubs and have front / back end developers program against a specification.
- Supports a formal __Object Model specification__ (e.g. [JSON Schema](https://json-schema.org/)) that specifies inputs and outputs of API endpoints.
- __Keeps your implementation and formal API specification document in sync__. It is rare that documentation keeps in sync with the real world situation. We usually forget to update our documentation throughout all the changes.

Having said that, how does OpenAPI propose to solve this?

# What is OpenAPI?

Good design and programming practices recommend the use of [interface definitions](https://stackoverflow.com/questions/383947/what-does-it-mean-to-program-to-an-interface). An interface definition defines what a system or a piece of code (module etc) is doing from a high level standpoint, and then you program against that interface.

This achieves decoupling of the actual implementation code from the interface code (the outside world in a broad sense). We're free to choose how we implement against the contract as long as we satisfy it. Furthermore, we're simplifying application design by abstracting away as much of the implementation details as we can ([black box principle](https://en.wikipedia.org/wiki/Black_box)).
  
OpenAPI does exactly that, it provides an interface definition that bridges the front-facing application and the back-end  "processing / data storage" part of the application (typical 3-tier architecture situation). 

How it does that is through a REST API specification document that defines in code (YAML or JSON) API endpoints and data models ([JSON Schema](https://json-schema.org/)) amongst other things. With this programming language agnostic API definition file you can generate code across application tiers (front-end and back-end), and validate input and output against its JSON Schema definition.

A good and well documented design of this interface will therefore benefit the whole application development life-cycle. 

There are a few steps involved in getting this all working together. What we will cover in brief is:

- [Where does OpenAPI 3 fit in your development process?](#where-does-openapi-fit-in)
- [What kind of tooling is available?](#tooling)
- And finally, [the next steps](#whats-next) I'll cover in later blog posts

I won't cover the structure of the language in depth just yet, I'll do that in later blog posts with a sample application. For now, review [this](https://swagger.io/docs/specification/basic-structure/) short explanation to get an idea.

# Where does OpenAPI fit in?

Broadly we can identify [these](https://www.ibm.com/support/knowledgecenter/zosbasics/com.ibm.zos.zappldev/zappldev_11.htm) application development phases, and I'll put several together to condense the discussion:
- __Requirements, Analysis and Design;__ What are we building?
- __Code & Test__, We're building building and testing it.
- __Production & Maintenance__, It is in production and running

Here we can have several iterations of phases depending upon project management style (Agile, Waterfall etc.) Again, a very broad topic. For now let's consider these phases, where does OpenAPI fit in?

## Requirements, Analysis and Design

In this phase OpenAPI will be used by front and back-end developers to agree on what is required  at both sides to satisfy business and architectural requirements. This in itself is a very expansive discussion, what OpenAPI does is formalize the output of that design process into code that can be used in subsequent development phases.
OpenAPI can also formalize security concepts, such as publicly accessible or requiring authenticated access, as well as extensions.

Extensions (e.g. [Google Cloud Endpoints](https://cloud.google.com/endpoints/docs/openapi/openapi-extensions), [AWS API Gateway](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html)) enable vendors or companies to add "features" to the API specification. For instance, AWS API Gateway has developed extensions to codify its integration with backend services. That means an endpoint, e.g. ``` GET /customer/2 ```, can be directly integrated with a DynamoDB database through a Velocity template. Or, with a code execution service such as [Lambda](https://aws.amazon.com/lambda/). 

All of this formalized into a document that satisfies both the why and the how of the API. Which brings us to the next steps, code and test. 

## Code and Test

In this stage normally the Tester will have a document that outlines the test cases from the business requirements side, but it will have to wait to do any [contract testing](https://www.mabl.com/blog/understanding-contract-testing-microservices-mabl) before an API is available to do so. With an OpenAPI document you get a head start, tests can be generated from the specification (up to a certain point).

On the developer side, the API can already be generated as a client and server side [stub](https://en.wikipedia.org/wiki/Method_stub) from the OpenAPI document. That facilitates independent client and server side  development.

Developers and testers can iteratively work through testing and developing contracts in a much more rapid pace than before. Furthermore, both [client](https://apisyouwonthate.com/blog/the-many-amazing-uses-of-json-schema-client-side-validation) and [server](https://apisyouwonthate.com/blog/server-side-validation-with-api-descriptions) side can leverage the validation of data models through the use of the included JSON Schema definition.

## Production and Maintenance

Once the application hits the _production & maintenance_ phase the specification is effective for:
- __Verification__, here we verify the OpenAPi specification document is the same as what is deployed. Tooling such as _Dredd_ can help here
-  __Testing__, what we intend to deploy to production, does it operate according to the specification?
-  __Documentation__, answering such questions as;
   -  what has been built,
   -  how can developers, internally and potentially externally, implement against the API specification.

# Tooling?

Now we're getting to the meat and bones of OpenAPI and why I love to use it, the tooling!

![dilbert](https://c1.staticflickr.com/5/4084/5039801864_3f3345df94.jpg)

It may take a few thousand lines of code to specify every single thing about your API, but then the automation you have unleashed makes this a productivity booster you wouldn't believe.

So lets have a look shall we.

## Design and Development

- __[Swagger hub and Swagger Editor](https://swagger.io/solutions/api-design/)__, Swagger generally (as creators of Swagger/OpenAPI) provide tooling across the application life-cycle. I particularly like their Editor to validate the specification on the fly, and as a documentation/code generation tool.
- __Visual Studio Code__. This editor has a lot of plugins that simplify editing large OpenAPI documents, the plugins I use:
  - [OpenAPI Editor with Tree view](https://marketplace.visualstudio.com/items?itemName=42Crunch.vscode-openapi), I like this extension a lot since it breaks down this massive document into a tree structure that is quick to navigate.
  - [OpenAPI Document generation](https://marketplace.visualstudio.com/items?itemName=ms-openapi.OpenApiDocumentTools), creates a visual representation of your specification.
  - [Swagger viewer](https://marketplace.visualstudio.com/items?itemName=Arjun.swagger-viewer), it's the same viewer that the Swagger Editor uses.
  - [OpenAPI Linting](https://marketplace.visualstudio.com/items?itemName=mermade.openapi-lint)

## Implementation frameworks

A few of the major frameworks, and cloud native solutions that I have used:
- __[AWS API Gateway](https://aws.amazon.com/about-aws/whats-new/2018/09/amazon-api-gateway-adds-support-for-openapi-3-api-specification/)__, you can either use IAC tooling or the GUI to import a Swagger/OpenAPI document and it will create the endpoints automatically. There are specific [AWS Extensions](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions.html) to the OpenAPI specification that will add Authentication, and [Integration with AWS Lambda](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-integration.html) for instance.
- __Java Spring Boot / Maven integration__, [this](https://www.north-47.com/knowledge-base/generate-spring-boot-rest-api-using-swagger-openapi/) article describes a possible integration between the two.
- __Node/ExpressJS__
  - [OpenAPI Enforcer](https://byu-oit.github.io/openapi-enforcer/) has a specific side project that will generate the endpoint in your Express app automatically. It also included data validation via the JSON Schema definitions in the OpenAPI document, see the [validation](#validation) sub-section.


## Code generation

Both of these provide a similar set of client and server generator output
- __[OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator)__ , see the table below for supported languages and frameworks.

|   | Languages / Frameworks  |
|---|---|
|  __API clients__ | ActionScript, Ada, Apex, Bash, C, C# (.net 2.0, 3.5 or later, .NET Standard 1.3 - 2.0, .NET Core 2.0), C++ (cpp-restsdk, Qt5, Tizen), Clojure, Dart (1.x, 2.x), Elixir, Elm, Eiffel, Erlang, Go, Groovy, Haskell (http-client, Servant), Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured, Spring 5 Web Client, MicroProfile Rest Client), Kotlin, Lua, Nim, Node.js/JavaScript (ES5, ES6, AngularJS with Google Closure Compiler annotations, Flow types), Objective-C, OCaml, Perl, PHP, PowerShell, Python, R, Ruby, Rust (rust, rust-server), Scala (akka, http4s, scalaz, swagger-async-httpclient), Swift (2.x, 3.x, 4.x, 5.x), Typescript (AngularJS, Angular (2.x - 8.x), Aurelia, Axios, Fetch, Inversify, jQuery, Node, Rxjs)  |
|  __Server stubs__ |  Ada, C# (ASP.NET Core, NancyFx), C++ (Pistache, Restbed, Qt5 QHTTPEngine), Erlang, F# (Giraffe), Go (net/http, Gin), Haskell (Servant), Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, Jersey, RestEasy, Play Framework, PKMST, Vert.x), Kotlin (Spring Boot, Ktor, Vertx), PHP (Laravel, Lumen, Slim, Silex, Symfony, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Rust (rust-server), Scala (Finch, Lagom, Play, Scalatra) |

- __[Swagger CodeGen](https://swagger.io/tools/swagger-codegen/)__ and [Github](https://github.com/swagger-api/swagger-codegen), supports fewer languages and frameworks, but may fit your needs exactly.

|   | Languages / Frameworks  |
|---|---|
|  __API clients__ | ActionScript, Ada, Apex, Bash, C# (.net 2.0, 3.5 or later), C++ (cpprest, Qt5, Tizen), Clojure, Dart, Elixir, Elm, Eiffel, Erlang, Go, Groovy, Haskell (http-client, Servant), Java (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign, RestTemplate, RESTEasy, Vertx, Google API Client Library for Java, Rest-assured), Kotlin, Lua, Node.js (ES5, ES6, AngularJS with Google Closure Compiler annotations) Objective-C, Perl, PHP, PowerShell, Python, R, Ruby, Rust (rust, rust-server), Scala (akka, http4s, swagger-async-httpclient), Swift (2.x, 3.x, 4.x, 5.x), Typescript (Angular1.x, Angular2.x, Fetch, jQuery, Node)  |
|  __Server stubs__ |  Ada, C# (ASP.NET Core, NancyFx), C++ (Pistache, Restbed), Erlang, Go, Haskell (Servant), Java (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy, Play Framework, PKMST), Kotlin, PHP (Lumen, Slim, Silex, Symfony, Zend Expressive), Python (Flask), NodeJS, Ruby (Sinatra, Rails5), Rust (rust-server), Scala (Finch, Lagom, Scalatra) |

## Validation and Testing

- __[Dredd](https://github.com/apiaryio/dredd)__ is a CLI tool / Javascript Library that can validate your specification against a running Server. OpenAPI 3 support is still experimental (!)
- __[OpenAPI Enforcer](https://byu-oit.github.io/openapi-enforcer/)__, validation library for server side Node (optionally Express).
- __[Swagger Test generation](https://github.com/apigee-127/swagger-test-templates#readme)__ automatically creates test cases for specific HTTP status codes and it can also do load testing.
-  __[JSON Schema validators / generators / testing](https://json-schema.org/implementations.html)__, a lot of tooling exists to validate, generate, and test based on JSON Schemas.

# What's next?

Next week I'll demonstrate with [Terraform](https://www.terraform.io/), and AWS API Gateway how we can use an OpenAPI specification to create a server side REST API with validation.

Let me know in the comments below if this article was useful for you and what else you'd like to read about. 

If you're already using OpenAPI, please tell me in the comments what your experiences are with it.

Thanks for reading and till next week!

# Further reading

- [The difference between OpenAPI and Swagger](https://swagger.io/blog/api-strategy/difference-between-swagger-and-openapi/)
- [OpenAPI Tools](https://openapi.tools)
- [OpenAPI 3.0.2 specification](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md)
- [Basic structure of OpenAPI](https://swagger.io/docs/specification/basic-structure/)
- [Why API documentation matters](https://swagger.io/blog/api-documentation/what-is-api-documentation-and-why-it-matters/)
- [How to use OpenAPI with Spring Boot](https://www.north-47.com/knowledge-base/generate-spring-boot-rest-api-using-swagger-openapi/)
- [API Design vs. Code first](https://apisyouwonthate.com/blog/api-design-first-vs-code-first)
- [JSON Schema client side validation](https://apisyouwonthate.com/blog/the-many-amazing-uses-of-json-schema-client-side-validation)
- [JSON Schema server side validation](https://apisyouwonthate.com/blog/server-side-validation-with-api-descriptions)
- [What is Swagger and Why do you need it?](https://www.8bitmen.com/what-is-swagger-and-why-do-you-need-it-for-your-project/)
- [JSON Schema Implementations](https://json-schema.org/implementations.html)