Categorie
Javascript Programmazione

{JS} API Third-party: API SOAP

API SOAP (Simple Object Access Protocol)

API SOAPHTTPRPCXML

SOAP è un protocollo definito “leggero” basato su XML per lo scambio di informazioni.
Disegnato da Microsoft nel 1998, poi arricchito da IBM e Lotus.
Le API progettate con il protocollo SOAP trasmettono sempre le richieste mediante protocollo-di trasporto HTTP (o SMTP).

Qual’è quindi la principale differenze tra le API REST e le API SOAP?
La principale differenza si basa sul tipo di approccio ed è determinata sostanzialmente dalla struttura di come esse lavorano.

Le API REST sono basate sulle URI (Universal Resource Identifier) con le quali gli sviluppatori possono organizzare e richiedere informazioni.
le API SOAP sono basate su RPC e su un collegamento comunicativo chiamato IDL (Interface Definition Language), che consente l’esecuzione di carichi di lavoro remoti come se fossero avviati localmente. 
L’IDL consente di lavorare tra macchine che eseguono diversi sistemi operativi o che utilizzano linguaggi diversi.


SOAP seppur ritenuto obsoleto è ancora molto utilizzato, specie nei “Sistemi Legacy”, in quanto ha ricevuto un enorme successo prima dell’avvento delle API REST.

