E' arrivato il momento di accedere alla Rete grazie al linguaggio Rust mettendo a frutto quanto imparato sinora sulle attività asincrone, in particolare facendo uso del framework Tokio che già, in questa guida, ha avuto modo di dimostrarsi estremamente pratico. In questa lezione, accederemo alla Rete sfruttando dei servizi on line puramente di test, molto utili indipendentemente dalla tecnologia di programmazione che si sta impiegando. Tra i vari esistenti, nei nostri esempi faremo uso di httpbin.org, impiegabile anche in locale come container Docker, e di DummyJSON, anch'esso ottimo per emulare interrogazioni di API REST.
Lavorare in Rete con Rust
Esistono tanti modi per lavorare in rete con un linguaggio di programmazione ma quello di cui si ha più spesso bisogno negli attuali contesti produttivi è l'interazione mediante protocollo HTTP, quello delle pagine web per intenderci, usato tipicamente come vettore per i web service.
In Rust esistono molte librerie per lavorare con HTTP ed i criteri per procedere alla scelta tra di esse potrebbero essere tra i più vari ma soprattutto:
- la volontà di agire più a basso o alto livello in base a quanto controllo si vuole avere sulle operazioni e quale livello di astrazione si preferisce;
- capacità della libreria di gestire le attività in maniera asincrona. Non si è sempre costretti a farlo, potrebbe ad esempio esistere un caso di un piccolo client dedicato solo a tali funzionalità per il quale la presenza di codice bloccante non comporterebbe problemi. In generale però si vorrà almeno la possibilità di scegliere tra gestione sincrona e asincrona delle operazioni e ciò potrà condurre alla scelta di una libreria invece che un'altra.
Infine, a guidarci nella scelta di uno strumento, conteranno molto spesso preferenze personali, abitudini o semplicemente esperienze pregresse.
Per questo esempio abbiamo scelto la libreria reqwest
Nell'esempio che segue si fa accesso ad una pagina, con una richiesta GET (una semplice lettura di contenuto), e una volta ottenuto il risultato (variabile res
body
use reqwest::Error;
async fn web_access() -> Result<String, Error> {
let res= reqwest::get("https://httpbin.org/get").await?;
println!("Codice risposta HTTP: {}", res.status());
let data = res.text().await?;
Ok(data)
}
#[tokio::main]
async fn main() -> Result<(), Error> {
let result=web_access().await?;
println!("{}", result);
Ok(())
}
Abbiamo fatto accesso all'indirizzo https://httpbin.org/get
- abbiamo usato il framework Tokio
#[tokio::main]
main
- abbiamo creato la funzione asincrona
web_access
Error
Result
; - interroghiamo l'URL con
reqwest::get
Serializzazione e deserializzazione JSON
Molto spesso lo scambio di dati in Rete avviene mediante il formato JSON, in particolare quando parliamo di API REST. Conviene quindi imparare uno strumento Rust che si può usare per serializzare e deserializzare dati in JSON e che può essere inserito comodamente in un nostro progetto.
Per provare la libreria in questione, serde
, aggiungiamo l'opportuna dipendenza in Cargo con:
cargo add serde_json
Con il seguente codice accederemo ad un elenco di citazioni rese disponibili da DummyJSON dove la numero 1, ad esempio, contiene i seguenti dati:
{"id":1,
"quote":"Your heart is the size of an ocean. Go find yourself in its hidden depths.",
"author":"Rumi"}
Come si vede dal codice seguente, il risultato che otteniamo, nel caso di successo (gestito con un match
) provvederà alla deserializzazione dei dati ottenuti:
use reqwest;
use serde_json;
use reqwest::Error;
#[tokio::main]
async fn main() -> Result<(), Error>{
match reqwest::get("https://dummyjson.com/quotes/1").await {
Ok(resp) => {
let json: serde_json::Value = resp.json().await?;
println!("{}", json.get("quote").unwrap())
}
Err(err) => {
println!("Reqwest Error: {}", err)
}
}
Ok(())
}
Il risultato dell'interrogazione convertita (serde_json::Value = resp.json()
) sarà di tipo Value
, una enum
offerta dalla libreria serde
che tra le varie cose incardina un tipo di dato mappa
che associa coppie di chiavi e valori pertanto adatto alla conversione da JSON.
Alla fine il JSON ottenuto sarà trattabile proprio come una mappa, quindi richiederemo il valore della property quote
con json.get("quote").unwrap()
per estrarne il testo della citazione.