+++TRENITALIA SHOCK+++ NON crederete MAI a queste API *painful*
Dopo il titolo da Youtuber in tendenza siamo pronti a capire finalmente cosa c’è dietro le app e siti pressochè inutilizzabili di Trenitalia, o che se non altro sanno arrivare primi nelle Top Charts della contro-intuitività.
Quello che state per leggere è un compendio di tutto quello che non va fatto nella creazione di API.
Tenete a mente che ho scritto il tutto in veste di nazingegnere del software, quindi potrei risultare talvolta pedante o esagerato, ma tant’è.
Piccolo disclaimer e premessa iniziale
Sono lo sviluppatore di un’app per pendolari (si chiama JustInTrain, la trovate qua sul Play Store, e ai pendolari piace, tiè Trenitalia 😉) e ho a che fare con Trenitalia e le sue API da circa due anni.
Inoltre, non sono sicuramente un API Designer, e quello che leggerete è solo frutto di miei ragionamenti e mie opinioni. Premessa ovvia quanto necessaria, perdonatemi.
Ma bando alle ciance, e cominciamo l’avventura.
Nel post proverò a descrivere le API di due diversi servizi di Trenitalia:
- www.viaggiatreno.it: che è quello attualmente usato anche in JustInTrain.
- www.trenitalia.it: servizio che ho solo recentemente scoperto, e che include API che vengono usate solo dalla versione mobile del sito stesso.
VIAGGIATRENO
Viaggiatreno come vi dicevo è un sito di Trenitalia usato per monitorare tratte e treni, ed analizzandolo attraverso il tab Network del Chrome Inspector è possibile osservare che tutte le informazioni che mostra sono in realtà ottenute attraverso richieste ad endpoint REST che restituiscono informazioni in JSON.
Sembrerebbe tutto nella norma insomma, per essere delle API.
Di seguito proviamo a simulare la semplice ricerca di una tratta, dove vorremo poi capire quanto ritardo ha un determinato treno.
Semplice a dirsi, vediamo a farsi.
Le stazioni
Se stiamo cercando una tratta, abbiamo ovviamente bisogno di inserire nella richiesta la stazione di origine e di destinazione.
Se fatto attraverso la GUI dovremmo inserire i nomi delle città, andandole forzatamente a cliccare col mouse dal menù a tendina (se scriviamo il nome e basta senza selezionarlo dal menù non va bene, non funzionerà).
Quello che invece succede sotto il cofano è ben diverso: Viaggiatreno ha bisogno dei codici identificativi univoci delle due stazioni per poter cercare la tratta, e questi li possiamo cercare per “autompletamento”:
http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/autocompletaStazione/pes
Questi sono i risultati per pes
ad esempio:
Proviamo a capire cosa non va:
- Informazioni in Plain Text, il che significa che non c’è deserializzazione, e che quindi sei obbligato a trattarlo in maniera particolare. Nulla di che eh, ma non è proprio un gran inizio.
- Il codice della stazione non è lo nel formato che poi è richiesto per gli altri endpoint. Bisognerà infatti togliere
S0
dai codici e usare il formato conS0
in alcuni endpoint, e il formato senzaS0
in altri.
Ma vabbè direte voi, niente di improponibile. Ci può stare. Te lo salvi in locale, ci lavori un po’, ed è fatta.
E vi darei anche ragione, se non fosse che quando feci il dump di tutte le possibili stazioni, cominciai a vedere il primo strato di marcio.
Questo infatti, è quello che accade se si chiama l’endpoint dell’autocompletamento con solo la s
:
Di tutte le stazioni che iniziano con la s
vi sto facendo vedere in particolare quelle esemplificative del disagio, e i più attenti di voi noteranno come non ci sia regola e standard alcuni tra i vari nomi.
Praticamente un utente che vive in una città con un Santo deve sperare in un miracolo del Santo stesso prima di beccare una combinazione di abbreviazioni che gli restituisca la sua città nel menù (su cui sarà obbligato a cliccare, non vorrei fosse passato in sordina).
In ogni caso ci siamo fatti furbi:
- Abbiamo chiamato l’endpoint con ogni lettera dell’alfabeto.
- Abbiamo salvato in locale tutte le stazioni e tutti i codici.
- Le abbiamo formattate come si deve.
- E finalmente possiamo usarle per cercare una tratta.
Cerchiamo questa benedetta tratta allora.
Le tratte
Quando cercate una tratta su Viaggiatreno questo è quello che vedrete:
Vedendo l’endpoint però possiamo cominciare a capire cosa non va:
Prima di tutto, non ce la faccio a non menzionare il mapping orribile dell’endpoint, che con tutti quei new
si porta evidentemente dietro i segni e le cicatrici di nuove versioni, iterazioni, pezze a più non posso e non so che altro.
Inoltre possiamo notare come in questo caso le stazioni vengano identificate con il codice ma senza S0
, senza apparente motivo alcuno.
Ammetto però che tra tutte le richieste che vedremo in questo post, questa è quella col risultato più “normale”:
Per quanto non ci siano insensatezze abnormi, questa risposta riesce comunque a strapparci un sorriso di compassione, ad esempio con:
- Il mischione di campi in inglese e in italiano completamente randomico, con quel
vehicles
buttato là. - La sua incoerenza tra i nomi delle categorie, che in alcuni casi sono sigle (
REG, RV, IC
) e in altri casi sono nomi completi (Frecciabianca
). Qui non è neanche questione di standard e di pattern, bastava un minimo di logica.
Suvvia però, non esageriamo con l’essere bacchettoni. Vogliamo chiamarle sviste? Chiamiamole sviste. Magari migliorerà poi.
I treni
Quando vogliamo mostrare tutte le possibili soluzioni per una tratta, dato che non siamo Trenitalia e ci teniamo all’esperienza dei nostri utenti, ora vogliamo anche mostrare il ritardo associato a ciascuna soluzione.
Tra le informazioni che ci venivano date con la richiesta per le tratte però non v’era traccia del ritardo, perciò dovremo prendere ciascun treno e fare un’ulteriore chiamata usando il suo numero identificativo.
Per fare questa richiesta non basta però solo il numero del treno. Dobbiamo infatti sapere anche il codice della stazione di partenza del treno stesso, cosa che ovviamente non è comunicata insieme al codice del treno, ma va recuperata in qualche altro modo. E indovinate un po’ come?
Con una chiamata a un endpoint di autocompletamento, ovviamente.
E quindi:
E finalmente scopriamo che il treno con codice 2183
parte dalla stazione con codice S04501
. OH che bello, finalmente possiamo scoprire il ritardo di questo dannato treno.
Procediamo allora a chiamare l’endpoint di dettaglio del treno:
http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/andamentoTreno/S04501/2183
Prima di guardare alla risposta della chiamata (che va probabilmente incorniciata e messa nel Museo del Nonsense) notare come stavolta sia richiesto il S0
nel codice della stazione 🤷.
Spero siate pronti ora, perchè sta per arrivare il pezzo forte, ovvero la risposta che si ottiene quando si richiede lo stato di un treno:
Come dite? Non c’avete capito nulla? Nulla ha senso?
Non so neanche da dove cominciare.
- La scelta di scrivere i nomi dei campi in inglese o in italiano a questo punto è chiaro che la facciano tirando una monetina (
nextTrattaType
enextFermataType
sono i miei all time favourites). - Campi messi a
null
che non verranno MAI usati. Ve lo giuro, il 98% dei campi che vedete esserenull
in questo esempio saranno semprenull
.
E allora perchè sono ancora lì voi mi direte. Non lo so. Non lo so proprio. Probabilmente retrocompabilità, ma renderebbe il tutto soltanto più grottesco, quindi preferisco non sapere. - Poi vabè, quegli array di stringhe vuote e traduzioni che mi faranno sempre sognare, 2 anni che lavoro con sta roba, mai una volta che abbiano avuto un senso.
Il resto credo si commenti da solo.
Riepiloghiamo
Abbiamo quindi scoperto che per mostrare le soluzioni con i rispettivi ritardi per una data tratta da A a B dobbiamo fare:
- Richiesta di autocompletamento del nome della stazione sia per A che per B.
- Da qui otteniamo (forse) i codici stazione di entrambe.
- Richiesta di soluzioni per la tratta usando i codici stazione trovati prima (ma modificati).
- Per ogni treno di ogni soluzione, prendiamo il suo codice identificativo.
- Richiesta di autocompletamento di ogni treno, ottenendo quindi il codice della sua stazione di partenza.
- Richiesta di dettagli del treno usando il codice di della stazione di partenza del treno e il suo codice identificativo.
Se si cercasse la parola “contorto” sul dizionario probabilmente verrebbe fuori come esempio questo esatto punto elenco.
Il fatto è che un mondo diverso è possibile:
Questo è il relativo di JustInTrain per avere le stesse informazioni che abbiamo cercato di ottenere fino adesso, ovvero soluzioni unite a ritardi, senza tanti altri voli pindarici.
Con tutta l’umiltà di questo mondo eh, però mi sembra un’esperienza diversa da quella che abbiamo visto finora.
TRENITALIA.IT
Come vi ho raccontato in quest’altro post, grazie o per colpa (dipende dai punti di vista) di un disservizio di Viaggiatreno durato ben 1 settimana ho scoperto delle nuove API di Trenitalia.
Diversamente dalle precedenti, queste sono utilizzate dalla versione mobile del sito www.trenitalia.it.
Ora proviamo a emulare la ricerca di tratte e ritardi che abbiamo fatto prima, e vediamo come va.
Partiamo a gamba tesa: siccome fare le cose con un senso non appartiene al vocabolario di Trenitalia, per fare la ricerca per tratte attraverso questi nuovi endpoint è necessario innanzitutto usare il nome delle stazioni.
Eppure prima avevamo trovato i codici di tutte le stazioni. Codici univoci. Bastavano quelli. E invece no. Adesso vogliono il nome.
IL NOME.
Vedere per credere:
https://www.lefrecce.it/msite/api/solutions?origin=roma%20termini&destination=cesena&…
A questo punto comincio quasi a pensare che queste siano tutte delle efficacissime e originali misure di sicurezza per rendere inutilizzabili le loro API da terzi.
Insomma, ora abbiamo a che fare con un’altra lista di nomi, discorde nel numero e nel contenuto da tutte le liste che avevamo fino adesso, per un totale di 4 liste diverse usate ciascuna in situazioni diverse.
Tranquilli però, perchè abbiamo ovviamente anche un nuovo frizzantissimo endpoint di autocompletamento, che però stavolta ci porta a sognare direttamente sulla Luna, perchè (tenetevi eh):
- Restituisce al massimo 5 risultati.
- Funziona solo quando gli si danno almeno 3 lettere iniziali del nome, altrimenti niente.
- Ma soprattutto: la sua ricerca la fa tra le stazioni di tutta Europa (perchè al peggio non c’è fine)
Quindi dopo che abbiamo chiamato l’endpoint con par
a questo indirizzo:
https://www.lefrecce.it/msite/api/geolocations/locations?name=par
Ci ritroviamo con 5 stazioni di cui forse due sono italiane, una è serba e due spagnole.
Questi sono invece i risultati che ci offre gentilmente Viaggiatreno, che seppur a modo suo, fa il suo sporco lavoro.
Comunque, abbiamo in qualche modo ottenuto i nuovi nomi di stazione, siamo pronti a cercare le soluzioni per la nostra tratta, non ci resta che settare l’ora, e letteralmente solo l’ora, senza i minuti.
Perchè questa è la granularità che Trenitalia ci offre, e noi che facciamo? Ci accontentiamo.
Stavolta, questo è il risultato che ci spetta se cerchiamo una tratta, ad esempio Roma Termini — Cesena.
Diamo a Cesare quel che è di Cesare, e ammettiamo che qualche passo avanti s’è fatto:
- Si sono incredibilmente decisi su che lingua usare. Grandi.
- Quel
trainacronym
sembra sufficientemente uniformato da poter essere usato senza troppi pensieri, al contrario delle variegate categorie di Viaggiatreno. - C’è un campo che si chiama
happyDay,
non so a cosa serva (probabilmente a nulla) ma è bellissimo.
Avrei preferito non dirlo, ma per un passo che hanno fatto in avanti, ne hanno fatti almeno almeno tre indietro:
- Non c’è più l’orario di partenza e arrivo per ciascun cambio. Forse aveva troppo senso averlo, quindi l’hanno tolto, e più avanti vedremo che è stato fatto per assicurare che il livello di assurdità fosse uniformato a tutto il resto.
- Sono andati così vicini a seguire lo standard REST che dovevano rovinarlo in qualche modo, mischiando la formattazione camelCase e noncamelcase.
- C’erano quasi anche con i numeri dei treni, ma no, stavolta hanno deciso di unire il numero di treno al nome (?) del treno, che però non è la sigla (?), ma è il nome esteso (?). Ma vabbè, l’unica gioia è che ‘sto maledetto numero è sempre in fondo alla stringa, quindi con una regex stupida si riesce a isolare e a estrarre alla svelta. Certo che però si son messi d’impegno eh.
Beh comunque rimane il fatto che ci mancano ancora delle informazioni, a partire dagli orari di partenza e arrivo dei vari cambi all’interno di una soluzione.
Se si guarda la GUI si intuisce subito il problema:
Gli orari di cui stiamo parlando appaiono solo quando premiamo su “info treno”.
Questo perchè quando si preme quel bottone viene fatta un’ulteriore richiesta utilizzando la stringa esadecimale idsolution
ottenuta dalla ricerca per tratta.
Per ottenere le informazioni all’interno del riquadro grigio avremo quindi questa richiesta:
https://www.lefrecce.it/msite/api/solutions/451917a0f6cf8636c7f8460cf4d236bdi0/info
La domanda è: c’era veramente bisogno di un altro endpoint per sapere solo l’orario di partenza e arrivo di un cambio?
Seriamente non era roba che poteva viaggiare insieme all’oggetto di prima?
Per onestà intellettuale devo farvi vedere pure quest’altro, che è lo stesso endpoint di prima, ma con /details
al posto di /info
.
https://www.lefrecce.it/msite/api/solutions/451917a0f6cf8636c7f8460cf4d236bdi0/details
Qui otteniamo le informazioni necessarie a mostrare questo dialog con qualche informazione ridondata rispetto a prima, e qualche altra cosa in più ma solo vagamente utile:
Che in JSON diventa:
Già che ci siamo tanto vale far notare le icone in PNG codificate in base64 all’interno del JSON (e ho tagliato le stringhe per ovvi motivi, erano lunghissime).
Avrei voluto essere lì mentre qualcuno argomentava il fatto che fare così era di gran lunga la soluzione migliore, e tutti gli altri gli davano ragione.
In ogni caso, la mancanza di informazioni dinamiche rende gli endpoint di questo servizio fondamentalmente inutili, se non altro per i nostri scopi.
L’unica informazione realmente utile è probabilmente il prezzo della tratta, che è altrimenti possibile ottenere in alcun modo da Viaggiatreno.
L’altro vantaggio di queste API risiede nel fatto che basandosi fondamentalmente su un altro sistema sono meno volubili di quelle di Viaggiatreno, e magari non si attraversano periodi di downtime di una settimana. Ehm. Viaggiatreno. Ehm.
Concludendo
Ho riversato in questo post tutta la frustrazione che ho accumulato in due anni di lavoro con questa roba. Spero di non essere stato troppo noioso e sconclusionato.
Lo dico perchè quando parlo di questa faccenda mi inalbero abbastanza facilmente, e rischio di diventare un ottantenne scorbutico.
Non so bene cosa dire riguardo a tutta questa cosa, so solo che quando ne parlo rimango sempre con l’amaro in bocca, e mi dispiace.
Mi dispiace perchè analizzando una cosa stupida come queste API in realtà si riesce a capire molto dell’azienda e della sua (cattiva) gestione.
Si intuisce che manca totalmente una visione a lungo termine, almeno in questo settore dell’azienda.
Si tira a campare, si mettono le pezze dove si può, e dove non si può la gente starà senza.
Questa è la filosofia.
Posso solo dire che spero che le cose cambino, magari con un hard-refresh dal lato dirigenziale, anche se non so bene neanche che combinazioni di eventi e personalità hanno portato ad avere un sistema in queste condizioni. Non so neanche se una cosa del genere potrebbe risolverla la situazione, arrivati a questi punto.
Lo spero davvero che le cose cambino, altrimenti ho dei seri dubbi sulla capacità di Trenitalia di stare al passo coi tempi nei prossimi 5 o 10 anni.
Lo spero, anche se questo vorrà dire la morte di JustInTrain, perchè io le mani nei treni non ce le metto più. 👋
Grazie veramente tanto di essere arrivato/a fin qua.
Se questo post ti è piaciuto e ti suscita un commento o un pensiero qualsiasi, fammelo sapere qua sotto nei commenti o su Twitter, o magari fammi sapere quale delle varie assurdità è la tua preferita.
Credo che nella mia Top 3 ci siano i campi misti anglo-italiani tipo nextTrattaType
, le immagini trasmesse in esadecimale nel JSON e le tratte cercate con i nomi delle stazioni.
Se proprio ne hai voglia puoi fare anche quella cosa dove tieni premuto sull’applauso 👏 qua sotto finchè non arrivi a un multiplo di 50, così il mio e il tuo OCD saranno contenti. 🤤