V-ați întrebat vreodată cum funcționează conectarea / înscrierea pe un site web în back-end? Sau cum, atunci când căutați „pisicuțe drăguțe” pe YouTube, obțineți o grămadă de rezultate și puteți să transmiteți de la o mașină la distanță?

În acest ghid prietenos pentru începători, vă voi prezenta procesul de configurare a unui API RESTful. Vom declasifica o parte din jargon și vom arunca o privire la modul în care putem codifica un server în NodeJS. Să ne scufundăm puțin mai adânc în JavaScript!

Scoateți jargonul

Deci, ce este REST? Conform Wikipedia:

Transferul reprezentativ al statului (ODIHNĂ) este un stil arhitectural software care definește un set de constrângeri care trebuie utilizate pentru crearea serviciilor web. Serviciile Web RESTful permit sistemelor solicitante să acceseze și să manipuleze reprezentări textuale ale resurselor Web utilizând un set uniform și predefinit de operații fără stat.

Să demitificăm ce înseamnă asta (sperăm că ați primit forma completă). REST este practic un set de reguli pentru comunicarea între un client și un server. Există câteva constrângeri cu privire la definiția REST:

  1. Arhitectura client-server: interfața cu utilizatorul site-ului / aplicației trebuie separată de cererea / stocarea datelor, astfel încât fiecare parte să poată fi scalată individual.
  2. Apatridia: comunicarea nu ar trebui să aibă niciun context de client stocat pe server. Aceasta înseamnă că fiecare cerere către server ar trebui să fie făcută cu toate datele necesare și nu ar trebui făcute ipoteze dacă serverul are date din cererile anterioare.
  3. Sistem stratificat: clientul nu ar trebui să poată spune dacă comunică direct cu serverul sau un intermediar. Aceste servere intermediare (fie că sunt proxy sau echilibratoare de încărcare) permit scalabilitatea și securitatea serverului de bază.

Bine, deci acum că știți ce sunt serviciile RESTful, iată câțiva dintre termenii folosiți în titlu:

  1. Client REST: cod sau o aplicație care poate accesa aceste servicii REST. Îl folosești pe unul chiar acum! Da, browserul poate acționa ca un client REST necontrolat (site-ul web gestionează solicitările browserului). Browserul, pentru o lungă perioadă de timp, a folosit o funcție încorporată numită XMLHttpRequest pentru toate cererile REST. Dar, acest lucru a fost urmat de FetchAPI, un modern, promisiune abordare bazată pe cereri. Alte exemple sunt bibliotecile de coduri, cum ar fi axios, superagent și a primit sau unele aplicații dedicate precum Poştaş (sau o versiune online, poștașă!), sau un instrument de linie de comandă cum ar fi răsuci!
  2. Serviciul REST: server-ul. Există multe biblioteci populare care fac crearea acestor servere o briză, cum ar fi ExpressJS pentru NodeJS și Django pentru Python.
  3. API REST: acesta definește punctul final și metodele permise pentru accesarea / trimiterea datelor către server. Vom vorbi despre acest lucru în detaliu mai jos. Alte alternative la aceasta sunt: ​​GraphQL, JSON-Pure și oData.

Deci, spune-mi acum, cum arată REST?

În termeni foarte largi, solicitați serverului anumite date sau îi cereți să salveze unele date, iar serverul răspunde solicitărilor.

În termeni de programare, există un punct final (un URL) pe care serverul îl așteaptă pentru a primi o solicitare. Ne conectăm la acel punct final și trimitem câteva date despre noi (amintiți-vă, REST este apatrid, nu sunt stocate date despre cerere) și serverul răspunde cu răspunsul corect.

Cuvintele sunt plictisitoare, permiteți-mi să vă fac o demonstrație. Voi folosi Postman pentru a vă arăta cererea și răspunsul:

Tutorial REST API REST Client serviciul REST si apelurile
poștaș: cerere de configurare

Datele returnate sunt în JSON (JavaScript Object Notation) și pot fi accesate direct.

Aici, https://official-joke-api.appspot.com/random_joke se numește un punct final al unui API. Va exista un server care ascultă pe acel punct final pentru solicitări precum cea pe care am făcut-o.

Anatomia REST:

