Questa è la faccia con cui vi voglio mentre leggete questo post.

+++TRENITALIA SHOCK+++ NON crederete MAI a queste API *painful*

Alberto Giunta
13 min readFeb 2, 2018

--

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:

Bene, ma non benissimo.

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 con S0 in alcuni endpoint, e il formato senza S0 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:

I Santi. Trenitalia te li fa tirare giù tutti uno per uno.

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:

  1. Abbiamo chiamato l’endpoint con ogni lettera dell’alfabeto.
  2. Abbiamo salvato in locale tutte le stazioni e tutti i codici.
  3. Le abbiamo formattate come si deve.
  4. E finalmente possiamo usarle per cercare una tratta.
La stessa cosa in JustInTrain è rappresentata così. E di certo non è rocket science.

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:

http://193.138.161.135/viaggiatrenonew/resteasy/viaggiatreno/soluzioniViaggioNew/7104/5066/2018-01-27T10:29:00

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 quelvehicles 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.

Una cosa del genere insomma.

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:

http://www.viaggiatreno.it/viaggiatrenonew/resteasy/viaggiatreno/cercaNumeroTrenoTrenoAutocomplete/2184

L’ennesimo esempio di incoerenza: il nome della stazione di partenza del treno a sinistra è diverso da quello restituito dall’autocompletamento nel menù. Questa cosa apparantemente innocua causa una marea di problemi quando si vogliono fare ragionamenti più complessi, perchè non si sa mai con quale lista di stazioni si sta avendo a che fare.

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 ( nextTrattaTypee nextFermataTypesono i miei all time favourites).
  • Campi messi a null che non verranno MAI usati. Ve lo giuro, il 98% dei campi che vedete essere null in questo esempio saranno sempre null.
    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:

  1. Richiesta di autocompletamento del nome della stazione sia per A che per B.
  2. Da qui otteniamo (forse) i codici stazione di entrambe.
  3. Richiesta di soluzioni per la tratta usando i codici stazione trovati prima (ma modificati).
  4. Per ogni treno di ogni soluzione, prendiamo il suo codice identificativo.
  5. Richiesta di autocompletamento di ogni treno, ottenendo quindi il codice della sua stazione di partenza.
  6. 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.

QUESTE, son le stazioni che vorrei vedere se cerco PAR. Non qualche città serba o spagnola.

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.

Qui ho finalmente capito come ottengono i prezzi le altre app di treni. Usano proprio queste API qua.

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. 🤤

--

--