Costruisci il tuo primo router in Node con Express

Se hai fatto qualche sviluppo web con Node negli ultimi anni, probabilmente hai usato Express. Anche se non l’hai usato direttamente, molti framework destinati a rendere lo sviluppo web ancora più semplice sono ancora costruiti su Express.

Una delle caratteristiche chiave di Express è la capacità di creare rotte. Una combinazione infinita di URL può colpire lo stesso server Express, e le rotte sono il modo per determinare quali URL eseguono quale pezzo di codice. Puoi avere parametri e wildcard in modo da non dover dichiarare esplicitamente ogni endpoint.

In questo tutorial, ti guiderò attraverso la creazione di un server e ti insegnerò tutto quello che devi sapere sulle rotte in Express.

Cos’è una rotta in Express?

Le rotte determinano quali dati devono essere consegnati per ogni URL. Prendiamo come esempio il file server più semplice. Diciamo che hai una struttura di file:

files/├── images/│ ├── cat.png│ ├── dog.jpg│ └── pig.bmp└── text/ ├── README.md └── todo.txt

Potresti quindi eseguire un semplice server HTTP che servirà automaticamente quei file e creerà un indice per le directory. Non c’è files/index.html, ma il server sta ancora generando una pagina web e servendo il contenuto basato sui file in quella cartella. Se vai su /images/cow.gif otterrai un errore 404 – anche se non c’è nessun file lì, sta ancora servendo qualcosa.

npm install -g http-servercd fileshttp-server

In Express, una rotta consiste in un method, un path, e un handler.

Metodi, percorsi e gestori, oh mio Dio!

Il method potrebbe essere qualsiasi verbo HTTP, come GET (per recuperare il contenuto – questo è ciò che la maggior parte delle pagine web usa), o POST (per inviare il contenuto al server – questo è comune con i moduli HTML). Puoi anche specificare che vuoi che Express gestisca lo stesso percorso per tutti i metodi, se vuoi.

Il path è una stringa o un’espressione regolare che descrive l’URL relativo. Se stai lavorando con la root della tua app, questo descrive l’URL assoluto. Un percorso può essere definito in diversi modi.

Il metodo e il percorso sono essenziali per sapere quando fare qualcosa, ma il gestore è la funzione di callback che viene effettivamente chiamata in quei casi. Ad un gestore vengono passati un request, un response, e un next callback, e questi argomenti sono tipicamente scritti come (req, res, next)..

  • Richiesta (req): La richiesta contiene tutti i tipi di informazioni su ciò che è stato chiesto dall’utente. Da qui si può accedere al percorso, ai parametri, alle intestazioni e a una miriade di altre cose. Per tutto ciò che riguarda una richiesta, potete consultare il riferimento API
  • Risposta (res): La risposta è il modo in cui si inviano le informazioni all’utente. Il modo più semplice per rimandare i dati è con il metodo .send (per esempio res.send('Hello, world!')), ma ci sono molti altri metodi. Di nuovo, puoi trovare tutti i metodi nel riferimento API
  • Next Callback (next): La funzione next permette di utilizzare più gestori per la stessa rotta. Puoi usare un gestore per elaborare le informazioni, e quando ha finito può chiamare next() per segnalare che è possibile passare al gestore successivo. Se si passa una stringa, verrà invece lanciato un errore, che si può catturare altrove, o mostrare all’utente (ad esempio next('You must be authenticated to access this route')).

Che cos’è un Router in Express?

Ora che si ha un po’ più di familiarità con le rotte, in cosa è diverso da un router? Puoi pensare a un router come a una collezione di rotte. Questo può essere un modo utile per organizzare diverse sezioni della tua app.

Quando usi un router, puoi pensare in termini di un percorso principale, anche se stai per usare quel router da qualche sottopercorso. Per esempio, diciamo che avete un’API per gestire i messaggi. Potreste avere un router con un percorso '/' per GET tutti i messaggi o POST un nuovo messaggio. Si potrebbe avere un altro percorso '/:id' per GET o PUT (modificare) un messaggio specifico.

Creare una semplice app con un router in Node con Express