Bine, așa că acum știm că datele pot fi solicitate de client și serverul va răspunde în mod adecvat. Să analizăm mai profund modul în care se formează o cerere.

  1. Punct final: Ți-am spus deja despre asta. Pentru o reîmprospătare, este adresa URL unde ascultă serverul REST.
  2. Metodă: Mai devreme, am scris că puteți solicita date sau le puteți modifica, dar cum va ști serverul ce fel de operație dorește să efectueze clientul? REST implementează mai multe „metode” pentru diferite tipuri de solicitări, următoarele sunt cele mai populare:
    OBȚINE: Obțineți resurse de la server.
    POST: Creați resursă pe server.
    PLASTURE sau A PUNE: Actualizați resursa existentă pe server.
    ȘTERGE: Ștergeți resursa existentă de pe server.
  3. Anteturi: Detalii suplimentare furnizate pentru comunicarea între client și server (amintiți-vă, REST este apatrid). Unele dintre anteturile comune sunt:
    Cerere:
    gazdă: adresa IP a clientului (sau de unde a venit cererea)
    accept-limbaj: limbaj de înțeles de către client
    agent utilizator: date despre client, sistem de operare și furnizor
    Raspuns:
    stare: starea cererii sau codului HTTP.
    tipul de conținut: tip de resursă trimisă de server.
    set-cookie: setează cookie-uri pe server
  4. Date: (numit și corp sau mesaj) conține informații pe care doriți să le trimiteți serverului.

Destul cu detaliile – arată-mi codul.

Să începem să codificăm un serviciu REST în nod. Vom implementa toate lucrurile pe care le-am învățat mai sus. De asemenea, vom folosi ES6 + pentru a ne scrie serviciul.

Asigurați-vă că aveți instalat Node.JS și node și npm sunt disponibile în calea ta. Voi folosi nodul 12.16.2 și NPM 6.14.4.

Creați un director rest-service-node și cd în el:

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

Inițializați proiectul nodului:

npm init -y

-y steagul omite toate întrebările. Dacă doriți să completați întregul chestionar, rulați npm init.

Să instalăm câteva pachete. Vom folosi cadrul ExpressJS pentru dezvoltarea serverului REST. Rulați următoarea comandă pentru ao instala:

npm install --save express body-parser

Ceea ce este body-parser acolo pentru? Express, în mod implicit, este incapabil să gestioneze datele trimise prin cerere POST ca JSON. body-parser permite Express să depășească acest lucru.

Creați un fișier numit server.js și adăugați următorul cod:

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.`);
});

Primele două linii importă Express și body-parser.

A treia linie inițializează serverul Express și îl setează la o variabilă numită app.

Linia, app.use(bodyParser.json()); inițializează pluginul body-parser.

În cele din urmă, ne setăm serverul să asculte pe port 5000 pentru cereri.

Obținerea datelor de pe serverul REST:

Pentru a obține date de la un server, avem nevoie de un GET cerere. Adăugați următorul cod înainte app.listen:

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

app.get("/", sayHi);

Am creat o funcție sayHi care ia doi parametri req și res (Voi explica mai târziu) și trimite un „Bună!” ca răspuns.

app.get() ia doi parametri, calea rutei și funcția de apelat atunci când calea este solicitată de client. Deci, ultima linie se traduce prin: Bună, server, ascultați cererile din „/” (gândiți la pagina principală) și apelați la sayHi funcție dacă se face o cerere.

app.get ne oferă, de asemenea, un request obiect care conține toate datele trimise de client și un response obiect care conține toate metodele cu care putem răspunde clientului. Deși acestea sunt accesibile ca parametri de funcție, convenția generală de denumire sugerează să le numim res pentru response și req pentru request.

Destul de vorbărie. Să aprindem serverul! Rulați următorul server:

node server.js

Dacă totul are succes, ar trebui să vedeți un mesaj pe consolă care să spună: Serverul rulează pe portul 5000.

Notă: Puteți schimba portul cu orice număr doriți.

1611700510 362 Tutorial REST API REST Client serviciul REST si apelurile

Deschideți browserul și navigați la http://localhost:5000/ și ar trebui să vedeți așa ceva:

1611700510 186 Tutorial REST API REST Client serviciul REST si apelurile

Gata! Primul tau GET cererea a avut succes!

Trimiterea datelor către serverul REST:

Așa cum am discutat mai devreme, să configurăm cum putem implementa un POST solicită în serverul nostru. Vom trimite două numere, iar serverul va returna suma numerelor. Adăugați această nouă metodă sub app.get :

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

Aici, vom trimite datele în format JSON, astfel:

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

Să trecem peste cod:

Pe linia 1, invocăm.post() metoda ExpressJS, care permite serverului să asculte POST solicitări. Această funcție ia aceiași parametri ca .get() metodă. Traseul pe care îl parcurgem este /add, astfel încât să puteți accesa punctul final ca http://your-ip-address:port/add sau în cazul nostru localhost:5000/add. Ne înclinăm funcția în loc să scriem o funcție în altă parte.

Pe linia 2, am folosit un pic de sintaxă ES6, și anume, destructurarea obiectelor. Orice date pe care le trimitem prin cerere sunt stocate și sunt disponibile în body din req obiect. Deci, în esență, am fi putut înlocui linia 2 cu ceva de genul:

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

Pe linia 3, folosim send() funcția res obiectează să trimită rezultatul sumei. Din nou, folosim literele șablon din ES6. Acum, pentru a-l testa (folosind Postman):

1611700510 401 Tutorial REST API REST Client serviciul REST si apelurile

Deci, am trimis datele 5 și 10 ca a și b folosindu-le ca corp. Poștașul atașează aceste date la cerere și le trimite. Când serverul primește cererea, poate analiza datele de la req.body , așa cum am făcut în codul de mai sus. Rezultatul este prezentat mai jos.

Bine, codul final:

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:

Bine, am creat un server, dar cum îl putem accesa de pe site-ul nostru web sau din aplicația web? Aici bibliotecile client REST vor fi utile.

Vom construi o pagină web care va conține un formular, unde puteți introduce două numere și vom afișa rezultatul. Să începem.

În primul rând, să schimbăm server.js putin:

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.`);
});

