←
{JS} API Third-party: API REST/RESTful
home / javascript /
Lucio Paolo Asciolla
Senior Full Stack Developer
| API REST | HTTP | URI | JSON |
A differenza delle precedenti, API Libraries, le API REST comunicano tramite richieste HTTP per eseguire funzioni di creazione, lettura, aggiornamento e l'eliminazione di record all'interno di una risorsa.
L'insieme di queste operazioni è noto come CRUD, acronimo di "create, read, update and delete".
Un'API REST utilizzerà una richiesta HTTP di tipo GET per richiamare un record, una richiesta POST per crearne una, una richiesta PUT per aggiornare un record e una richiesta DELETE per eliminarne una.
Le informazioni possono essere fornite e passate praticamente in qualsiasi formato (HTML, XLT, Python, PHP o testo semplice) ma il formato JSON risulta indubbiamente più diffuso perché può essere letto sia dagli esseri umani che dalle macchine ed è indipendente dal linguaggio di programmazione.
Gli "header" delle richieste, le intestazioni, e i relativi parametri di richiesta possono risultare importanti nelle chiamate API REST.
Queste possono includere importanti informazioni di identificazione come metadati, autorizzazioni, URI (uniform resource identifier), memorizzazione in cache, cookie e altro ancora.
Le API REST operano mediante richieste HTTP basate sulle URI.
In informatica "URI" sta per Uniform Resource Identifier che rappresenta una sequenza di caratteri che identifica universalmente ed univocamente una risorsa.

Possiamo affermare quindi che le API REST lavorano con richieste HTTP, inviate mediante la composizione di una query string, rappresentate da una URI.
All'interno dell'URI lavoreremo con particolari parametri forniti dall'API stessa.
Le API REST sono anche chiamate RESTful ed assumono questo nominativo se rispettano determinate strutture architetturali.
Standard comune per la definizione di API REST
Quasi la totalità delle API REST oggi giorno sono di tipo RESTful.
Queste API invece di ottenere dati utilizzando le funzionalità di una libreria JavaScript, ottengono dati effettuando richieste HTTP a URL specifici.
Le richieste dovranno essere effettuate a URL specifici, indicati dall'API stessa, mediante richieste HTTP che conterranno particolari parametri nella queryString (come termini di ricerca o altre proprietà).
Questo è un modello comune che incontrerai con le API.
Prendiamo come esempio l'API RESTful del New York Times per comprendere il funzionamento di questo tipo di API.
Da questo link https://developer.nytimes.com/ possiamo accedere alla documentazione dell'API, creare un account e creare la nostra API Key.
Quello che abbiamo fatto in questo video è creare un account sviluppatore richiedere una API Key ed accedere alla documentazione per l'utilizzo.
Come è possibile vedere sono disponibili diversi servizi, noi ci concentreremo su quella che consente la ricerca delle notizie mediante parametri passati nella queryString.
Non abbiamo bisogno di integrare alcuna libreria all'interno del nostro sito, potremo effettuare le nostre ricerche inviando direttamente richieste HTTP all'indirizzo indicato.
Come fa a sapere che siamo noi a inviare la richiesta? Lo sa perchè nella nostra queryString includeremo la nostra API Key.
https://api.nytimes.com/svc/search/v2/articlesearch.json?q=election&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz

https://api.nytimes.com/svc/search/v2/articlesearch.json? | questo è l'indirizzo dove inviare la richiesta; il "?" indica l'inizio della queryString |
q=election | la "q" rappresenta il parametro di ricerca per contenuto testuale |
&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz | "api-key" è il parametro che contiene la nostra API Key ed è quella che ci consente di inviare le richieste |
La documentazione ci fornisce tutto di cui abbiamo per recuperare le informazioni che desideriamo.
Nello specifico ci vengono forniti tre parametri di ricerca utilizzabili nelle queryString "q", "fq" e "api-key"
| q | è il paramentro di ricerca per contenuto testuale |
| fq | è il parametro di ricerca che include particolari filtri |
| api-key | è il parametro per aggiungere la nostra chiave sviluppatore alla richiesta |
E' possibile congiungere i parametri di ricerca attraverso il simbolo "&"
https://api.nytimes.com/svc/search/v2/articlesearch.json?q=election&fq=.........&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz
Il parametro di ricerca "fq" dell'API New York Times utilizza Elasticsearch , che consente al parametro del filtro, mediante una particolare sintassi, di separare il nome del filtro ed il valore del campo con i due punti; inoltre include la possibilità di racchiudere più valori tra parentesi tonde.
fq=news_desk:("Sports" "Foreign")
L'API ci fornisce una serie di filtri utilizzabile nelle query (ne mostriamo solo alcuni):

