If you don't know what a REST API is, I recommend read about it here.
As a short summary, building an API in a RESTful way means that you have to build its URL endpoints grouped by "resources". A resource is something you want to manage, for example: a student, a user, a car, etc. A resource is somewhat similar to a database table, but we call them "resources" because of a few exceptions.
Here is an example of RESTful API endpoints to manage Students:
Method | URL | Description |
---|---|---|
GET | /student | It should return all students |
GET | /student/1 | It should return a single student with id=1 |
GET | /cohort/1/student | It should return all students in the class with id=1 |
POST | /student | It should create a new student |
PUT | /student/1 | It should update the student information with the id=1 |
DELETE | /student/1 | It should remove the student with id=1 |
Take a look at the URLs, they follow a pattern. After a while, the endpoints will speak for themselves, they will make sense and you will be able to guess what they do or even guess some endpoints. That's the idea.
☝️ You can read more about REST APIs in this 4Geeks.com lesson.
Here is an 8 minute video explaining REST: https://www.youtube.com/watch?v=7YcW25PHnAA
Expressjs is a library that allows us to build a web API server in a fast, minimalist and flexible way using nodejs. The first step to use it is performing the installation in your project, for this in your terminal you must execute:
$ npm install express --save
Once the installation is finished we can create a server.js file and we will add the following lines, the compute will start listening to HTTP requests:
1const express = require('express'); 2const app = express(); 3 4app.get('/', (req, res)=>{ 5 res.send("Hello World!") 6}) 7 8 9app.listen(4000, function(){ 10 console.log('API running on port 4000'); 11})
1const express = require('express'); // here we are importing the Expressjs library in our file. 2const app = express(); #here we create a new Expressjs server instance. 3 4app.get('/', (req, res)=>{ // here we define the first API path: GET / 5 res.send("Hello World!") // expressjs will return "Hello World, this could be an HTML string or a JSON string. 6}) 7 8 9app.listen(4000, function(){ // to finish we start the server on localhost. 10 console.log('API en ejecución en el puerto 4000'); 11})
In Expressjs we can add new endpoints using the variable app
which is the instance we defined in expressjs and adding the http method where our endpoint will be available app.get('/', (req, res)=>{}
, as you can see we will have a callback function that will receive 2 parameters req, res
, the detail of these parameters is as follows:
req : It is an object that represents the HTTP request and gives us information about the request such as the body, query params, HTTP headers.
res : It is an object that represents the HTTP response that the Express application sends when it receives an HTTP request.
In the following link you can access the documentation of Expressjs.
If you want to add another endpoint to your API that is executed when a client does the GET/person
, you will need to add another block of code like this:
1app.get('/', (req, res)=>{ // here we define the first API path: GET / 2 res.send("Hello World!") // expressjs will return "Hello World, this could be an HTML string or a JSON string. 3})
If you want your endpoint to respond to POST, PUT or DELETE, you can specify it as follows:
1const express = require('express'); 2const app = express(); 3 4app.get('/', (req, res)=>{ // here we define the first API path: GET / 5 res.send("Se recibió un GET") 6}) 7 8app.post('/', (req, res)=>{ // here we define the first API path: POST / 9 res.send("Se recibió un POST") 10}) 11 12app.listen(4000, function(){ // to finish we start the server on localhost. 13 console.log('API en ejecución en el puerto 4000'); 14})
The response can be basically anything you want as long as it's a string: HTML, JSON, CSS, images, etc. Just make sure to string whatever you want to reply to.
In the following example, we are using the JSON.stringify method to convert an object named person1
to a JSON string before returning it to the client.
1const express = require('express'); 2app.get('/person', (req, res)=>{ 3 const person1 = { 4 "name": "Bob" 5 } 6 res.status(200).json(person1); 7})
The response code is 200 by default, and 500 if there is an unknown error. If you want to reply to the client with a different code, you'll need to specify it like this:
1const express = require('express'); 2app.get('/person', (req, res)=>{ 3 const contenido = { 4 "detalles": "Hubo un error en la solicitud" 5 } 6 res.status(400).json(contenido); //here we change the status code to 400 (very common code in case of request errors) 7})
But what if the request comes with errors? For example: if we have an endpoint to create a person and we need to specify the first_name AND the last_name, but only the first_name was found in the request, this is how we would validate it:
1const express = require('express'); 2 3app.use(express.json()) // Allows to parse the content in an application/json type 4app.use(express.urlencoded({ extended: true })) // Allows parsing the content into an application/x-www-form-urlencoded type 5 6 7app.post('/person', (req, res) => { 8 const { body } = req; 9 10 if (!body) { 11 return res.status(400).json({ message: "The request body is null" }); 12 } 13 14 if (!body.hasOwnProperty('first_name')) { 15 return res.status(400).json({ message: "The request first_name is null" }); 16 } 17 18 if (!body.hasOwnProperty('last_name')) { 19 return res.status(400).json({ message: "The request last_name is null" }); 20 } 21 22 return res.status(400).json(body); 23})
The express-validator
library gives us a more comfortable way to handle validations, you can get more information on how to use it by visiting its documentation https://express-validator
A middleware is a function that has access to the request object, the response object, and the next middleware function to be executed in the request/response cycle. Once our middleware finishes its execution it is important to execute the next()
function or the request will hang.
Below is an example of a middleware that will print the date and time in which the API queries occur on the console
1const express = require('express'); 2 3app.use(function (req, res, next) { 4 console.log('Time:', Date.now()); 5 next(); // aquí invoca al siguiente midleware 6}); 7
We have prepared this live coding example that you can run yourself on Gitpod and use as the basis for your project..
Expressjs Rest Hello: https://github.com/4GeeksAcademy/expressjs-rest-hello