Note: Un sistema Legacy, in informatica, è un'applicazione o un componente obsoleto, che continua ad essere usato poiché l'utente (di solito un'organizzazione) non intende o non può rimpiazzarlo.

SOAP dispone di linee guida che permettono la comunicazione via Internet tra due programmi.

Tra i principali vantaggi offerti da SOAP, troviamo in particolare:

  • Neutralità di linguaggio: SOAP può essere sviluppato con qualsiasi linguaggio.
  • Inter-operabilità: SOAP può essere implementato in qualsiasi lingua e può essere eseguito in qualsiasi piattaforma.
  • Semplicità: i messaggi SOAP sono in un formato XML molto semplice.
  • Scalabilità: grazie all’utilizzo del protocollo HTTP per il trasporto.
Chiarimento

La più grande difficoltà che potremmo incontrare è quella di chiederci come funzioni un API SOAP, ovvero, cosa c’è sotto il motore di questa tipologia di API.
In realtà l’obbiettivo lato front-end deve essere quello di conoscere tutti gli elementi necessari per utilizzarle, senza chiederci come faccia a risponderci.

RPC (Remote Procedure Call)

RPC è un protocollo nato per le interazioni, intese come scambio di informazioni, tra applicazioni client e applicazioni server.

Letteralmente una “Remote Procedure Call” è un modo per permettere l’esecuzione di procedure remote come se le procedure fossero locali.

Le chiamate a procedure remote sono definite attraverso routine contenute nel protocollo RPC.

Note: Una funzione (detta anche routinesubroutine) nell'ambito della programmazione, è un particolare costrutto sintattico che permette di raggruppare, all'interno di un programma, una sequenza di istruzioni in un unico blocco, che esegue in generale operazioni più complesse;  Questo fa in modo che a partire da determinati istruzioni di input, restituisca determinati output.

Le ruotine contenute nel protocollo RPC gestiscono ogni messaggio di chiamata e restituiscono un messaggio di risposta.

Le chiamate e le risposte RPC possono utilizzare due diversi linguaggi, JSON (JSON-RPC) e XML (XML-RPC) per la codifica, ma è universalmente utilizzato il formato XML.

gRPC (gRPC Remote Procedure Calls)

gRPC è un moderno framework open source ad alte prestazioni creato da Google nel 2015. Rappresenta un upgrade di RPC che aggiunge supporto per load balancing (bilanciamento del carico), il tracciamento, il controllo della sicurezza e l’autenticazione garantendo elevate performance.

Come funzionano le API SOAP

Il Simple Object Access Protocol (SOAP) è un protocollo basato su XML e su RPC che consente a due applicazioni di comunicare tra loro.

Gli elementi da conoscere necessari per l’utilizzo di un API SOAP sono:

  • Conoscere la struttura dei messaggi di richiesta e risposta
  • Cos’è il WSDL
  • Come inviare un richiesta HTTP

Messaggi SOAP

SOAP definisce il formato dei messaggi che due applicazioni possono scambiarsi.

SOAP è basato su XML ed un messaggio SOAP non è altro che un documento XML che descrive una richiesta di elaborazione o il risultato di una elaborazione, costituito dai seguenti elementi:

EnvelopeRappresenta il contenitore del messaggio e l’elemento root del documento XML
Header(Opzionale) È un elemento che contiene informazioni globali sul messaggio come la specifica della lingua di riferimento del messaggio, la data dell’invio, ecc.
BodyRappresenta la richiesta di elaborazione o la risposta derivata da una elaborazione
Fault(Opzionale)fornisce informazioni sugli errori che si sono verificati durante l’elaborazione e può essere presente soltanto nei messaggi di risposta

Fondamentale nella struttura di un messaggio XML sono quindi solo l’elemento-contenitore “Envelope” e l’elemento “Body” che rappresenta il contenuto dell’effettiva richiesta o risposta.

<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">

<soap:Body>
...
</soap:Body>

</soap:Envelope>

Prefissi e namespace

Il protocollo SOAP definisce il prefisso “soap:” come elemento che contraddistingue i tag e gli attributi.
Tutti i tag e quindi gli elementi principali xml di un messaggio SOAP inizieranno con il prefisso “soap:”.

Quando si utilizzano prefissi in XML, è opportuno definire un namespace.

La dichiarazione dei namespace seguente sintassi:

 xmlns: prefisso ="URI"

L’utilizzo dei namesace previene la possibilità di conflitto quando si tenta di combinare documenti XML da diverse applicazioni XML.

Quando viene definito uno spacename per un elemento, tutti gli elementi figlio con lo stesso prefisso sono associati allo stesso spacename.
Inoltre, come precedentemente accennato, può essere utilizzato per associare attributi agli elementi:

<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">

In queste tre prime linee di codice riguardanti l’elemento “Envelope”, oltre ad aver associato un prefisso “soap” così come richiesto dalle specifiche del protocollo SOAP, abbiamo creato un namespace con il medesimo nome; successivamente abbiamo creato e valorizzato l’attributo “econdingStyle” sempre attraverso il namespace appena attribuito all’elemento.

L’URI dei namespace non viene utilizzato dal parser per cercare informazioni; lo scopo dell’utilizzo di un URI è dare allo spacename un nome univoco.

Tuttavia è utilizzano spesso come puntatore a una pagina Web contenente informazioni.

 xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"

Questo namespace ed il relativo URI ci consente di determinare la versione di SOAP utilizzata (versione 1.2).
 
Se un’applicazione SOAP riceve un messaggio basato su un altro spacename, la stringa “URI” non coincide, deve generare un errore. Questa regola garantisce che tutti i messaggi conformi utilizzino esattamente lo stesso spacename e lo stesso schema XML , e quindi le stesse regole di elaborazione.

WSDL

Il Web Services Description Language (WSDL) è un documento XML in grado di descrivere le funzioni e i parametri di un Web Service.

Questo documento è quindi una descrizione di come interagire con il servizio lato client.

All’interno del file WSDL Sono descritte:

  • le “operazioni” messe a disposizione dal servizio;
  • il protocollo di comunicazione da utilizzare per accedere al servizio;
  • il formato dei messaggi accettati in input;
  • gli output restituiti e il loro formato;
  • gli endpoint di ogni funzione.

Gli elementi principali che compongono un documento WSDL (XML) sono:

<types> definisce i tipi di dato che possono essere scambiati tra client e web service
<message>descrive i messaggi che possono essere scambiati tra il web service e i client
<portType> definisce i punti di connessione verso il webservice (ogni operazione esposta ha un elemento portType)
<binding> descrive un operazione esposta dal servizio web con gli elementi in input, output ed i loro vincoli
<service> descrizione testuale del servizio (leggibile dall’uomo), e informa i client da dove accedere a quest’ultimo.

Spesso lo stesso file WSDL che avrà estensione *.wso rappresenta lo stesso “endpoint” di accesso.

Un endpoint del servizio Web (API) è una risorsa a cui è possibile fare riferimento e a cui è possibile indirizzare i messaggi di richiesta tramite HttpRequest.

E’ uso comune definire un namespace con riferimento ad esso nel campo body:

<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
soap:encodingStyle="http://www.w3.org/2003/05/soap-encoding">

<soap:Body xmlns="http://webservices.daehosting.com/services/isbnservice.wso">
...
</soap:Body>

</soap:Envelope>

E’ possibile utilizzare l’attributo “xmlns:” solo per specificare un riferimento all’URI; questo ci consente di allegare un informazione al corpo della richiesta senza dover riportare il nome prefisso ai tag figli contenuti.

Messaggi di richiesta SOAP

Qui è possibile trovare alcune API SOAP utilizzabili per testing (fornite da POSTMAN che vedremo dopo):

https://documenter.getpostman.com/view/8854915/Szf26WHn#58604e5a-7631-43dc-8ed4-904f4223d59b

Per comprendere i messaggi di richiesta e successivamente di risposta faremo riferimento a questa API “Number Conversion Service

https://www.dataaccess.com/webservicesserver/NumberConversion.wso

Questa API consente due operazioni; una funzione per convertire un numero in stringa e una funzione per convertire un numero in dollari.
Per il nostro esempio utilizzeremo la funzione “NumberToWords”:

Abbiamo precedentemente detto che il contenuto della nostra richiesta è presente all’interno del campo “Body”; per comprendere come compilare la richiesta possiamo visualizzare la relativa documentazione:

https://www.dataaccess.com/webservicesserver/NumberConversion.wso?op=NumberToWords
<?xml version="1.1" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body xmlns="https://www.dataaccess.com/webservicesserver/NumberConversion.wso">
    <NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/">
      <ubiNum>615</ubiNum>
    </NumberToWords>
  </soap:Body>
</soap:Envelope>

All’interno del tag “ubiNum” passiamo un valore numerico che vogliamo sia convertito in stringa; il tag “NumberToWords” rappresenta la funzione a cui passare il valore contenuto in “ubiNum”.

La documentazione indica il namespace, seppur non nominativo, da includere nel tag “NumberToWords”; questo a differenza del namespace del body è da inserire obbligatoriamente affinché l’API accetti la richiesta.

Inviare la richiesta HTTP
Nota: stiamo utilizzando un API SOAP Test di Postman che è basato su Node.js. E' noto che Node.js non ha un browser su cui eseguire codice motivo per il quale se proviamo ad eseguire questi esempi di codice nella Google Dev Console ci sarà restituito un errore CORS.
Cors è un sistema di sicurezza del browser e sia AJAX che Fetch sono API built-in appartenenti al browser.
Ad oggi risulta difficile trovare API-SOAP Web in uso.

Per inviare il messaggio di richiesta SOAP dovremo effettuare una richiesta all’endpoint dell’API; per farlo possiamo usare la struttura AJAX con XMLHttpRequest.
Sempre all’interno della documentazione ci viene fornito l’endpoint e la configurazione necessaria per l’header della richiesta:

var xmlhttp = new XMLHttpRequest();
    xmlhttp.open('POST', 'https://www.dataaccess.com/webservicesserver/NumberConversion.wso', true);

var soapMessageRequest = `<?xml version="1.1" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body xmlns="https://www.dataaccess.com/webservicesserver/NumberConversion.wso">
    <NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/">
      <ubiNum>614</ubiNum>
    </NumberToWords>
  </soap:Body>
</soap:Envelope>`;

xmlhttp.setRequestHeader('Content-Type','application/soap+xml; charset=utf-8');
xmlhttp.setRequestHeader('Content-lenght','length');

xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
            console.log(xmlhttp.responseText);
        }
    };