Basta parlare… passiamo al codice reale. Per iniziare, create una cartella che ospiterà tutto il vostro codice. Poi impostate una cartella package.json per aiutare a gestire le dipendenze. Potete usare npm init per farlo. Avrai anche bisogno di installare Express.

mkdir my-first-routercd my-first-routernpm init -ynpm install [email protected] [email protected]

Crea un file index.js con il seguente codice:

index.js

Questo dice a Express di usare Handlebars (hbs) come motore di visualizzazione. Usa il path integrato in Node per dirgli la directory contenente le viste. Al percorso / viene detto di rendere la pagina usando index.hbs, che metterà il content in un tag paragrafo (p).

Per essere sicuri che Express abbia dei template da renderizzare, create una nuova cartella chiamata views, poi create un nuovo file lì dentro chiamato layout.hbs. Quando dite a Express di rendere una vista, renderà prima layout.hbs e metterà il contenuto della vista dentro il tag {{{body}}}. Questo ti permette di impostare uno scheletro per l’applicazione. Ecco un po’ di HTML di base usando Bootstrap che vi darà un bello stile senza bisogno di scrivere alcun CSS. Questo renderà anche il title passato nel contesto nel vostro / route.

views/layout.hbs

Avrete anche bisogno di creare una index.hbs vista che sarà solo molto semplice per ora:

views/index.hbs

<p>{{content}}</p>

Per rendere lo sviluppo un po’ più facile, è possibile installare nodemon con:

npm install --save-dev [email protected]

Quindi modifica il tuo file package.json in modo che la voce "scripts" includa uno script iniziale con nodemon .. Questo farà in modo che possiate semplicemente eseguire npm start e il vostro server si riavvierà automaticamente ogni volta che farete delle modifiche:

"scripts": { "start": "nodemon ."}

Ora nel vostro terminale, se digitate npm start avvierete il server. Potete poi andare su per vedere l’applicazione in esecuzione.

Creare un Router in Express

Bene, è un po’ noioso. Che ne dite di fargli fare qualcosa di utile? Creiamo una semplice lista di cose da fare. Iniziate creando un router per gestire un elenco di elementi. Create un nuovo file chiamato todo.js:

todo.js

Qui avete due gestori di route. Il primo ascolta le richieste POST (indicate da router.post). Sostituirà la lista delle cose da fare con una copia di quello che riceve dal modulo. Se il modulo contiene la proprietà remove (contenente un indice), userà splice per rimuovere l’elemento a quell’indice. Se il modulo contiene la proprietà new, un nuovo elemento sarà spinto nell’array. Dopo aver finito di modificare la lista delle cose da fare, chiama next() per passare al gestore del percorso successivo.

Il secondo gestore del percorso è sempre utilizzato (indicato da router.use). Il suo unico scopo è quello di rendere la lista delle cose da fare. Separando le rotte in questo modo, si può facilmente fare una cosa sempre, e un’altra cosa solo in determinate circostanze (in questo caso su una richiesta POST).

Per dire all’app di usare questo router, dovrete aggiungere alcune linee al index.js:

index.js