Tutti i filtri disponibili nella documentazione: https://developer.nytimes.com/docs/articlesearch-product/1/overview
Note: multiple tokens indica la possibilità di passare più valori al filtro del parametro "fq"; single token limita il valore ad uno.
Esistono alcuni filtri a cui è possibile passare dei valori preimpostati, questi sono indicati sempre nella documentazione:

A questo punto dovremmo aver capito come è composta una query string e conseguenzialmente le richiesta HTTP consentite dall'API.
BASE ? PARAMETRO1 = VALORE & PARAMETRO2 = VALORE & PARAMENTRO3 (API-KEY) = VALORE
Le nostre query sono guidate da parametri fissati dall'API stessa, utilizzabili e valorizzabili per effettuare le richieste.
Questo meccanismo prende il nome di "Query String Param".
L'API mette a disposizione altri parametri che vedremo rapidamente.
| facet_field | permette di impostare l'ordine dei risultati in base a dei campi specifici |
facet | impostando il campo su "true" attiviamo le funzionalità facet |
nel parametro facet_filed possiamo impostare un campo guida appartenente ai campi filtri, rimasti inutilizzati nella nostra richiesta, in modo che i risultati siano riordinati in base a tale campo
(es. day_of_week, document_type, ingredients, news_desk, pub_month, pub_year, section_name, source, subsection_name, and type_of_material);
dovremo inoltre includere il parametro "facet=true" che che attiva questa funzionalità
https://api.nytimes.com/svc/search/v2/articlesearch.json?q=match&fq=news_desk:("Sports" "Foreign")&facet_fields=day_of_week&facet=true&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz
Cosi facendo saranno restituiti i risultati riordinati in base al giorno della settimana.
| page | permette di recuperare 10 risultati per volta |
Un altro parametro è "page" che gestisce l'impaginazione;
L'API restituisce 10 risultati per volta; se impostiamo il parametro su "page=0" otterremo i risultati da 1-10, se impostiamo su "page=1" otteniamo i risultati da 11-20 e così via.
https://api.nytimes.com/svc/search/v2/articlesearch.json?q=match&page=0&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz
Così otterremo tu i risultati, da 1 a 10, che contengono la parola "match".
Abbiamo visto un pò tutti i parametri forniti dall'API per effettuare richieste, ma non possiamo gestire tutto questo manualmente.
Proviamo quindi a gestire un campo di ricerca testuale che invii un richiesta mediante l'API ai server del NewYorkTimes
Questo è il codice HTML che crea un form con un campo input di tipo testuale, un bottone per gestire l'evento "submit" del form ed un paragrafo per mostrare i risultati
<form id="formRicerca"> <input id="ricercaUtente" type="text"> <button type="submit">Ricerca</button> </form> <p stle="color:white;" id="risultatiRicerca"></p>
Questo invece il codice Javascript che utilizziamo per gestire la composizione dell'urlRequest che invieremo come richiesta HTTP al verificarsi dell'evento "submit"; per farlo utilizzaremo l'API "fetch".
var formRicerca = document.getElementById('formRicerca');
var campoRicerca = document.getElementById('ricercaUtente');
//var testoImmesso = campoRicerca.value;
var risultatiRicerca = document.getElementById('risultatiRicerca');
var urlBase = 'https://api.nytimes.com/svc/search/v2/articlesearch.json?';
//var paramTxtRicerca = `q=${testoImmesso}`;
var counterPage = 0;
var paramPage = `&page=${counterPage}`;
var paramApiKey = `&api-key=mJ8y6SKy3D5jMnj8Grpw9xWwlwzzWkcz`;
//var urlRequest = `${urlBase}${paramTxtRicerca}${paramPage}${paramApiKey}`;
formRicerca.addEventListener('submit', function(event){
event.preventDefault();
testoImmesso = campoRicerca.value;
paramTxtRicerca = `q=${testoImmesso}`;
urlRequest =`${urlBase}${paramTxtRicerca}${paramPage}${paramApiKey}`;
fetch(urlRequest)
.then(function(response){
return response.json();
//console.log('Recuperato e converito json in Promise Object');
})
.then(function(result){
for(const news of result.response.docs){
//console.log(news.abstract);
risultatiRicerca.appendChild(document.createElement('p')).innerHTML = `ARTICOLO: ${news.abstract}`;
}
})
.catch(function(error){
console.log(error.message);
})
})
Note: abbiamo commentato alcune righe, lasciandole comunque presenti in quanto consentono di capire come gestiremo la composizione dell'urlRequest; queste variabili dovranno essere create in concomitanza al verificarsi dell'evento "submit".
Dalla riga 1 alla riga 4 recuperiamo il riferimento al form, al campo input e al paragrafo dove mostrare i risultati;
dalla riga 6 alla riga 10 creiamo le variabili per gestire le singole porzioni della urlRequest: url base, un counter per le pagine, il parametro "page" ed il paramentro "api-key";
dalla riga 14 alla riga 15 iniziamo a gestire l'evento "submit"; creiamo la funzione di callback che gestirà tutte le operazioni da gestire allo scatenarsi dello evento.
"event.preventDefault()" previene il comportamento di default del form;
dalla riga 17 alla riga 18 ci occupiamo di creare le variabili necessarie all'interno della callback e successivamente necessarie nella "fetch promise" conenuta nella callback: il testo immesso dall'utente, "paramTxtRicerca" la compilazione del paramento "q" necessario alla urlRequest e infine la generazione della "urlRequest" totale concatenata.
Riprendiamo tutto il blocco che gestisce l'effettiva richiesta al server:
fetch(urlRequest)
.then(function(response){
return response.json();
console.log('Recuperato e converito json in Promise Object');
})
.then(function(result){
for(const news of result.response.docs){
console.log(news.abstract);
risultatiRicerca.appendChild(document.createElement('p')).innerHTML = `ARTICOLO: ${news.abstract}`;
}
})
.catch(function(error){
console.log(error.message);
})
Tutta la struttura della nostra "fetch" è contenuta all'interno della callback dell'evento "submit", questo perchè la richiesta HTTP deve avvenire solo al momento del click sul bottone "Ricerca".
Abbiamo esaminato già l'API Fetch è sappiamo che "fetch(urlRequest)" rappresenta una funzione con una promise, più esattamente una "Promise"; questo ci consentirà di gestire la risposta con la struttura ".then().then()....catch()".
Nel primo ".then(function(response){...}" recuperiamo la risposta preoccupandoci di convertire il JSON ricevuto in oggetto Javascript mediante il metodo "response.json()".
Quello che otteniamo è un oggetto response