Am importat un pachet nou path, care este furnizat de Node, pentru a manipula calea pe mai multe platforme. Apoi am schimbat GET solicitați pe ‘/’ și utilizați o altă funcție disponibilă în res, adică sendFile, care ne permite să trimitem orice tip de fișier ca răspuns. Deci, ori de câte ori o persoană încearcă să navigheze către „/”, o va primi pe a noastră index.html pagină.

În cele din urmă, ne-am schimbat app.post funcție pentru a returna suma ca JSON și a le converti pe ambele a și b la numere întregi.

Să creăm o pagină html, o voi numi index.html, cu un stil de bază:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>REST Client</title>
  </head>
  <style>
    * {
      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;
    }
  </style>
  <body>
    <div class="container">
      <h1>Simple POST Form</h1>
      </h1>
      <form>
        <label>Number 1:</label>
        <input id="num1" type="number" />
        <label>Number 2:</label>
        <input id="num2" type="number" />
        <input type="submit" value="Add"/>
      </form>
      <div class="result">Click Add!</div>
    </div>
  </body>
</html>

Să adăugăm un script etichetă chiar înainte de eticheta corpului de închidere, deci nu este nevoie să menținem un .js fişier. Vom începe prin a asculta submit eveniment și apelați o funcție în consecință:

<script>
	document.addEventListener("submit", sendData);
</script>

Mai întâi trebuie să prevenim reîmprospătarea paginii când se face clic pe butonul „Adăugare”. Acest lucru se poate face folosind preventDefault() funcţie. Apoi, vom obține valoarea intrărilor în acel moment:

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

Acum vom efectua apelul către server cu ambele valori a și b. Vom folosi Fetch API, încorporat în fiecare browser pentru aceasta.

Fetch primește două intrări, punctul final URL și un obiect de solicitare JSON și returnează un Promisiune. A le explica aici va fi în afara limitei, așa că vă las asta.

Continuați în interiorul sendData() funcţie:

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));

Mai întâi transmitem URL-ul relativ al punctului final ca prim parametru către fetch. Apoi, trecem un obiect care conține metoda pe care dorim să o folosească Fetch pentru cerere, care este POST în acest caz.

Trecem și noi headers, care va oferi informații despre tipul de date pe care le trimitem (content-type) și tipul de date pe care le acceptăm ca răspuns (accept).

Apoi trecem body. Vă amintiți că am tastat datele ca JSON în timp ce foloseam Postman? Facem un fel similar aici. Deoarece expres tratează șirul ca intrare și îl procesează în funcție de tipul de conținut furnizat, trebuie să ne convertim sarcina utilă JSON în șir. Facem asta cu JSON.stringify(). Suntem un pic mai precauți și analizăm intrarea în numere întregi, așa că nu ne încurcă serverul (deoarece nu am implementat nici o verificare a tipului de date).

În cele din urmă, dacă promisiunea (returnată de fetch) se rezolvă, vom primi acel răspuns și îl vom converti în JSON. După aceea, vom obține rezultatul din data cheie returnată de răspuns. Apoi, afișăm pur și simplu rezultatul pe ecran.

La final, dacă promisiunea este respinsă, vom afișa mesajul de eroare pe consolă.

Iată codul final pentru index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>REST Client</title>
  </head>
  <style>
    * {
      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;
    }
  </style>
  <body>
    <div class="container">
      <h1>Simple POST Form</h1>
      </h1>
      <form>
        <label>Number 1:</label>
        <input id="num1" type="number" />
        <label>Number 2:</label>
        <input id="num2" type="number" />
        <input type="submit" value="Add"/>
      </form>
      <div class="result">Click Add!</div>
    </div>
    <script>
      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));
      }
    </script>
  </body>
</html>

Am învârtit o mică aplicație pe glitch pentru ca tu să testezi.

Concluzie:

Deci, în acest post, am aflat despre arhitectura REST și anatomia cererilor REST. Ne-am străduit prin crearea unui server REST simplu care servește GET și POST solicită și a construit o pagină web simplă care folosește un client REST pentru a afișa suma a două numere.

Puteți extinde acest lucru pentru tipurile rămase de cereri și chiar să implementați o aplicație CRUD back-end completă.

Sper că ați învățat ceva din asta. Dacă aveți întrebări, nu ezitați să mă contactați prin twitter! Codificare fericită!