xmlhttp.send(soapMessageRequest);

Risulta molto più agevole utilizzare l’API Fetch sfruttando l’ “init object” e la relativa proprietà “body”:

fetch('https://www.dataaccess.com/webservicesserver/NumberConversion.wso', {
    method: 'POST',
    headers: {
     "Content-Type" : "application/soap+xml; charset=utf-8",
     "Content-lenght" : "length"
    },
    body: `<?xml version="1.1" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body xmlns="https://www.dataaccess.com/webservicesserver/NumberConversion.wso">
<NumberToWords xmlns="http://www.dataaccess.com/webservicesserver/"><ubiNum>614</ubiNum></NumberToWords></soap:Body></soap:Envelope>`
    })

.then(function(response){
        console.log(response.text()); 
})
.catch(function(error){
        console.log('Richiesta fallita: ', error);
})

Messaggi di risposta SOAP

La risposta ad un messaggio di richiesta SOAP è un documento xml:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <m:NumberToWordsResponse xmlns:m="http://www.dataaccess.com/webservicesserver/">
            <m:NumberToWordsResult>six hundred and fourteen </m:NumberToWordsResult>
        </m:NumberToWordsResponse>
    </soap:Body>
</soap:Envelope>

Nel caso di AJAX dovremo preoccuparci di rivedere lo snippet ed utilizzare “.responseXML”

