One of the popular methods for creating websites, web applications and even web multiplayer games today are REST APIs. This technique allows for decoupling of a client application from the server.
Because of that split, a single server API can serve multiple clients. For example, a website, a mobile application, or even a desktop game. All of these are clients that can consume the same REST API built on the server.
API is an acronym for application programming interface. You don't need to remember that, but the important word here is "interface". An interface is a contract defining how two pieces of software are communicating with each other. In this case, a client is trying to communicate with a server-side application. When a client wants some information from the server it sends a request to the REST API and expects a response in return.
When you enter a URL in your web browser, it makes a request to the server. Very often before that request hits your application it goes through a web server, for example, Apache or Nginx. These can be quite complex, so for the purpose of this article, we only need to know that the server takes a URL of our request and points it to a specified file. That file is an entry point of our REST API.
The difference between REST API and a regular website is that REST API will usually not return HTML ready to be rendered by the browser. Rest API will return data in a raw format, XML or more popular now JSON. This leaves the job of data presentation to the client requesting it. The same data from the server can now be processed by multiple consuming clients, often written in different languages and using different technologies for rendering. If the client would want to render something in OpenGL, it would be troublesome to parse the HTML and extract the information it needs.
When we build REST APIs, there are a few simple practices that you could follow:
1. When you just want to read data from your REST API, you should send a GET
2. When you are trying to persist new data on the server, send a POST
3. When you update existing data, send a PUT
HTTP request. You can also use a PATCH
HTTP request if you like, but for me, the difference feels a bit too artificial, like an unnecessary complication. If you want to know more about this, you can read a very extensive explanation about this difference
. I prefer to keep it simple and choose to only use PUT for updating any resource (or multiple) and skip PATCH completely.
4. When you want to delete existing data, send the DELETE
In REST API you can have URL your_domain/user/1
do different things depending on what kind of HTTP method you choose from the ones described above. So we chose an URL and we are sending it to the server that points it to some file. What's next?
Routing receives request information and points to a specific function, where data is going to be further processed. In your routes, you will point every available URL and Request method to specific methods of your server-side application. If the provided URL request is not registered in routing, we return HTTP 404 “Not found”
response to the client, so it can act accordingly.
There are many approaches to validation, but you should know two things. First, it absolutely has to be implemented, as it prevents someone from breaking your REST API. Secondly, it should most definitely happen before doing any database queries.
Historically validation was done in multiple places. If MVC (Model-view-controller) design pattern was implemented, validation often could be found in models or controllers. The best place I know to validate data sent is between routing and method that the route is pointing to.
If you expect data field “email” to be a valid email address, you would want to check if the format of the string is correct. If you expect integer in the data field, you should make sure an integer, not a string is provided. When request data sent to the REST API is invalid, we return error messages for fields that have to be changed with HTTP 422 "Unprocessable Entity"
. This is also a perfect place to verify if an authorized user has access to the requested resource. If the user is not authorized, we would return an HTTP 403 “Access denied”
Other than persisting the data in a database, we might want to do some other stuff here. A good example could be scheduling an email to be sent to the user, or extracting data from a CSV file
. This part will usually be different depending on which programming language or framework is being used and which architectural design pattern is chosen. The goal at this time is to make the necessary changes to the data, persist it and prepare a response.
If everything went right, we would return an HTTP 200 "OK"
response with some data or a message. In case something went wrong in our REST API, we should return HTTP 500 “Internal Server Error”
with some error message informing the user what was the issue. Keep in mind, that if something goes wrong, you should never return the real errors thrown by your database or other tools that you use from your REST API, as it can expose sensitive information!
These were the basics of data flow through a REST API. As usual, the implementation and names of methods for achieving this will differ across multiple languages and frameworks, but my hope is that after reading this, you will have fundamental knowledge about what general steps should be taken before and after your REST API will process the request. You can also check out my full feature implementation for REST API in Laravel
if you need to see a code example.
Hope it helps, and if you have questions or want to discuss this topic in more detail, don’t hesitate to leave a comment!