101 - CORS policy con Ionic e Node

  • Di
  • 2021-05-31 - 5 minuti
banner

CORS policy con Ionic e Node: che incubo! Hai sviluppato un’app e dei servizi back-end e vuoi sapere come gestire la CORS policy?

Mettiti comod****ə e leggi questo articolo.

Repository

Repository App Ionic di esempio

Repository back-end Node.js di esempio

Breve intro

A chi non è capitato di avere a che fare con lo sviluppo di un’applicazione che deve comunicare con dei servizi esterni e di vedere che tutto funziona (più o meno) perfettamente, finché non installiamo l’app sul device e… Si rompe.

Vediamo come gestire questa comunicazione nel modo più semplice possibile (per sviluppo, e non solo), in modo da portare alla luce temi come la CORS policy e la sua gestione.

Esempio di errore di CORS policy con Ionic e Node Esempio di errore di CORS policy con Ionic e Node

In questo caso, l’app creata è estremamente semplice: permette di inserire una serie di attività da compiere o di cancellarle, il tutto grazie ad un servizio sviluppato in Node.js che comunica con un database MongoDB (se hai dubbi su come questi componenti funzionano o come crearli, controlla le risorse utili in fondo!).

CORS policy

Cos’è

Si tratta di un meccanismo basato sull’utilizzo del protocollo HTTP che consente a un server di specificare una qualsiasi origine (dominio, schema o porta) oltre alla propria da cui un browser dovrebbe consentire il caricamento delle risorse; in altre parole, serve a specificare chi, in termini di dominio, ha accesso ad una certa risorsa, come ad esempio un servizio.

Casi d’uso

Si basa su un altro meccanismo anche più vecchio: i browser effettuano una richiesta di “verifica preliminare” rispetto al contenuto che devono accedere (aka preflight) al server che ospita la risorsa, al fine di verificare che il server ne consenta la richiesta effettiva. Per rendere ancora più immediato il concetto, vediamo un esempio: supponendo di avere un dispositivo (browser o mobile che sia) con un indirizzo http://localhost:8100 (che definiamo origine) e un’API Node.js che risponde all’indirizzo http://localhost:8081 (che definiamo destinazione), se i CORS accettano qualunque tipo di request, abbiamo quanto segue:

Caso 1: CORS in cui vengono accettate tutte le request Caso 1: CORS in cui vengono accettate tutte le request

Allo stesso modo, se configurassimo i servizi Node.js in modo che accettino le request solo da quelle con origine http://localhost:8100, avremmo quest’altro caso d’uso, che è abbastanza comunque quando si testa un’applicazione Ionic in locale:

Caso 2: CORS per cui solo http://localhost:8100 è accettata come origin Caso 2a: CORS per cui solo http://localhost:8100 è accettata come origin, quindi il browser accede correttamente

Caso 2: CORS per cui solo http://localhost:8100 è accettata come origin, quindi da mobile non si accede ai servizi Caso 2b: CORS per cui solo http://localhost:8100 è accettata come origin, quindi da mobile non si accede ai servizi

Questo è il caso più comune: come visibile nella parte superiore a sinistra dell’immagine, dove è riportato quello snippet di codice, vediamo che nella configurazione del back-end abbiamo configurato un’origine specifica per cui accettiamo le request in ingresso. Chiaramente, essendo un array, è possibile specificarne più di una e non solo: per come è stata pensata questa policy, è possibile fare riferimento anche ad altri campi inerenti l’header delle request, come il campo Access-Control-Allow-Credentials.

Torniamo però a noi: nei casi che abbiamo appena illustrato, la soluzione sembra semplice. In effetti, lo è se abbiamo controllo sul back-end e quindi possiamo decidere in che modo modificare la gestione di questa policy.

La stessa documentazione di Ionic suggerisce che, usando Capacitor, è possibile specificare a seconda del sistema operativo, l’origine con la quale veicolare le request.

Per quanto sembri strano, localhost è il valore di default e funzionerà anche una volta che l’applicazione sarà disponibile negli store: questo vuol dire che se lasciassimo che il servizio Node.js accetti tutte le richieste da http://localhost, questo meccanismo funzionerebbe come un orologio svizzero anche una volta che il nostro utente avrà scaricato l’app dal suo store di riferimento.

