Search This Blog

Sunday, April 18, 2021

Using Swagger to do Document Driven Development

Swagger is one among many tools that allow you to define API RESTful endpoints. It then generates API Documents and Application Skeletons for you. Afterward, you can write code to implement the APIs' functionality. Another similar tool is RAML.

I personally think that if you are using Ruby, you can just write a good README file about APIs, and done with it. It will be much faster and  cleaner, if you know what you are doing. However, if you run a project that build multiple services by different teams with different skill levels, things such as Swagger and RAML will help you to maintain a certain level of unification of different codebases. And those tools also help to keep the APIs in synch with API docs (Lazy developers will like this feature).

This article describes step-by-step  of using Swagger to define API functions, generate a Sinatra skeleton web-based app and write code to implement the app. The Sinatra skeleton generated by Swagger does not work out of the box, and the quality of Ruby code is terrible, so I have to do some modifications myself to make it work and be bearable.

The steps are:

  • Write YML file that contains API definitions.
  • Generate and download the Sinatra skeleton.
  • Modify the code to make it work.
  • Implement the APIs' functionality.
  • View API documentation and test the functionality from Web browser.

I. Prerequisites

There are Swagger tools that you can download and use offline on your computer. To me, they are not attractive, so you can see about downloading and installing them here.

But to use online tools, you just need a web browser. I test the tools with Chrome and Opera on Mac OS X, and they work.

 

II. Write YML file that contains API definitions

Use your web browser to go to the Swagger YML Editor:  http://editor.swagger.io/#/

On the browser, you will see this screen if you come to Swagger Editor the first time:

 

Click on the button "Got it!", you will come to a screen to edit the YML file that describe your APIs. In the editor on the left side, you will see the YML definition of the example app Uber API like this:
 

 

You can delete everything in the YML editor on the left, and write your own API definitions there. I already wrote the YML definitions for two APIs of Email Services in this YML file.

POST /verifications.json

When a user registers a new account on a site, developer can use this API to send verification email to user's email address. User must click on the comeback_url to come back to the site to prove that his email is valid.

 

POST /invitations.json

When a user or an organization invites a user to participate a site, developer can use this API to send the invitee an invitation email. The invitee can click on the invitation email to come to the site.

 

Both API endpoints accept JSON parameter with this format:


"organization_name": "Some Organization Name",
"recipient": "somebody@some-email.com",
"comeback_url": "Some full URL, including protocol http/https"
}

 

For example:


"organization_name": "Amazon",
"recipient": "somebody@rubygems.org",
"comeback_url": "http://rubygems.org"
}

You can read details about YML and JSON specs for API definitions here: http://swagger.io/specification/ .

It is always easier, faster and cleaner to use YML to define APIs.

 

III. Generate and download the Sinatra skeleton

For now, you can copy this YML file written by me, and paste it into the YML editor on the left side of the screen on browser, you should see the screen like this:

 

 

After you copy/paste the YML file in the YML editor and verify on the right side to see the APIs verifications and invitations get defined correctly, you can download the Sinatra Server skeleton by clicking on the menu Generate Server, and select Sinatra.

A zip file called sinatra-server-generated.zip will be downloaded to your local machine. Extract the file, you will have a directory called sinatra-server. That is your Sinatra Server skeleton generated by Swagger. Feel free to change the directory name to any name you want. 

 

 IV. Modify the code to make it work

The generated Sinatra skeleton has some troubles, so it does not show APIs or anything out-of-the-box as it supposes to do. Besides, the Ruby code quality generated by Swagger is terrible. So we need to do some modifications to make it work. 

1) my_app.rb

Add require to include the files in ./api/, so the application will know about the API endpoints' definitions.

2) lib/swaggering.rb

- Method self.add_route:

The line "accepted = case method" never works, because the method names in APIs are generated as UPPERCASE, while the accepted tests for the method names uses lowercase.

And the way the code is written to check for valid method names are super dumb. Please look at the modified file for a much better and cleaner implementation.

 

- Method self.to_api:

This method hardcodes base_path in api_listing to the one in @@configuation. It makes the API docs stop working if the application is deployed to any place other than "http://localhost:4567".

Please look at the modified file for a much better and cleaner implementation.

 3) Two files invitations_api.rb and verifications_api.rb

The two API endpoints are defined in these two files.

The API definitions, routes, resourcePaths and endpoints must be modified to reflect (to some degree) the correct APIs defined in the YML Editor (See the right side).
Please look at the modified files invitations_api.rb and  verifications_api.rb, at the parameters of MyApp.add_route.

 

After the 3 steps above, you should be able to fire up the server using the command rackup -p 4567 config.ru.

Then  you can use any REST client, for example Postman to test the APIs at:

POST http://localhost:4567/invitations.json

POST http://localhost:4567/varifications.json    

In both cases, you should receive back a JSON:

{"message": "yes, it worked"}

Now we can start to implement the functionality for the email APIs.

 

V. Implement the APIs' functionality

I implement the Mail functionality using the gem ActionMailer.

Everything follows the Rails conventions: the mailers are in ./app/mailers/. The mails' contents are in ./app/views/.

Take a look at the repository for implementation details.

You must configure the email sending configuration in the file ./config/initalizers/setup_email.rb to be able to send mail.

If you run the application on any OS that has postfix, you can configure the file ./config/initializers/setup_email.rb like this:

ActionMailer::Base.raise_delivery_errors = true
ActionMailer::Base.delivery_method = :sendmail
ActionMailer::Base.view_paths = File.join('./app', 'views')

 

VI. View API documentation and test the functionality from Web browser

I add the directory public with modified Swagger UI to the application, and add two new routes in the file my_app.rb to support the API docs functionality. It allows users to view API docs, regardless where the application is deployed. 

Once you finish all the modifications and APIs' implementations, run the server with the command 
rackup -p 4567 config.ru, then you can see the API docs by open this URL in browser:

http://localhost:4567/api_docs

Replace localhost:4567 with the real URL where you deploy the application. You should see something like this:

 

You can click on "Show/Hide" and "List Operations" to view details of each API endpoint.

 

 

You can try out the APIs by clicking on "Expand Operations". Once you click on "Expand Operations", you will see a screen similar to this:

 

You should be able to paste parameter similar to the following JSON in to the text box Value, and hit "Try it out!" to see the API endpoint run.

{ 
"organization_name": "My Awesome Organization",
"recipient": "somebody@some-email.com",
"comeback_url": "http://www.google.com"
}

 

For your convenient, I put the fully implemented application here: https://github.com/linhchauatl/sinatra-email-services-server

Please read the README file about how to bring it up and running.
Happy swaggering!


No comments:

Post a Comment

CON NGƯỜI và TINH THẦN

CON NGƯỜI và TINH THẦN 1 –  " Nếu có một gã trọc phú hàng to súng lớn, có thể mua biệt thự alibaba cho em ở, xe lếch xù cho em đi, nạp ...