Didacticiel de l'API REST - Explication du client REST, du service REST et des appels d'API avec des exemples de code

Vous êtes-vous déjà demandé comment la connexion / inscription sur un site Web fonctionne sur le back-end? Ou comment, lorsque vous recherchez des "minous mignons" sur YouTube, vous obtenez un tas de résultats et êtes capable de diffuser depuis une machine distante?

Dans ce guide convivial pour les débutants, je vais vous guider à travers le processus de configuration d'une API RESTful. Nous déclassifierons une partie du jargon et verrons comment nous pouvons coder un serveur dans NodeJS. Plongeons un peu plus dans JavaScript!

Éliminez ce jargon

Alors, qu'est-ce que REST? Selon Wikipedia:

Le transfert d'état de représentation ( REST ) est un style d'architecture logicielle qui définit un ensemble de contraintes à utiliser pour créer des services Web. Les services Web RESTful permettent aux systèmes demandeurs d'accéder et de manipuler les représentations textuelles des ressources Web en utilisant un ensemble uniforme et prédéfini d'opérations sans état

Démystifions ce que cela signifie (j'espère que vous avez le formulaire complet). REST est essentiellement un ensemble de règles de communication entre un client et un serveur. Il existe quelques contraintes sur la définition de REST:

  1. Architecture client-serveur : l'interface utilisateur du site Web / de l'application doit être séparée de la demande / du stockage de données, afin que chaque partie puisse être mise à l'échelle individuellement.
  2. Apatridie : la communication ne doit avoir aucun contexte client stocké sur le serveur. Cela signifie que chaque demande au serveur doit être faite avec toutes les données requises et qu'aucune hypothèse ne doit être faite si le serveur dispose de données provenant de demandes précédentes.
  3. Système en couches : le client ne doit pas être en mesure de dire s'il communique directement avec le serveur ou un intermédiaire. Ces serveurs intermédiaires (qu'il s'agisse de proxy ou d'équilibreurs de charge) permettent l'évolutivité et la sécurité du serveur sous-jacent.

Bon, maintenant que vous savez ce que sont les services RESTful, voici quelques-uns des termes utilisés dans l'en-tête:

  1. Client REST : code ou application pouvant accéder à ces services REST. Vous en utilisez un en ce moment! Oui, le navigateur peut agir comme un client REST incontrôlé (le site Web gère les demandes du navigateur). Le navigateur a utilisé pendant longtemps une fonction intégrée appelée XMLHttpRequest pour toutes les requêtes REST. Mais, cela a été réussi par FetchAPI, une approche moderne et prometteuse des demandes. D'autres exemples sont des bibliothèques de code comme axios, superagent et got ou des applications dédiées comme Postman (ou une version en ligne, postwoman!), Ou un outil de ligne de commande comme cURL !.
  2. Service REST : le serveur. Il existe de nombreuses bibliothèques populaires qui facilitent la création de ces serveurs, comme ExpressJS pour NodeJS et Django pour Python.
  3. API REST : cela définit le point de terminaison et les méthodes autorisés à accéder / soumettre des données au serveur. Nous en parlerons en détail ci-dessous. D'autres alternatives à cela sont: GraphQL, JSON-Pure et oData.

Alors dis-moi maintenant, à quoi ressemble REST?

En termes très généraux, vous demandez au serveur certaines données ou lui demandez d'enregistrer certaines données, et le serveur répond aux demandes.

En termes de programmation, il existe un point de terminaison (une URL) que le serveur attend pour recevoir une requête. Nous nous connectons à ce point de terminaison et envoyons des données sur nous (rappelez-vous, REST est sans état, aucune donnée sur la demande n'est stockée) et le serveur répond avec la bonne réponse.

Les mots sont ennuyeux, laissez-moi vous faire une démonstration. J'utiliserai Postman pour vous montrer la demande et la réponse:

Les données renvoyées sont en JSON (JavaScript Object Notation) et sont directement accessibles.

Ici, //official-joke-api.appspot.com/random_jokes'appelle un point de terminaison d'une API. Il y aura un serveur à l'écoute sur ce point de terminaison pour les demandes comme celle que nous avons faite.

Anatomie de REST:

Très bien, nous savons maintenant que les données peuvent être demandées par le client et que le serveur répondra de manière appropriée. Examinons plus en détail comment une demande est formée.

  1. Endpoint : Je vous ai déjà parlé de cela. Pour rappel, il s'agit de l'URL sur laquelle le serveur REST écoute.
  2. Méthode : Plus tôt, j'ai écrit que vous pouvez demander des données ou les modifier, mais comment le serveur saura-t-il quel type d'opération le client souhaite effectuer? REST implémente plusieurs `` méthodes '' pour différents types de requêtes, les suivantes sont les plus populaires:

    - GET : récupère la ressource du serveur.

    - POST : crée une ressource sur le serveur.

    - PATCH ou PUT : mettre à jour la ressource existante sur le serveur.

    - DELETE : supprime la ressource existante du serveur.

  3. En-têtes : les détails supplémentaires fournis pour la communication entre le client et le serveur (rappelez-vous que REST est sans état). Certains des en-têtes courants sont:

    Demande:

    - hôte : l'adresse IP du client (ou d'où provient la demande)

    - accept-language : langage compréhensible par le client

    - user-agent : données sur le client, le système d'exploitation et le fournisseur

    Réponse :

    - status : l'état de la requête ou du code HTTP.

    - content-type : type de ressource envoyée par le serveur.

    - set-cookie : définit les cookies par serveur

  4. Données : (également appelé corps ou message) contient les informations que vous souhaitez envoyer au serveur.