Documentazione ufficiale di Ionic sull’uso di Capacitor Documentazione ufficiale di Ionic sull’uso di Capacitor: https://ionicframework.com/docs/troubleshooting/cors

Ma siamo sicuri…?

Tuttavia, è sicuro lasciare localhost come origine? Assolutamente no (anche se…)

Come scritto nelle ultime due righe riportate nella figura precedente, localhost dovrebbe essere sostituito da un valore più consono relativo all’hostname che diventerà la nostra origine.

Un suggerimento può essere quello di utilizzare il dominio che fa riferimento all’applicazione: se, per esempio, questa avesse un sito di riferimento come pippo.com, l’idea dovrebbe essere quella di utilizzare questa come origine.

Per farlo, sono necessarie due modifiche: in primis, è necessario specificarlo all’interno del file capacitor.config.json in questo modo:

{
  "appId": "io.ionic.starter",
  "appName": "todoslist",
  "bundledWebRuntime": false,
  "npmClient": "npm",
  "webDir": "www",
  "plugins": {
    "SplashScreen": {
      "launchShowDuration": 0
    }
  },
  "cordova": {},
  "server": {
    "hostname": "http://pippo"
  }
}

Non solo: come visto in precedenza, all’interno della dichiarazione della funzione cors() nel servizio Node.js, dobbiamo aggiungere il dominio scelto tra quelli ammessi:

app.use(cors({origin: ['http://pippo']}))

Caso 3: CORS per cui solo http://pippo è accettata come origin, quindi da mobile si accede correttamente Caso 3: CORS per cui solo http://pippo è accettata come origin, quindi da mobile si accede correttamente

Let’s test!

Per poter verificare che tutto funzioni correttamente sfruttando la nostra rete di casa, abbiamo bisogno di 2 cose: un dispositivo mobile e una connessione WiFi.

Prima di tutto, colleghiamo il dispositivo mobile su cui installeremo l’app di sviluppo alla stessa rete dove è collegato il nostro portatile; fatto questo, verifichiamo qual è l’indirizzo del portatile nella rete locale tramite la riga di comando, con il comando ipconfig per Windows o ifconfig per sistemi GNU/Linux e macOS:

Esempio di indirizzo IP nella rete locale Esempio di indirizzo IP nella rete locale

Perfetto, l’indirizzo IPv4 è 192.168.1.64; ci aspettiamo che anche il telefono abbia un indirizzo di rete che appartiene alla stessa rete, e possiamo verificarlo tramite le impostazioni, a seconda del sistema operativo. Indicativamente, se inizia con 192.168.1.x, siamo a cavallo!

A questo punto, modifichiamo il file che riporta l’indirizzo di base dei servizi che utilizziamo nella nostra app: in questo caso, è sufficiente modificare il valore della proprietà endpointUrl all’interno del file environment.ts in questo modo:

export const environment = {
  production: true,
  baseURL: 'http://192.168.1.66:8081/api'
};

Fatto questo, siamo pronti: colleghiamo il telefono al portatile, installiamo l’app, e verifichiamo che tutto funzioni perfettamente!

Risorse utili

Post correlati

Iscriviti al TheRedCode.it Corner

La tecnologia corre, e tu devi correre più veloce per rimanere sempre sul pezzo! 🚀

Riceverai una volta al mese (o anche meno) con codici sconto per partecipare agli eventi del settore, quiz per vincere dei gadget e i recap degli articoli più interessanti pubblicati sul blog

Ci sto!

Partners

Community, aziende e persone che supportano attivamente il blog

Logo di Codemotion
Logo di GrUSP
Logo di Python Milano
Logo di Schrodinger Hat
Logo di Python Biella Group
Logo di Fuzzy Brains
Logo di Django Girls
Logo di Improove
Logo del libro open source
Logo di NgRome

Vuoi diventare #tech content writer? 🖊️

Se vuoi raccontare la tua sul mondo #tech con dei post a tema o vuoi condividere la tua esperienza con la community, sei nel posto giusto! 😉

Manda una mail a collaborazioni[at]theredcode.it con la tua proposta e diventa la prossima penna del blog!

Ma sì, facciamolo!