When designing large web applications, it is very important to use principles that will be clear to all participants. To standardize the interaction, the REST API was developed, which has been the de facto standard in the industry for many years. REST stands for Representative State Transfer. It was invented by Roy Fielding. Remarkably, he is also one of the creators of the HTTP protocol.
REST principles are difficult to follow 100% of the time. Often, the actions that endpoints are responsible for in the application go beyond a simple CRUD. However, if you avoid the mistakes listed below, your API will become cleaner. It will be easier for other developers to use it. Moreover, it will allow you to avoid bugs that are difficult to catch.
Do not forget that REST is not a silver bullet. Surely you have encountered SOAP, grpc, webSocket, webHooks. For each task, you need to choose your own architectural style and method of interaction.
Large web applications usually have several clients. It can be a browser, Android, or iOS application. API development often lies on the backend engineer and he provides it further for use by the frontend developers. But this is not quite the right approach. Each platform has its own features, and it is very important to hear the opinion of each team member so that the API is convenient to use. The maximum logic should be put on the backend so that the frontend is responsible only for UI rendering.
In order for your API to meet the REST architecture, it is necessary to use HTTP methods correctly. This will also allow you to improve the performance and security of your web application. In REST architecture, query design is built around resources, and methods are needed to determine the type of operation that needs to be performed on it. For example, you should use GET to get an object, and POST to create a new one. If you use HTTP methods to operate on resources incorrectly, this may lead to unpredictable behavior of your API and it will become difficult to maintain it.
The main HTTP methods are used as follows:
Each method has its own features and can be used in different situations depending on the requirements of your project. Developers often confuse the use cases of PATCH and PUT methods. Use PATCH for partial modification of the object, and PUT for complete replacement. These methods should be idempotent and used to update the resource, not to act on it.
Actions on a resource in the REST API are transmitted via HTTP methods (GET, POST, PUT, DELETE, etc.) and request parameters.
For example, if you want to perform the “create message” action for the “user” resource, then you can use the POST method and pass the request parameters containing the message text and the user ID.
Here is an example of a URL performing this action:
POST /users/{user_id}/messages
Here {user_id} is the user ID.
You can also use the request parameters to transmit additional information about the action on the resource.
Some developers use only GET and POST methods. Either out of ignorance or because of defective versions of libraries that do not support the other methods. If you care that the client using your API does not support other requests, you can develop 2 versions, normal and simplified.
Do not forget about API versioning at the design stage. It is important in order to maintain compatibility between the client and server parts of the application. Versioning allows you to add new features and change your API without fear of breaking the work of clients who use the old version of the API. Versioning is especially critical when you cannot control the client side of the application.
For example, mobile applications. The user can install an application on his phone and then not update it for a long time. Over time, the functionality can change a lot and it is simply impossible to develop the application within the old API. For example, you can add a new parameter to the request, but the clients will not know about it and the functionality of the application will be disrupted.
If your team develops a web browser version at the same time as the server part, you are less exposed to this risk. But for the convenience of development, it's still not worth ignoring this. Versioning allows a developer to manage the lifecycle of a web application by supporting multiple APIs for clients at the same time.
There may be a situation when user 1 requested an object, while user 2 changed the object. If after that user 1 changes the object again, then user 2's changes will disappear. It is especially dangerous when the PUT method is used, updating the entire object. To prevent this from happening, you can enter the “version” parameter for each entity.
Then the algorithm will be as follows:
user 1 requests an object, an entity comes to him with {“version”: 1}
user 2 overwrites the object, and the entity is saved to the server as {“version”: 2}
if user 1 tries to save the old version of the object, he will get the error “409 Conflict”
he needs to re-request the current object from the server with {“version”: 2}
after that, he can save his version without the risk of losing data
the final object with {“version”: 3} will be saved to the server
The use of timezones in the REST API is necessary for the correct display of date and time on the client side. This will allow you to avoid problems with daylight saving time and the use of your application by clients in time zones. When storing the date and time, you also need to use an additional field to specify the time zone There are several options for using timezones. Each approach has its advantages and disadvantages, so its choice depends on the specific requirements of the project.
use Unix timestamp
use the server's local timezone
use UTC
In practice, the method has proven itself using a composite object with two fields
"CurrentTime":{
"DateTime":"2023-05-12T10:00:00",
"Timezone":"America/New_York"
}
The advantage of this approach is that by having a timezone, you can convert the time to any format. It also gives an advantage when working with the server part of the application.
HTTP response codes tell the client what happened to the request. Focusing on them, you can understand what went wrong if there were problems. You can't ignore them when developing an API.
For example, the response code 200 means successful execution of the request. But it is not necessary to use only it in any positive scenario. There are other successful answers. For example, 204 is a successful response without a body (for example, when deleting an object). If we use 200 and do not return the object, in some cases this may lead to unexpected results, because the client will wait for the response body.
In case of a client error, do not always limit yourself to code 400. There are many codes 401 - not authorized, 403 - access is denied, 404 means that the requested resource is not found, 409 - conflict when saving an outdated version to the server. They are all useful and should be used depending on the scenario.
If you don't use response codes, then you turn your API into a black box. You will not be able to get information about what is happening with requests and will greatly complicate your life by catching errors. Your client may start behaving unpredictably, and the logic of the application may be broken.
Therefore, you should always pay attention to the HTTP response codes and process them by the client according to their logic. The server should always be transparent and report what happened to the request. Using standard codes will allow you to ensure API compatibility with other clients and servers. Handle error errors appropriately using 4xx and 5xx codes. And most importantly, do not forget about the documentation, since the code needs to be maintained. Describe the behavior of the system and explain what the HTTP response codes of your REST API mean.
Pagination is needed to reduce the load on the server and improve the performance of the application. When loading a large amount of data to a client request, waiting for a response may be too long. This may not be acceptable for end users who expect to receive information immediately. With pagination, you can split a large amount of information into small parts and upload only the information that the client needs at a given time.
For example, if you are developing an application for a social network and want to display a list of all users, then you can use pagination to display only a certain number of users on a page and load the next user page as needed.
Use 2 parameters:
Pagination also reduces the load on the server and speeds up the processing of client requests.
https://mysite.ru/api/v1/messages?offset=0&limit=25
It's hard to imagine developing a large application with a lot of teams without documentation. However, on small projects, there may not be a resource to document the code. Do not neglect this activity. Information about which requests can be sent to the server, what parameters need to be passed in the request, and the nature of data that will be returned in response is important for using your API. The documentation should contain information about what errors can occur when working with the API and how they can be handled. This will help speed up the process of application development and integration, as well as improve the user experience.
HTTP headers are an important part of the REST API. They contain meta-information that is required for the correct operation of both the client and server parts. For example, data about the client's session and cache, encoding, content type, and response length. It is recommended to expand the headers, but not replace the existing data in them. This is very important in a micro-service architecture when a single request can go through many related APIs within a cluster. The use of headers will allow different components of the system to function correctly. HTTP headers are used to control caching of responses to requests.
For example, in radish, you can create a composite key from header fields. Client authentication data can be received from headers. One of the most common types is the jwt token. Headers can also be used to specify the format of the response to the request. It can be JSON, XML, text, multimedia, etc.
The examples given show that it is necessary to adhere to the uniformity and standards adopted in the industry. If you avoid mistakes and apply best practices, your API will become more transparent and understandable for end users. You will be able to get rid of bugs and make functional, fast, and secure web applications.
The featured image for this piece was generated using HackerNoon’s Kadinsky 2 model
Prompt: Frame work