Assez de détails - montrez-moi le code.

Commençons par coder un service REST dans Node. Nous mettrons en œuvre toutes les choses que nous avons apprises ci-dessus. Nous utiliserons également ES6 + pour écrire notre service.

Assurez - vous que vous avez installé et Node.JS nodeet npmsont disponibles dans votre chemin. J'utiliserai Node 12.16.2 et NPM 6.14.4.

Créez un répertoire rest-service-nodeet cd dedans:

mkdir rest-service-node cd rest-service-node

Initialisez le projet de nœud:

npm init -y

Le -ydrapeau ignore toutes les questions. Si vous voulez remplir tout le questionnaire, lancez simplement npm init.

Let's install some packages. We will be using the ExpressJS framework for developing the REST Server. Run the following command to install it:

npm install --save express body-parser

What's body-parser there for? Express, by default, is incapable of handling data sent via POST request as JSON. body-parser allows Express to overcome this.

Create a file called server.js and add the following code:

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

The first two lines are importing Express and body-parser.

Third line initializes the Express server and sets it to a variable called app.

The line, app.use(bodyParser.json()); initializes the body-parser plugin.

Finally, we are setting our server to listen on port 5000 for requests.

Getting data from the REST Server:

To get data from a server, we need a GET request. Add the following code before app.listen:

const sayHi = (req, res) => { res.send("Hi!"); }; app.get("/", sayHi);

We have created a function sayHi which takes two parameters req and res (I will explain later) and sends a 'Hi!' as response.

app.get() takes two parameters, the route path and function to call when the path is requested by the client. So, the last line translates to: Hey server, listen for requests on the '/' (think homepage) and call the sayHi function if a request is made.

app.get also gives us a request object containing all the data sent by the client and a response object which contains all the methods with which we can respond to the client. Though these are accessible as function parameters, the general naming convention suggests we name them res for response and req for request.

Enough chatter. Let's fire up the server! Run the following server:

node server.js

If everything is successful, you should see a message on console saying: Server is running on port 5000.

Note: You can change the port to whatever number you want.

Open up your browser and navigate to //localhost:5000/ and you should see something like this:

There you go! Your first GET request was successful!

Sending data to REST Server:

As we have discussed earlier, let's setup how we can implement a POST request into our server. We will be sending in two numbers and the server will return the sum of the numbers. Add this new method below the app.get :

app.post("/add", (req, res) => { const { a, b } = req.body; res.send(`The sum is: ${a + b}`); });

Here, we will be sending the data in JSON format, like this:

{ "a":5, "b":10 }

Let's get over the code:

On line 1, we are invoking the .post() method of ExpressJS, which allows the server to listen for POST requests. This function takes in the same parameters as the .get() method. The route that we are passing is /add, so one can access the endpoint as //your-ip-address:port/add or in our case localhost:5000/add. We are inlining our function instead of writing a function elsewhere.

On line 2, we have used a bit of ES6 syntax, namely, object destructuring. Whatever data we send via the request gets stored and is available in the body of the req object. So essentially, we could've replaced line 2 with something like:

const num1 = req.body.a; const num2 = req.body.b;

On line 3, we are using the send() function of the res object to send the result of the sum. Again, we are using template literals from ES6. Now to test it (using Postman):

So we have sent the data 5 and 10 as a and b using them as the body. Postman attaches this data to the request and sends it. When the server receives the request, it can parse the data from req.body , as we did in the code above. The result is shown below.

Alright, the final code:

