Come costruire un API Gateway con Express

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

Hai bisogno di sapere come costruire un API Gateway con Express, ma non sai come fare? Nessun problema.

Chiariamo il concetto di API gateway e poi vediamo come realizzarne uno, oppure quali tra gli strumenti già esistenti è possibile (e consigliato usare).

Cos’è un API gateway

Funzionamento dell’API gateway con due o più microservizi Funzionamento dell’API gateway con 2+ microservizi

Un API gateway è un componente che accetta tutte le request API dai client e quindi le instrada al microservizio appropriato attraverso il routing, la composizione e il protocollo appropriato. In altre parole, è un servizio che permette di gestire più richieste a servizi diversi, occupandosi di prendere in carico le chiamate e “smistarle” al microservizio giusto, determinando il percorso migliore. Può occuparsi anche della traduzione tra protocolli Web e protocolli non compatibili con l’applicazione del client (come AMQP o WebSocket).

Inoltre, l’API gateway è un vero e proprio pattern: è consigliato se si desidera progettare e creare applicazioni basate su microservizi complessi o di grandi dimensioni con più applicazioni client che devono accedere ad una serie di servizi. Lo scopo è simile a quello del pattern cosiddetto facade: in questo caso però, costituisce un proxy inverso all’interno di un sistema e utilizza un modello di comunicazione sincrono.

Un API gateway fornisce un singolo endpoint o URL che le applicazioni client possono utilizzare e mappa internamente le richieste ai microservizi appropriati; questo fornisce quindi un livello di astrazione maggiore, nascondendo alcuni dettagli di implementazione (ad esempio, il modo in cui la richiesta verrà gestita), oltre a funzionalità aggiuntive come piani di sottoscrizione (chi può interrogare una serie di servizi e fino a quando) o trasformazioni dell’input e dell’output, o ancora gestione dei logs e degli errori.

In questo articolo, il nostro API gateway fungerà semplicemente da gateway tra i client e i nostri servizi.

Step-by-step

Creazione del progetto Express Gateway

Per creare un progetto con Express Gateway, è necessario installare Node.js ed Express Gateway; una volta fatto, è possibile usare questo comando per creare un progetto che ci permetta di scrivere la nostra applicazione:

$ eg gateway create

Verrà generato un progetto con i seguenti file:

File generati dal comando precedente File generati dal comando precedente

Chiaramente, dovremo avere a disposizione uno (o più) servizi con il quale il nostro gateway dovrà interagire. All’interno di questo articolo, andremo ad utilizzare questo repository, che offre un servizio di memorizzazione delle attività di una TODO list, ma nulla esclude che il nostro gateway possa in futuro aggiungere altri servizi e fornire un unico punto di accesso!

Configurazione del gateway

Per creare dei servizi manutenibili, esiste il file gateway.config.yml, che permette di definire un elenco di API che il gateway deve andare ad interrogare quando riceve una richiesta da un client.

Andiamo a modificare le seguenti voci: per prima cosa, definiamo nella riga 6 all’interno della proprietà apiEndpoints una nuova API che il nostro gateway andrà ad esporre, ossia tasksApi: a partire dall’indirizzo localhost (il nostro gateway si trova in locale, al momento), mapperà tutti i path sotto /tasks* (vedere la definizione all’interno del file di routing del singolo microservizio), sfruttando il servizio che andiamo a definire subito dopo, all’interno di serviceEndpoints:

apiEndpoints:
  tasksApi:
    host: localhost
    paths: '/tasks\*'
serviceEndpoints:
  tasksService:
    url: 'http://localhost:8081/api'

Anche i servizi sono esposti su localhost, ma sulla porta 8081: nel caso del gateway, andremo ad utilizzare la porta 8080, definendo questa regola all’inizio del file:

http:
  port: 8080

L’oggetto pipelines ci permette di definire in che modo il gateway deve cablare gli endpoint dell’API e il servizio: in questo caso, ne creiamo una ad hoc chiamata tasks che utilizza l’API endpoint definito in precedenza e stabilisce a quale servizio deve fare riferimento quando riceve una request:

pipelines:
  - name: tasks
    apiEndpoints:
      - tasksApi
    policies:
      - proxy:
          - action:
              serviceEndpoint: tasksService
              changeOrigin: true

Testiamo su Postman

Per assicurarci che la nostra API funzioni correttamente, possiamo testarla con Postman (o qualunque altro strumento).

Quello che avremmo fatto in precedenza, utilizzando il microservizio, sarebbe stato di effettuare una chiamata come quella riportata in figura, dove interroghiamo direttamente il servizio attraverso la sua porta:

Chiamata al microservizio Chiamata al microservizio

Invece, adesso disponiamo di un gateway che ci permette di reindirizzare correttamente le request, utilizzando un’unica porta (la 8080):

Chiamata al microservizio attraverso il gateway Chiamata al microservizio attraverso il gateway

Abbiamo raggiunto il nostro obiettivo configurando un solo microservizio: se ne volessimo aggiungere altri 10? Sarebbe sufficiente modificare il file seguendo gli step visti in precedenza per ogni nuovo microservizio, ed il gioco è fatto!

Definire un customer API

Express Gateway offre anche la possibilità di definire dei customer, ossia degli utenti che sono autorizzati ad utilizzare l’API, e questo ci permette di mettere in sicurezza i nostri servizi.

Per creare un nuovo consumer, eseguiamo la seguente request sulla porta 9876 (che viene utilizzata per la gestione amministrativa):

Creazione di un consumer Creazione di un consumer

Una volta inserite le informazioni, dobbiamo specificare che la nostra API ha bisogno di una chiave di autenticazione, e lo facciamo in questo modo: inseriamo all’interno dell’attributo policies la proprietà key-auth, che ci permette di definire che l’API sarà esposta tramite una chiave di autenticazione con un header personalizzato (opzionale) che definiamo come CUSTOM-HEADER:

pipelines:
  - name: tasks
    apiEndpoints:
      - tasksApi
    policies:
      - key-auth:
          - action:
              apiKeyHeader: CUSTOM-HEADER
              disableHeadersScheme: true
      - proxy:
          - action:
              serviceEndpoint: tasksService
              changeOrigin: true

A questo punto, creiamo delle credenziali da assegnare all’utente creato poco fa con il seguente comando:

Creazione credenziali nel formato key-auth Creazione credenziali nel formato key-auth

Se proviamo a eseguire nuovamente una request lasciando le impostazioni così com’erano, questo è quello che otteniamo:

Unauthorized La response è (giustamente) unauthorized

Per far sì che funzioni, andiamo ad aggiungere un header alla nostra request, dove il nome sarà quello configurato in precedenza, e il valore sarà dato dalla keyId:keySecret, ossia le due chiavi che abbiamo ottenuto durante il processo di creazione:

Aggiunta dell’header alla request Aggiunta dell’header alla request

Alternative

Se ti è rimasta della curiosità, prova a dare un’occhiata a queste alternative:

Risorse utili

Post correlati

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

Iscriviti alla newsletter

Per non perderti gli ultimi articoli e per vincere biglietti e gadget TheRedCode

Riceverai una volta al mese (o anche meno) gli articoli più interessanti pubblicati sul blog, e potrai provare a vincere un biglietto per uno dei prossimi eventi!

Andiamo!