...
xmlhttp.onreadystatechange = function(){
if (xmlhttp.readyState == 4 && xmlhttp.status == 200){
            console.log(xmlhttp.responseXML);
        }
    };
...

Nel caso di FETCH dovremmo gestire la risposta in modo da poterla convertire:

...
.then(function(response){
        return response.text();
    })
.then(function(result){
    var parser = new DOMParser();
    var xml = parser.parseFromString(result, "application/xml");
    console.log(xml);
    })
.catch(function(error){
        console.log('Richiesta fallita: ', error);
    })

Il risultato è un documento XML da poter manipolare navigare similmente al DOM.

Alcuni dettagli
  • Anche nelle API SOAP sono previste API-KEY; queste la dove indicato saranno passate come tag all’interno del messaggio di richiesta XML-SOAP.
  • Le API-SOAP sono obsolete, spesso deprecate a favore delle API-REST; il loro utilizzo è legato a sistemi Legacy.
  • Il tag <Fault> è presente solo nei messaggi di risposta ed è facoltativo; lo si può ritrovare nel documento XML-SOAP di risposta e conterrà dettagli su errori di elaborazione.

Risorse sulla rete:
https://www.w3.org/TR/2000/NOTE-SOAP-20000508/
https://www.html.it/articoli/soap-far-comunicare-le-applicazioni-sul-web/
https://codetogo.io/how-to-fetch-xml-in-javascript/

Postman

Postman rappresenta un ottimo strumento per il test di richieste HTTP di diversa natura.
Postman è su base Node.js ed è noto che Node.js è framework per sviluppo backend che non ha un browser su cui eseguire il codice, motivo per il quale il test di esecuzione codice si limita a Node Language.

Qui è spiegato come utilizzare Postman con le nostre richieste:
https://learning.postman.com/docs/sending-requests/soap/making-soap-requests/

Invece qui come testare il nostro codice node-language su Postaman:
https://learning.postman.com/docs/writing-scripts/intro-to-scripts/

Su NPM inoltre è disponibile un ottimo modulo per gestire API SOAP:
https://www.npmjs.com/package/soap

Lascia un commento

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