const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); const sayHi = (req, res) => { res.send("Hi!"); }; app.get("/", sayHi); app.post("/add", (req, res) => { const { a, b } = req.body; res.send(`The sum is: ${a + b}`); }); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

REST Client:

Okay, we have created a server, but how do we access it from our website or webapp? Here the REST client libraries will come in handy.

We will be building a webpage which will contain a form, where you can enter two numbers and we will display the result. Let's start.

First, let's change the server.js a bit:

const path = require("path"); const express = require("express"); const bodyParser = require("body-parser"); const app = express(); app.use(bodyParser.json()); app.get("/", (req, res) => { res.sendFile(path.join(__dirname, "index.html")); }); app.post("/add", (req, res) => { const { a, b } = req.body; res.send({ result: parseInt(a) + parseInt(b) }); }); app.listen(5000, () => { console.log(`Server is running on port 5000.`); }); 

We imported a new package path, which is provided by Node, to manipulate path cross-platform. Next we changed the GET request on '/' and use another function available in res, ie. sendFile, which allows us to send any type of file as response. So, whenever a person tries to navigate to '/', they will get our index.html page.

Finally, we changed our app.post function to return the sum as JSON and convert both a and b to integers.

Let's create an html page, I will call it index.html, with some basic styling:

     REST Client   * { margin: 0; padding: 0; box-sizing: border-box; } .container { height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; display: flex; flex-direction: column; justify-content: center; align-items: center; } form { display: flex; flex-direction: column; margin-bottom: 20px; } label, input[type="submit"] { margin-top: 20px; } 

Simple POST Form

Number 1: Number 2: Click Add!

Let's add a script tag just before the closing body tag, so we don't need to maintain a .js file. We will begin by listening for the submit event and call a function accordingly:

 document.addEventListener("submit", sendData); 

First we need to prevent page refresh when the 'Add' button is clicked. This can be done using the preventDefault() function. Then, we will get the value of the inputs at that instant:

function sendData(e) { e.preventDefault(); const a = document.querySelector("#num1").value; const b = document.querySelector("#num2").value; }

Now we will make the call to the server with both these values a and b. We will be using the Fetch API, built-in to every browser for this.

Fetch takes in two inputs, the URL endpoint and a JSON request object and returns a Promise. Explaining them here will be out-of-bounds here, so I'll leave that for you.

Continue inside the sendData() function:

fetch("/add", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ a: parseInt(a), b: parseInt(b) }) }) .then(res => res.json()) .then(data => { const { result } = data; document.querySelector( ".result" ).innerText = `The sum is: ${result}`; }) .catch(err => console.log(err));

First we are passing the relative URL of the endpoint as the first parameter to fetch. Next, we are passing an object which contains the method we want Fetch to use for the request, which is POST in this case.

We are also passing headers, which will provide information about the type of data we are sending (content-type) and the type of data we accept as response (accept).

Next we pass body. Remember we typed the data as JSON while using Postman? We're doing kind of a similar thing here. Since express deals with string as input and processes it according to content-type provided, we need to convert our JSON payload into string. We do that with JSON.stringify(). We're being a little extra cautious and parsing the input into integers, so it doesn't mess up our server (since we haven't implemented any data-type checking).

Finally, if the promise (returned by fetch) resolves, we will get that response and convert it into JSON. After that, we will get the result from the data key returned by the response. Then we are simply displaying the result on the screen.

At the end, if the promise is rejected, we will display the error message on the console.

Here's the final code for index.html:

     REST Client   * { margin: 0; padding: 0; box-sizing: border-box; } .container { height: 100vh; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; display: flex; flex-direction: column; justify-content: center; align-items: center; } form { display: flex; flex-direction: column; margin-bottom: 20px; } label, input[type="submit"] { margin-top: 20px; } 

Simple POST Form

Number 1: Number 2: Click Add! document.addEventListener("submit", sendData); function sendData(e) { e.preventDefault(); const a = document.querySelector("#num1").value; const b = document.querySelector("#num2").value; fetch("/add", { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify({ a: parseInt(a), b: parseInt(b) }) }) .then(res => res.json()) .then(data => { const { result } = data; document.querySelector( ".result" ).innerText = `The sum is: ${result}`; }) .catch(err => console.log(err)); }

I have spun up a little app on glitch for you to test.

Conclusion:

So in this post, we learnt about REST architecture and the anatomy of REST requests. We worked our way through by creating a simple REST Server that serves GET and POST requests and built a simple webpage that uses a REST Client to display the sum of two numbers.

You can extend this for the remaining types of requests and even implement a full featured back-end CRUD app.

I hope you have learned something from this. If you have any questions, feel free to reach out to me over twitter! Happy Coding!