Building good APIs
Thiago Leite e Carvalho
Senior Java Developer and Software Engineer. Tech Leader. University Professor. Writer. Instructor ??????
Knowing how is the architect of a REST API is important. I could talk about this in this article, but my friend Bruno Oliveira already has a good article about this. So I advise you to read first such article and return to here. The link is https://www.dhirubhai.net/pulse/do-all-restful-services-really-live-up-its-adjective-bruno-oliveira/.
But understanding how the REST API works isn't enough to build good APIs. Sometimes, simple mistakes take off the quality of an API. With this, use and maintainability get bad.
To avoid this situation, this article shows some good practices to help us build better APIs. All developers should use these simple practices, but unfortunately, they don't. Before we start, please listen to the next song, which shows in a relaxed way, the topics of this article: https://www.youtube.com/watch?v=nSKp2StlS6s.
Now, let's start... :)
Use HTTP methods the right way
There are a few methods in the HTTP protocol, but let's focus on the most used or which should be: GET, POST, PUT, DELETE and PATCH.
It's very common to see applications using only GET or POST requests to do all operations. Although it works, the concept of a REST API doesn't agree with this. Each operation has its own HTTP method. Thus, we should do like this:
Though this sounds like obvious, it's not. As I said before, using the methods in the wrong way makes the API non-fluent and difficult to understand. Many times to solve this, another bad practice is done and I'll talk about it in the next tip.
Create URIs the right way
When we don't use the HTTP methods in the right way, we're forced to use another way to say what such endpoint does. This way, the URIs become responsible to do this.
However, to do this we're obliged to use verbs on the URIs and this is a bad practice. When we do this, the concept of REST API is not applied: URI must show the manipulated resource, not the operation.
But if we're using the right HTTP methods, we're able to create good URIs. Thus, we should follow the tips below:
Write
GET: https://some.company.api.com/products
Instead of
GET: https://some.company.api.com/products/
To write in spinal case, use hyphen (-) to separate the words.
Write
GET: https://some.company.api.com/company-document
Instead of
GET: https://some.company.api.com/companyDocument
GET: https://some.company.api.com/company_document
Write
GET: https://some.company.api.com/reform-budget-room
Instead of
GET: https://Some.Company.API.Com/Reform-Budget-Room
The next URI creates a new car entity on the server. The values will be sent in the request body.
POST: https://some.company.api.com/car
The next URI gets a collection of existing cars
GET: https://some.company.api.com/cars
The next URI gets the student with id 45698.
GET: https://some.company.api.com/student/45698
The next URI gets students with the name “Thiago” who are 41 years old.
GET: https://some.company.api.com/students?name=thiago&age=41
The next URI gets the player with t-shirt 10 of the team Borussia Dortmund of the bundesliga of the championships collection
GET: https://api.soccer.org/championships/{liga}/teams/{team}/player/{id}
GET: https://api.soccer.org/championships/bundesliga/teams/borussia-dortmund/player/10
There are some others tips in the Mark's book. See it the Reference's section.
Use HTTP codes the right way
There are many HTTP codes and they are responsible for indicating the results of operations. To facilitate its use and understanding, there are groups for each type of result:
Unfortunately, it's common to see applications using usually 3 codes: 200, 404 and 500. It's a terrible way to report so many types of results. To solve this, we focused on the main groups: success, client and server error. Understanding the concept of each code helps us to provide better results and create consistent APIs. Thus, a strong contract between client and server makes both more reliable. The web server can return the underlined codes automatically, but we can use them if we need. The developers use the others more.
We should use this code when the request is successful according to the following situations:
- GET request fetched and resource transmitted in the message body;
- PUT, PATCH or POST update or create an entity. If we need, the entity can be transmitted in the message body;
- DELETE removes an entity and no message must be transmitted.
We should use it with a newly created entity. This is typically the response for POST requests and you don't need to return the new entity.
We should use this code with successful requests but not yet processed. It's useful when the data transmitted will be processed in a batch way in another moment.
We should use it with a succeeded request for GET, PUT, POST or DELETE operations, but we don't need or can't return a response with a body. The body must be empty.
We see it when the request isn't correct by the format, values or another's errors.
We should return this code when the request doesn't contain the required username and password to access the API.
We can see it when the request contains the required username and password, but access rights don't allow the request's execution. Maybe, some server configuration must be done to permit the access.
This is the most famous HTTP code and we use or use it when we want to inform that the desired resource doesn't exist.
This code means that the request sends the wrong method to an API. For example, the API supports the PUT method but receives a POST. It's possible to return a hint in the body with the correct method.
We see this code when the request contains a content response format that the server can't return. For example, the API supports JSON returns, but the request wanted an XML.
This code is seen when the server is busy and cannot respond to a request within the time that the server was prepared to wait.
We should use it to inform that the request(POST, PUT, PATCH or DELETE) can't execute, because will create an inconsistent state in the resource/entity.
This is the opposite of the 406 code. The client now sends a request content format that the server doesn't recognize. Thus, the request cannot be processed. For example, the API accepts JSON requests, but the request sends an XML.
We should use this code when the incoming request is not completed. The content and format are correct, but some business logic doesn't allow it to finish successfully.
This code means that some unexpected error occurred on the server. The problem is not with the request or response, but with the server. These are usually runtime errors like nullpointer, database shutdown, and so on.
The server cannot respond to the request now. Maybe it is busy or is only temporarily not processing the request, because of time or maintenance.
There are some others codes. If you need a specific code for your needs, look for them in the References section, second and third links.
Version your API
It's a good idea to version APIs. Thus, we avoid breaking clients. Remember many times the same API can be used for many clients. So, updates may introduce unexpected errors for some clients. If a new or an old client needs new data(values, format, etc), it's best a new version for him.?
The most used way to version an API is "Path Version". In this API version type, the URI shows the API version. For example:
https://my.api.com/do-something
https://my.api.com/v1/do-something
https://my.api.com/v2/do-something
In the previous URLs, the first URL is the original version. The second is the first version for a specific client. The third URL it's the second version to serve another client.
There are other ways to version an API like "Query String", "Subdomain" or "Headers". But as I said, "Path Version" is the most used. If you prefer one of the other ways, google it. There are lots of examples of them.
Document your API
Documenting software is very important and an API is no different. When we do this, a complete API view becomes public and we create a communication contract. Thus, we improved the use of this API.
This documentation, helps clients understand how to send requests, which type of return are available, how to handle returns and other important informations. Knowing this, helps us to build better clients for APIs and in the end better softwares.
There are some frameworks to helps us to document APIs. The most famous is Swagger, but another like API Blueprint and RAML can also be used. Choice one, google it and you'll build a good APIs.
Final words
This article showed some best practices that help us build better APIs. We noticed that they are all simple to do, but unfortunately sometimes they are not done. It's good practice to always care about them when we're building an API. That way, our APIs will be better. Think about it! Bye. ;)
References
MASSé, Mark.?REST API Design Rulebook: Designing Consistent RESTful Web Service Interfaces. O'Reilly Media, Inc.", 2011.
https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
https://swagger.io/docs/
https://semver.org/
https://apiblueprint.org/
https://raml.org/
Software Engineer
2 年Very nice! A pragmatic and clear view of the main good practices for building better APIs :)
Analista de testes | QA Automation Mobile | Testes de Software | Testes Web | Testes Mobile | Testes de API |
2 年Guilherme Nunes Behs