Ora per il template todo. È un po’ più grande, quindi l’ho tenuto per ultimo. Se avete familiarità con l’HTML non dovrebbe essere troppo difficile da seguire. Handlebars aggiunge alcune caratteristiche che ti permettono di accedere alle variabili. In questo caso, state usando un blocco {{#if}} per rendere qualcosa di speciale se non ci sono elementi, così come un blocco {{#each}} per rendere ogni elemento della lista con un markup minimo.

L’unico JavaScript usato qui è per inviare automaticamente il modulo quando cambiate qualcosa. Se JavaScript fosse disabilitato, questo funzionerebbe ancora quando si preme il tasto “Invio” sulla tastiera, grazie al pulsante nascosto etichettato “Autosave”.

views/todo.hbs

Ora andate su e inserite alcuni elementi nella vostra lista di cose da fare.

Aggiungi autenticazione utente in Node

Ora avete una lista di cose da fare funzionale. Avrai notato, però, che questo funziona solo se vuoi che tutti quelli che lo usano condividano la stessa lista. Se aggiungi l’autenticazione, puoi avere una lista di cose da fare separata per ogni utente.

Aggiungere utenti non deve essere un dolore. Infatti, può essere fatto molto semplicemente con Okta. Che cos’è Okta, potreste chiedere. Okta è un servizio cloud che permette agli sviluppatori di creare, modificare e memorizzare in modo sicuro gli account utente e i dati dell’account utente, e collegarli con una o più applicazioni.

Se non ne avete già uno, iscrivetevi per un account sviluppatore gratuito per sempre.

Avrete bisogno di salvare alcune informazioni da utilizzare nell’app. Crea un nuovo file chiamato .env. In esso, inserite l’URL della vostra organizzazione.

HOST_URL=http://localhost:3000OKTA_ORG_URL=https://{yourOktaOrgUrl}

Avrete anche bisogno di una stringa casuale da usare come App Secret per le sessioni. Potete generarla con i seguenti comandi:

echo -e "\nAPP_SECRET=`npx -q uuid`" >> .env

Poi, accedete alla vostra console di sviluppo, navigate su Applicazioni, poi cliccate su Aggiungi applicazione. Seleziona Web, quindi fai clic su Next. Date un nome alla vostra applicazione, come “Il mio primo router”. Cambiate l’URI di base in e l’URI di reindirizzamento al login in , poi cliccate su Done

Cliccate su Edit e aggiungete un URI di reindirizzamento al logout di , poi cliccate su Save.

La pagina a cui si arriva dopo aver creato un’applicazione ha alcune altre informazioni da salvare nel file .env. Copiate l’ID cliente e il segreto cliente.

OKTA_CLIENT_ID={yourClientId}OKTA_CLIENT_SECRET={yourClientSecret}

Ora torniamo al codice. Avrete bisogno di aggiungere il middleware OIDC di Okta per controllare l’autenticazione. Si basa anche sull’uso delle sessioni. Dovrete usare dotenv per leggere le variabili dal file .env. Per installare le dipendenze di cui avrai bisogno, esegui questo comando:

Ora modifica il tuo file index.js. Qui aggiungerai i middleware di sessione e OIDC, e un logout percorso in modo che gli utenti possano uscire dall’applicazione. Aggiungerai anche un middleware specifico al todoRouterapp.use('/todo', oidc.ensureAuthenticated(), todoRouter)). Aggiungendo oidc.ensureAuthenticated(), si lascia che Okta si assicuri che il percorso non possa essere raggiunto a meno che l’utente non sia loggato. Se l’utente non è loggato e cerca di raggiungere quel percorso, verrà portato su un sito sicuro per effettuare il login, e poi verrà reindirizzato al tuo sito.

index.js

Per rendere le cose un po’ più semplici quando un utente si disconnette, aggiungi un link all’elenco delle cose da fare dalla home page.

views/index.hbs

<p>{{content}}</p><a href="/todo">Go to To-Do List</a>

Puoi anche aggiungere un messaggio di benvenuto e un pulsante di logout al tuo layout.hbs.

views/layout.hbs

Per far sì che funzioni, dovrete aggiungere userinfo al contesto quando renderizzate le viste.

todo.js

index.js

OK, quindi ora state richiedendo agli utenti di effettuare il login prima di poter modificare la lista degli impegni, ma è ancora una lista singola e condivisa. Per dividerla in una lista separata per ogni utente, fate un’altra piccola modifica a todo.js.

todo.js

Impara di più su Node, Express e sullo sviluppo web sicuro

Ora che hai una lista di cose da fare perfettamente funzionante, ti incoraggio ad ampliarla. Prova a memorizzare i dati in un database, o addirittura lascia che Okta li memorizzi per te! Vedete se potete creare qualche altro router da aggiungere al server web.

Se volete vedere l’esempio di codice finale, potete trovarlo su GitHub.

Se volete saperne di più su Node ed Express guardate alcuni di questi altri articoli sul blog degli sviluppatori di Okta:

  • Costruire e capire il middleware Express attraverso degli esempi
  • Costruire e capire un semplice sito web Node.js con autenticazione utente
  • Costruisci una semplice API REST con Node e OAuth 2.0
  • Costruisci un’autenticazione sicura di Node con Passport.js e OpenID Connect
  • Sicura una API di Node con credenziali client OAuth 2.0

Lascia un commento

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