Note: per visualizzare in maniera organizzata/leggibile un file json all'interno del browser potremo scaricare l'estensione per Chrome "JSON Viewer"
Questa è la visualizzazione all'interno della Google Console:

All'interno del secondo ".then(function(result){...}" gestiamo il risultato; il risultato è l'oggetto convertito proveniente per effetto del chaining dal primo "then(function(response){...}".
Dentro il ciclo "for(const news of result.response.docs){...}" ci occupiamo di ciclare i risultati in modo da poterli mostrare tutti.

| result | rappresenta tutto l'oggetto ricevuto in seguito alla nostra richiesta |
| response | rappresenta la proprietà all'interno dell'oggetto response che a sua volta è un oggetto con all'interno altre proprietà |
| docs | è una proprietà dell'oggetto response è rappresenta un array di oggetti |
| abstract | è una proprietà degli oggetti contenuto all'interno dell'oggetto docs, array di oggetti |
E' importante sapere che l'oggetto response è consultabile all'interno della richiesta stessa, il che significa che la compilazione di elementi del DOM con informazioni nell'oggetto contenuti, sarà effettuabile all'interno della richiesta stessa.
Delle alternative potrebbero essere quella di dichiarare variabili globali, omettendo "var", all'interno di un ".then(function(result){...}" o adottare un MVC pattern.
...
fetch(urlRequest)
.then(function(response){
return response.json();
})
.then(function(result){
titolo1=result.response.docs[0].abstract;
titolo2=result.response.docs[1].abstract;
titolo3=result.response.docs[2].abstract;
})
..