Problem
I want to design a REST API so others can review it is is implemented. (This article will talk about ASP.NET, but designing the API this way can work for any language.)
Background
Everyone knows about how Swagger describes a REST API, and how ASP .NET makes it easy to publish a swagger endpoint for your API.
The /swagger
endpoint is generated by the Swashbuckle extensions to ASP.NET from your controllers their parameters. The site is a generic one, driven by a swagger.json
file, which has linked to at the top of the Swagger page. Here’s the beginning of the one for the demo API shown above:
{
"openapi": "3.0.1",
"info": {
"title": "DemoApi",
"version": "v1"
},
"servers": [
{
"url": "http://localhost:58301/demo-api"
}
],
"paths": {
"/api/demos/{id}": {
"get": {
"tags": [
"DemoApi"
],
"summary": "Gets request JSON",
"description": "Get a demo by id",
"parameters": [
{
"name": "id",de
"in": "path",
"description": "id of object",
"required": true,
"schema": {
"type": "string",
"description": "id of object"
}
}
],
Notice the first line says it’s openapi: "3.0.1"
. In 2015, Swagger became the OAS (OpenAPI Specification not the Organization of American States). The JSON conforms to the OAS specification, which is here. It’s not a long or complex spec, and you can digest the entire thing in a sitting.
With OAS, you can write the specification for you API, including all the input and output objects in a yaml file, and do an API review before writing one line of code. That is the solution to our problem.
Of course you can use a Word document, or spreadsheet, and those may be useful for some audiences, but to really accurately specify an API you need to be precise, which OAS is.
This can be really useful in multiple scenarios. First, most likely you aren’t the one consuming your API, so you need to collaborate with another team to work out the details of the API. Do these objects return all the data they need? Do the GETs have enough parameters to filter results as the client wants. If you used a build to generate the API for review, the iterations are much longer.
Second, you may have standards for things like pagination, queries, security, error codes, etc. Using a company-standard OAS file as a starting point can get your API conformant from the get go.
Finally, an architect may be responsible for designing the API, getting it reviewed, and ensuring it meets standards, but she may not be the one implementing it. Giving developers an OAS file lets them have a very clear specification of the API that ensures the code will match design without going through the vagaries of a Word doc or Excel spreadsheet.
Editing an OAS File
It’s just YAML, so any editor will do, but the VSCode Swagger Viewer by Arjun G allows you to edit an OAS file and see the Swagger site in real time as you edit the file. Below you can see the source and the preview in VSCode.
If you get an error in the OAS in VSCode, it can sometimes be subtle. Look for a red mark in the scroll bar, or open the Problems tab.
If you download and run the swagger-editor it puts errors in red at the top of the preview. I prefer VSCode, and just keep an eye on the preview. If it doesn’t update, you probably have an error.
This blog is meant to get you into writing an OAS file, and not the details on writing it. The OAS spec, plus the many examples you can get show plenty of ways to write the API.
Generating Code
Now that you have your API design set in OAS concrete, what’s next. Code!
SmartBear, who now owns Swagger, has services and tools for editing OAS files and generating code. The swagger-editor mentioned above has a menu to generate various client and server code.
I wanted it automated and more control over the code generation, so I downloaded the swagger-codegen tool to generate code from the command line. Here’s my commands to generate C# code:
Remove-Item $OutputFolder\*.* -Force -Recurse
java -jar $jarPath generate -i $OASFile -o $OutputFolder -l aspnetcore --api-package="shoot.test.cond" --model-package="dang.test.one"
Your mileage may vary, but in my case, I always had to tweak the generated code a bit, so there is a post processing script that does a few updates to controllers and classes.
The generated controllers give you a great starting point but you will certainly change these to fill in the implementation, add your security, etc. You shouldn’t have to change the classes, and if you do, I recommend using a script to make the changes, for reasons which will rapidly become apparent.
Your OAS file will have changes after you generate the code. You’ll add new controllers, tweak a parameter, etc. How do you manage changes?
When generating the code, I always generate it into a working folder that is then compared to my working source code. Since I have a post processing script that makes any changes I always need to make, the diff should only show changes. For classes, my compares are very clean with no noise.
For controllers, those will always be different, and after the initial generation, I usually just cut and paste a new or updated controller method into the live source file.
And, of course, I have a PowerShell script that does all the setup, editing, and launching of my compare tool in one easy command.
.\New-ServerApi.ps1 -OASFile .\openapi.yaml -namespace My.Demo.Model -OutputFolder \temp\swaggerapi
I haven’t included it here since it is specific to my environment, but the basic steps are:
- Validate parameters, java, create output folder if needed
- Run the swagger-gen jar as shown above
- If LASTEXITCODE -eq 0, for each class and controller, run cleanup scripts
- Launch compare tool, or write out file locations and directions
I hope this will convince you to try using OAS as a tool to specify your RESTful APIs. It has worked out for me on several projects, and others within the company have started using it, too. It won’t solve all your API woes, but it should help ameliorate them a bit.