Categorie
Javascript Programmazione

{JS} API Third-party: API REST/RESTful

API REST (Representational State Transfer)

API RESTHTTPURIJSON

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.

API RESTful

Le API REST sono anche chiamate RESTful ed assumono questo nominativo se rispettano determinate strutture architetturali.

 Specifica OpenAPI

Standard comune per la definizione di API REST

  1. Interfaccia uniforme. Tutte le richieste API devono presentarsi uguali, indipendentemente dal tipo di richiesta. Le risposte fornite non devono essere troppo grandi ma devono contenere tutte le informazioni di cui il client può avere bisogno.
  2. Disaccoppiamento client-server. Le applicazioni client e server devono essere completamente indipendenti l’una dall’altra. L’applicazione client non può interagire con l’applicazione server in alcun altro modo. In modo analogo, un’applicazione server non deve modificare l’applicazione client e limitarsi a trasferirle i dati richiesti tramite HTTP.
  3. Condizione di stateless. Le API REST sono stateless, il che vuol dire che devono richiedono alcuna sessione lato server. Alle applicazioni server non è consentito archiviare dati correlati a una richiesta client.
  4. Possibilità di memorizzazione nella cache. Quando possibile, le risposte devono essere memorizzabili nella cache o lato client o lato server. Le risposte del server devono contenere informazioni che indicano se la memorizzazione in cache è consentita. L’obiettivo è quello di migliorare le prestazioni sul lato client.
  5. Architettura di sistema a livelli. Le chiamate e le risposte passano attraverso diversi livelli e substrati. In generale, non devono presumere che le applicazioni client e server si connettano tra loro.
    Devono prevedere diversi intermediari nel loop di comunicazione. Le API REST devono essere progettate in modo che né il client né il server possano capire se comunicano con l’applicazione finale o con un intermediario.
  6. Codice on-demand (facoltativo). Le API REST di solito inviano risorse statiche ma, in certi casi, le risposte possono contenere anche del codice eseguibile (come ad esempio gli applet Java). In questi casi, il codice deve essere eseguito solo on-demand.

L’API RESTful del New York Times

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=electionla “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_fieldpermette di impostare l’ordine dei risultati in base a dei campi specifici
facetimpostando 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.

pagepermette 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”.

Un semplice campo di ricerca

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.

resultrappresenta tutto l’oggetto ricevuto in seguito alla nostra richiesta
responserappresenta 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;
})
..

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *