WHY SHOULD YOU USE OAS?
There is a huge amount of APIs over the whole worldwide web.
And many of them are not documented as they should be. So, you might hit the wall if you want to know more about how some API works.
In my professional career, I did hit the wall numerous times.
I don’t blame developers as this is tedious work they/we should do.
But using OAS we are all able, not only developers but also the managers, as well anyone who is (non)technically involved into the project to create, the easy way, a great API with great documentation from the start.
One of the beauties of using Swagger(OAS), is that non-technical expert might create an API and together with technical experts might define API and generate a much of boilerplate code for developers.
That way we boost developers productivity. Paired with time management skill we create great results and a happy client = happy employer = happy employee.
Imagine you can try out the requests straight out of the documentation!? That would be or better to say, IS fun!
I won’t delve too much into Swagger tooling as there are already great documentations about it.
What I will do is go into what API is, give you basics of OAS (Open API Specification) so you don’t get overwhelmed when you get in touch with it.
After reading this post you can start right away using Swagger and OAS with good basics and principles on how OAS / Swagger works.
So, I will show you the basic building blocks of writing OAS file.
But first, let’s start with what API is!?
WHAT IS API?
It’s an acronym for Application Programming Interface.
API defines how two (or more) pieces of software talk to each other.
There are several types of APIs:
- Web service APIs
- Websocket APIs
- Hardware APIs
- OS APIs
- Library based APIs
- Class based APIs
- Object remoting APIs
But in this text I’ll be covering strictly Web APIs, to be more precise, REST APIs. Since Web APIs are more than REST APIs, we have:
SO WHAT IS REST?
REST stands for REpresentational State Transfer and is not a protocol like the ones listed above.
REST is a set of architectural principles. So the architecture is the thing which differentiates a REST service of the other services.
WHAT IS AN OAS DEFINITION FILE?
It’s a simple file defining everything you can do with a collection of request coming to your API as well as responses.
Each definition file contains:
- Server location
- Type of security
- All requests used in API
- Data send to API
- Data retrieved of an API
- Types of HTTP status codes returned
To make it visually and easier to understand, an API request is shown below:
QUICK INTRO TO YAML
PHP developers using Symfony probably already know what YAML is.
As they use it regularly to configure for example Symfony framework.
YAML (an acronym for YAML Aint Markup Language) is a structured data format just like JSON is. So it’s used for data, NOT CONTENT.
The benefit of YAML is that it minimizes characters (compared to JSON or XML). So it’s mostly used for configuration files. It is structured like a dictionary (key: value).
Hence space between “key:” and “value”. ie.:
Since you can get into hierarchical depth or levels, the way you indent is by “white space“. No “tab indent” available!
It’s less characters compared to JSON:
Even more less than XML:
<name> <firstName>Denis</firstName> <lastName>Jakus</lastName> </name>
In YAML types are determined from context:
name: Denis (string) weight: 104.5 (float) years: 38 (integer) social_number: HR123456789 (string)
As you can see strings don’t need to be quoted (nor single nor double-quoted)!
You quote only if something might be interpreted as number or boolean.
Then you can use single or double-quotes.
How do you define the list?
Well, just use a dash (-) in front of an item, ie:
animals: - type: Lion name: Sahara description: Some description years_old: 5 weight: 150.4 - type: Tiger name: Awahara description: Some description years_old: 2 weight: 90.7 color: white
Since there are no quotation marks, how do we preserve lines and spaces?
We use special characters! Since we can use multiple characters I’ll state here only a few, most used ones:
- | means that we preserve spaces and lines i.e.:
- > fold new lines
name: | Denis Jakus Outputs: Denis Jakus name: > Denis Jakus Outputs: Denis Jakus
When commenting we use “#”
name: Denis #This is my name
ADDITIONAL SPECIAL COMMAND
$ref special OAS key that indicates that the value is a reference to a structure somewhere in the part of a file.
HOW TO CREATE DEFINITION FILE?
If using ie this domain:
Then just create file named filename.yaml with contents like:
swagger: '2.0' #might be 3.0 as new version is available info: # Document metadata version: "0.0.1" title: Example api service host: api.example.com basePath: /getlist schemes: - https
HOW TO DEFINE REQUEST?
Each request has to have:
- URL endpoint
- HTTP method
- Path params
- Query params
- Request body
Example of an defined POST request taken from editor.swagger.io:
paths: /pet: post: tags: - "pet" summary: "Add a new pet to the store" description: "" operationId: "addPet" consumes: - "application/json" - "application/xml" produces: - "application/xml" - "application/json" parameters: - in: "body" name: "body" description: "Pet object that needs to be added to the store" required: true schema: $ref: "#/definitions/Pet" responses: 405: description: "Invalid input" security: - petstore_auth: - "write:pets" - "read:pets"
WHAT IS SCHEMA?
The schema indicates the structure of the data we use.
It’s based on the JSON Schema Specification (http://json-schema.org/) and can be many levels.
We use schema to define what are the keys in key-value pairs and to define what type of data are values.
Steps to create SCHEMA:
- Create a key called definitions at the end of the file
- Add a level and give it the name from the $ref value
- Add a properties key
- For each top level element in the JSON, add a key of its name.
- Add a type key that says what type of data it is
- Add other keys(objects) for other data
definitions: newAnimal: properties: name: type: string species: type: string weight: type: number years_old: type: integer color: type: string habitat: type: object properties: country: type: string continent: type: string zooParkName: type: string isInZoo: type: boolean
As you can see from the above picture, there might be a lot of indentation, so this is where $ref comes handy. So we can rewrite the above like this:
definitions: newAnimal: properties: name: type: string species: type: string weight: type: number years_old: type: integer color: type: string habitat: $ref: '#/definitions/home'
and then write “home” somewhere else in the file like this:
home: properties: country: type: string continent: type: string zooParkName: type: string isInZoo: type: boolean
You can also add array like this:
definitions: newAnimal: properties: name: type: string species: type: string weight: type: number years_old: type: integer color: type: string habitat: $ref: '#/definitions/home' sibblings: type: array $ref: '#/definitions/sibbling
and then add sibbling somewhere else in the file:
sibbling: properties: id: type: integer name: type: string
Since many of the things in OAS is self-explanatory like required, response or request I’ll skip this and move to something very useful.
Imagine you have two objects one for request and the other for a response. They probably have a very similar structure. But they also might have the only one difference between them, like included “id”.
In that case, we use “AllOf“, i.e.:
animal: allOf: - $ref: '#/definitions/newAnimal' - properties: id: type: integer
As you can see, this key “allOf” is pretty useful.
WHAT ABOUT SECURITY?
Since this may be a little more complex topic to write about, I’ll just sum it up. If you don’t need security, great! Nothing to do here.
But, if you do want to secure your API then you use it like this:
- define security definition
- add name of your definition
- add type of security
- add name of header or query parameter
- set in value to know if it’s coming from query or header
Example when using OAuth security:
securityDefinitions: petstore_auth: type: "oauth2" authorizationUrl: "http://petstore.swagger.io/oauth/dialog" flow: "implicit" scopes: write:pets: "modify pets in your account" read:pets: "read your pets" api_key: type: "apiKey" name: "api_key" in: "header"
The above example has a little more stuff I did not explain. Like authorizationUrl, flow, scopes. These are self-explanatory.
- authorizationUrl – endpoint to do the authorization
- flow – are scenarios an API client performs to get an access token from the authorization server (more at https://swagger.io/docs/specification/authentication/oauth2/)
- scopes – access to specific resource
AND HOW DO I HANDLE ERRORS?
Errors are simply different responses. And they should include schema for every potential status code. You define error code and description. Additionally you add schema.
responses: 200: description: Everything is okay 401: description: Uh no, you can't go here schema: $ref: '#/definition/error'
They indicate format of the data in request and response body by using “Content-Type” header (i.e. application/json).
- consumes for requests
- produces for responses
consumes: - application/json - application/xml produces: - application/xml - application/json
We got several tools by Swagger:
- Swagger Editor
- Swagger CodeGen
- Swagger UI
- Swagger Hub
Helps when creating OAS file (syntax checking, autogenerated documentation visible instantly…).
Builds client SDKs based on OAS definition, does bunch of boilerplate code out of the box. Can generate a code for lot of known frameworks (Angular, React, .NET…)
Generates api documentation
Hosts all of these tools above on a single platform.
This is the only, Swagger, thing which is not open source.
So you got to pay for it!
I find Swagger pretty useful. We at hte company are using it for every project we start. So i recommend you to take a look at it!
There are alternatives to Swagger. But using Swagger inside my everyday work projects, I did not have any need to try out something differently.
If you did try and you do have better experience using other tools, please comment at LinkedIn or Twitter.
I hope you learned something new today!