Tutorial: creazione di una REST API con un'integrazione non proxy Lambda - Amazon API Gateway

Tutorial: creazione di una REST API con un'integrazione non proxy Lambda

In questa procedura guidata viene utilizzata la console API Gateway per creare un'API che permette a un client di chiamare le funzioni Lambda tramite l'integrazione non proxy Lambda (detta anche integrazione personalizzata). Per ulteriori informazioni su AWS Lambda e sulle funzioni Lambda, consulta la Guida per gli sviluppatori di AWS Lambda.

Per semplificare l'apprendimento, scegliamo una funzione Lambda semplice con una configurazione API minima per illustrare le fasi di creazione di un'API di API Gateway con l'integrazione personalizzata Lambda. Laddove necessario, descriveremo la logica. Per un esempio più dettagliato dell'integrazione personalizzata Lambda, consulta Tutorial: creazione di una REST API di calcolo con due integrazioni del servizio AWS e un'integrazione non proxy Lambda.

Prima di creare l'API, configura il back-end Lambda creando una funzione Lambda in AWS Lambda, come descritto di seguito.

Creazione di una funzione Lambda per l'integrazione non proxy Lambda

Nota

La creazione di funzioni Lambda può comportare addebiti all'account AWS.

In questa fase, viene creata una funzione Lambda "Hello, World!" per l'integrazione Lambda personalizzata. In tutta la procedura guidata la funzione è denominata GetStartedLambdaIntegration.

L'implementazione di questa funzione Lambda GetStartedLambdaIntegration è la seguente:

Node.js
'use strict'; var days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']; var times = ['morning', 'afternoon', 'evening', 'night', 'day']; console.log('Loading function'); export const handler = function(event, context, callback) { // Parse the input for the name, city, time and day property values let name = event.name === undefined ? 'you' : event.name; let city = event.city === undefined ? 'World' : event.city; let time = times.indexOf(event.time)<0 ? 'day' : event.time; let day = days.indexOf(event.day)<0 ? null : event.day; // Generate a greeting let greeting = 'Good ' + time + ', ' + name + ' of ' + city + '. '; if (day) greeting += 'Happy ' + day + '!'; // Log the greeting to CloudWatch console.log('Hello: ', greeting); // Return a greeting to the caller callback(null, { "greeting": greeting }); };
Python
import json days = { 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'} times = {'morning', 'afternoon', 'evening', 'night', 'day'} def lambda_handler(event, context): print(event) # parse the input for the name, city, time, and day property values try: if event['name']: name = event['name'] except KeyError: name = 'you' try: if event['city']: city = event['city'] except KeyError: city = 'World' try: if event['time'] in times: time = event['time'] else: time = 'day' except KeyError: time = 'day' try: if event['day'] in days: day = event['day'] else: day = '' except KeyError: day = '' # Generate a greeting greeting = 'Good ' + time + ', ' + name + ' of ' + \ city + '.' + ['', ' Happy ' + day + '!'][day != ''] # Log the greeting to CloudWatch print(greeting) # Return a greeting to the caller return {"greeting": greeting}

Per l'integrazione Lambda personalizzata, API Gateway passa l'input alla funzione Lambda dal client come corpo della richiesta di integrazione. L'oggetto event del gestore della funzione Lambda è l'input.

La nostra funzione Lambda è semplice. Analizza l'oggetto event di input per le proprietà name, city, time e day. Quindi restituisce un saluto, come un oggetto JSON di {"message":greeting}, all'intermediario. Il messaggio è nel modello "Good [morning|afternoon|day], [name|you] in [city|World]. Happy day!". Si presume che l'input per la funzione Lambda sia dell'oggetto JSON seguente:

{ "city": "...", "time": "...", "day": "...", "name" : "..." }

Per ulteriori informazioni, consulta la Guida per sviluppatori di AWS Lambda.

Inoltre, la funzione registra la propria esecuzione in Amazon CloudWatch chiamando console.log(...). Questo risulta utile per tracciare le chiamate durante il debug della funzione. Per consentire alla funzione GetStartedLambdaIntegration di registrare la chiamata, imposta un ruolo IAM con le policy appropriate per la funzione Lambda per creare i flussi CloudWatch e aggiungervi le voci di log. La console Lambda permette di creare le policy e i ruoli IAM necessari.

Se configuri l'API senza usare la console API Gateway, come nel caso in cui si esegue l'importazione di un'API da un file OpenAPI, dovrai creare esplicitamente, se necessario, e configurare una policy e un ruolo di invocazione affinché API Gateway possa invocare le funzioni Lambda. Per ulteriori informazioni su come configurare i ruoli di esecuzione e di invocazione Lambda per un'API di API Gateway, consulta Controllo degli accessi a una REST API con le autorizzazioni IAM.

A differenza di GetStartedLambdaProxyIntegration, la funzione Lambda per l'integrazione proxy Lambda, la funzione Lambda GetStartedLambdaIntegration per l'integrazione personalizzata Lambda riceve l'input solo dal corpo della richiesta di integrazione API di API Gateway. La funzione può restituire un output di qualsiasi oggetto JSON, una stringa, un numero, un valore booleano o un BLOB binario. La funzione Lambda per l'integrazione proxy Lambda, al contrario, può ricevere l'input da tutti i dati di richiesta ma deve restituire un output di un oggetto JSON specifico. La funzione GetStartedLambdaIntegration per l'integrazione personalizzata Lambda può ricevere come input i parametri di richiesta API, a condizione che API Gateway mappi i parametri di richiesta API necessari al corpo della richiesta di integrazione prima di inoltrare la richiesta client al back-end. Perché ciò accada, lo sviluppatore dell'API deve creare un modello di mappatura e configurarlo nel metodo API durante la creazione dell'API.

Viene ora creata la funzione Lambda GetStartedLambdaIntegration.

Per creare la funzione Lambda GetStartedLambdaIntegration per l'integrazione personalizzata Lambda
  1. Apri la console AWS Lambda all'indirizzo https://console.aws.amazon.com/lambda/.

  2. Scegliere una delle seguenti operazioni:

    • Se viene visualizzata la pagina di benvenuto, scegliere Get Started Now (Inizia subito), quindi Create a function (Crea una funzione).

    • Se viene visualizzata la pagina di elenco Lambda > Funzioni, scegliere Create a function (Crea una funzione).

  3. Scegli Author from scratch (Crea da zero).

  4. Nel riquadro Author from scratch (Crea da zero) procedere nel seguente modo:

    1. In Nome (Name), immettere GetStartedLambdaIntegration come nome della funzione Lambda.

    2. Per Runtime, scegli l'ultimo runtime supportato di Node.js o di Python.

    3. Mantieni l'impostazione predefinita per Architettura.

    4. In Autorizzazioni espandere Modifica ruolo di esecuzione predefinito. Nell'elenco a discesa Ruolo di esecuzione, scegli Crea nuovo ruolo dai modelli di policy AWS.

    5. Per Role name (Nome ruolo), digitare un nome per il ruolo, ad esempio GetStartedLambdaIntegrationRole.

    6. Per Modelli di policy, scegliere Autorizzazioni microservizi semplici.

    7. Selezionare Create function (Crea funzione).

  5. Nel riquadro Configure function (Configura funzione) effettua quanto segue in Function code (Codice funzione):

    1. Copiare il codice di funzione Lambda elencato all'inizio di questa sezione e incollarlo nell'editor di codice inline.

    2. Lascia i valori predefiniti negli altri campi di questa sezione.

    3. Selezionare Deploy (Distribuisci).

  6. Per testare la funzione appena creata, scegli la scheda Test.

    1. Per Event name (Nome evento) immettere HelloWorldTest.

    2. Per JSON dell'evento, sostituisci il codice predefinito con il seguente.

      { "name": "Jonny", "city": "Seattle", "time": "morning", "day": "Wednesday" }
    3. Scegliere Test (Testa) per invocare la funzione. Viene visualizzata la sezione Execution result: succeeded (Risultato esecuzione: riuscito). Espandi Dettaglio. Verrà visualizzato l'output seguente.

      { "greeting": "Good morning, Jonny of Seattle. Happy Wednesday!" }

      L'output viene scritto anche in CloudWatch Logs.

Come esercizio complementare, puoi usare la console IAM per visualizzare il ruolo IAM (GetStartedLambdaIntegrationRole) creato insieme alla funzione Lambda. A questo ruolo IAM sono collegate due policy inline. Una stipula le autorizzazioni di base per l'esecuzione Lambda e consente di chiamare il comando CreateLogGroup CloudWatch per qualsiasi risorsa CloudWatch del tuo account nella regione in cui viene creata la funzione Lambda. Questa policy consente, inoltre, di creare i flussi CloudWatch e di registrare gli eventi per la funzione Lambda GetStartedLambdaIntegration.

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "logs:CreateLogGroup", "Resource": "arn:aws:logs:region:account-id:*" }, { "Effect": "Allow", "Action": [ "logs:CreateLogStream", "logs:PutLogEvents" ], "Resource": [ "arn:aws:logs:region:account-id:log-group:/aws/lambda/GetStartedLambdaIntegration:*" ] } ] }

L'altro documento della policy si applica alla chiamata di un altro servizio AWS non utilizzato in questo esempio. Puoi ignorarlo in questa fase.

Al ruolo IAM è associata un'entità attendibile, ovvero lambda.amazonaws.com. La relazione di fiducia è la seguente:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }

La combinazione di questa relazione di fiducia con la policy inline rende possibile per la funzione Lambda invocare una funzione console.log() per registrare gli eventi in CloudWatch Logs.

Creazione di un'API con l'integrazione non proxy Lambda

Con la funzione Lambda (GetStartedLambdaIntegration) creata e testata, è possibile esporre la funzione mediante un'API di API Gateway. A scopo illustrativo, viene esposta la funzione Lambda con un metodo HTTP generico. Vengono utilizzati il corpo della richiesta, una variabile di percorso URL, una stringa di query e un'intestazione per ricevere i dati di input necessari dal client. Attiviamo il validatore di richieste API Gateway per l'API per garantire che tutti i dati necessari vengano definiti e specificati in modo appropriato. Configuriamo un modello di mappatura per API Gateway per trasformare i dati della richiesta forniti dal client nel formato valido, come richiesto dalla funzione Lambda di back-end.

Per creare un'API con un'integrazione non proxy Lambda
  1. Accedere alla console API Gateway all'indirizzo https://console.aws.amazon.com/apigateway.

  2. Se si utilizza API Gateway per la prima volta, verrà visualizzata una pagina che presenta le caratteristiche del servizio. In API REST, scegliere Crea. Quando appare il popup Create Example API (Crea API di esempio), scegliere OK.

    Se non è la prima volta che si utilizza API Gateway, scegliere Create API (Crea API). In API REST, scegliere Crea.

  3. Per API name (Nome API), immettere LambdaNonProxyAPI.

  4. (Facoltativo) In Description (Descrizione), immettere una descrizione.

  5. Lasciare l'opzione Tipo di endpoint API impostata su Regionale.

  6. Seleziona Create API (Crea API).

Dopo l'API, è necessario creare una risorsa /{city}. Questo è l'esempio di una risorsa con una variabile di percorso che riceve un input dal client. Più avanti mapperai questa variabile nell'input della funzione Lambda utilizzando un modello di mappatura.

Per creare una risorsa
  1. Scegli Crea risorsa.

  2. Mantieni l'opzione Risorsa proxy disattivata.

  3. Mantieni Percorso risorsa impostato su /.

  4. Per Resource Name (Nome risorsa) immetti {city}.

  5. Mantieni CORS (Cross Origin Resource Sharing) disattivato.

  6. Scegli Crea risorsa.

Dopo la risorsa /{city}, è necessario creare un metodo ANY. Il metodo HTTP ANY funge da segnaposto per un metodo HTTP valido inviato da un client al runtime. Questo esempio mostra che il metodo ANY può essere utilizzato sia per l'integrazione Lambda personalizzata sia per quella proxy.

Per creare un metodo ANY
  1. Seleziona la risorsa /{city}, quindi scegli Crea metodo.

  2. Per Tipo di metodo seleziona ANY.

  3. Per Tipo di integrazione seleziona Funzione Lambda.

  4. Mantieni l'opzione Integrazione proxy Lambda disattivata.

  5. Per Funzione Lambda seleziona la Regione AWS in cui hai creato la funzione Lambda, quindi inserisci il nome della funzione.

  6. Scegli Impostazioni della richiesta del metodo.

    Ora, attivare un validatore richiesta per una variabile di percorso URL, un parametro di stringa di query e un'intestazione per assicurarsi che tutti i dati necessari siano definiti. Per questo esempio, crea un parametro della stringa di query time e un'intestazione day.

  7. Per Validatore richiesta seleziona Convalida parametri di stringa query e intestazioni.

  8. Scegli Parametri della stringa di query URL ed effettua le seguenti operazioni:

    1. Scegliere Add query string (Aggiungi stringa di query).

    2. Per Nome, immetti time.

    3. Attiva Campo obbligatorio.

    4. Mantieni disattivata l'opzione Caching.

  9. Scegli Intestazioni di richiesta HTTP e procedi come segue:

    1. Seleziona Add header (Aggiungi intestazione).

    2. Per Nome, immetti day.

    3. Attiva Campo obbligatorio.

    4. Mantieni disattivata l'opzione Caching.

  10. Scegli Crea metodo.

Dopo aver attivato un validatore della richiesta, configura la richiesta di integrazione per il metodo ANY aggiungendo un modello di mappatura del corpo per trasformare la richiesta in ingresso in un payload JSON, come richiesto dalla funzione Lambda di back-end.

Per configurare la richiesta di integrazione
  1. Nella scheda Richiesta di integrazione scegli Modifica in Impostazioni della richiesta di integrazione.

  2. Per Richiesta corpo passthrough scegli Quando non ci sono modelli definiti (consigliato).

  3. Scegli Modelli di mappatura.

  4. Scegliere Add mapping template (Aggiungi modello di mappatura).

  5. Per Tipo di contenuto inserisci application/json.

  6. Per Corpo del modello inserisci il seguente codice:

    #set($inputRoot = $input.path('$')) { "city": "$input.params('city')", "time": "$input.params('time')", "day": "$input.params('day')", "name": "$inputRoot.callerName" }
  7. Seleziona Salva.

Test della chiamata del metodo API

La console API Gateway offre l'opportunità di testare la chiamata dell'API prima della distribuzione. La caratteristica Test della console consente di testare l'API inviando la richiesta seguente:

POST /Seattle?time=morning day:Wednesday { "callerName": "John" }

In questa richiesta di test imposterai ANY su POST e {city} su Seattle e assegnerai Wednesday come valore di intestazione di day e "John" come valore di callerName.

Test del metodo ANY
  1. Seleziona la scheda Test. Potrebbe essere necessario scegliere il pulsante freccia destra per visualizzare la scheda.

  2. In Tipo di metodo, seleziona POST.

  3. In Percorso immetti Seattle per city.

  4. In Stringhe di query immetti time=morning.

  5. In Intestazioni immetti day:Wednesday.

  6. In Corpo della richiesta immetti { "callerName": "John" }.

  7. Scegli Test (Esegui test).

Verifica che il payload della risposta restituita sia come segue:

{ "greeting": "Good morning, John of Seattle. Happy Wednesday!" }

Puoi anche visualizzare i log per analizzare il modo in cui API Gateway elabora la richiesta e la risposta.

Execution log for request test-request Thu Aug 31 01:07:25 UTC 2017 : Starting execution for request: test-invoke-request Thu Aug 31 01:07:25 UTC 2017 : HTTP Method: POST, Resource Path: /Seattle Thu Aug 31 01:07:25 UTC 2017 : Method request path: {city=Seattle} Thu Aug 31 01:07:25 UTC 2017 : Method request query string: {time=morning} Thu Aug 31 01:07:25 UTC 2017 : Method request headers: {day=Wednesday} Thu Aug 31 01:07:25 UTC 2017 : Method request body before transformations: { "callerName": "John" } Thu Aug 31 01:07:25 UTC 2017 : Request validation succeeded for content type application/json Thu Aug 31 01:07:25 UTC 2017 : Endpoint request URI: https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:GetStartedLambdaIntegration/invocations Thu Aug 31 01:07:25 UTC 2017 : Endpoint request headers: {x-amzn-lambda-integration-tag=test-request, Authorization=****************************************************************************************************************************************************************************************************************************************************************************************************************************************338c72, X-Amz-Date=20170831T010725Z, x-amzn-apigateway-api-id=beags1mnid, X-Amz-Source-Arn=arn:aws:execute-api:us-west-2:123456789012:beags1mnid/null/POST/{city}, Accept=application/json, User-Agent=AmazonAPIGateway_beags1mnid, X-Amz-Security-Token=FQoDYXdzELL//////////wEaDMHGzEdEOT/VvGhabiK3AzgKrJw+3zLqJZG4PhOq12K6W21+QotY2rrZyOzqhLoiuRg3CAYNQ2eqgL5D54+63ey9bIdtwHGoyBdq8ecWxJK/YUnT2Rau0L9HCG5p7FC05h3IvwlFfvcidQNXeYvsKJTLXI05/yEnY3ttIAnpNYLOezD9Es8rBfyruHfJfOqextKlsC8DymCcqlGkig8qLKcZ0hWJWVwiPJiFgL7laabXs++ZhCa4hdZo4iqlG729DE4gaV1mJVdoAagIUwLMo+y4NxFDu0r7I0/EO5nYcCrppGVVBYiGk7H4T6sXuhTkbNNqVmXtV3ch5bOlh7 [TRUNCATED] Thu Aug 31 01:07:25 UTC 2017 : Endpoint request body after transformations: { "city": "Seattle", "time": "morning", "day": "Wednesday", "name" : "John" } Thu Aug 31 01:07:25 UTC 2017 : Sending request to https://lambda.us-west-2.amazonaws.com/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:GetStartedLambdaIntegration/invocations Thu Aug 31 01:07:25 UTC 2017 : Received response. Integration latency: 328 ms Thu Aug 31 01:07:25 UTC 2017 : Endpoint response body before transformations: {"greeting":"Good morning, John of Seattle. Happy Wednesday!"} Thu Aug 31 01:07:25 UTC 2017 : Endpoint response headers: {x-amzn-Remapped-Content-Length=0, x-amzn-RequestId=c0475a28-8de8-11e7-8d3f-4183da788f0f, Connection=keep-alive, Content-Length=62, Date=Thu, 31 Aug 2017 01:07:25 GMT, X-Amzn-Trace-Id=root=1-59a7614d-373151b01b0713127e646635;sampled=0, Content-Type=application/json} Thu Aug 31 01:07:25 UTC 2017 : Method response body after transformations: {"greeting":"Good morning, John of Seattle. Happy Wednesday!"} Thu Aug 31 01:07:25 UTC 2017 : Method response headers: {X-Amzn-Trace-Id=sampled=0;root=1-59a7614d-373151b01b0713127e646635, Content-Type=application/json} Thu Aug 31 01:07:25 UTC 2017 : Successfully completed execution Thu Aug 31 01:07:25 UTC 2017 : Method completed with status: 200

I log mostrano la richiesta in ingresso prima della mappatura e la richiesta di integrazione dopo la mappatura. I log risultano utili per valutare, in caso di esito negativo di un test, se l'input originale è corretto o il modello di mappatura funziona correttamente.

Distribuzione dell'API

La chiamata di test è una simulazione e presenta alcune limitazioni. Ad esempio ignora qualsiasi sistema di autorizzazione attuato per l'API. Per testare l'esecuzione dell'API in tempo reale, è necessario prima distribuire l'API. Per distribuire un'API, crea una fase per creare una snapshot dell'API in quel momento. Il nome della fase definisce inoltre il percorso di base in base al nome host predefinito dell'API. La risorsa radice dell'API viene aggiunta dopo il nome della fase. Quando modifichi l'API, devi ridistribuirla in una fase nuova o esistente per rendere effettive le modifiche.

Per distribuire l'API in una fase
  1. Seleziona Deploy API (Distribuisci API).

  2. In Fase, seleziona Nuova fase.

  3. In Stage name (Nome fase) immettere test.

    Nota

    L'input deve essere un testo con codifica UTF-8, ovvero non localizzato.

  4. (Facoltativo) In Description (Descrizione), immettere una descrizione.

  5. Seleziona Deploy (Implementa).

In Dettagli fase, scegli l'icona Copia per copiare l'URL di richiamo dell'API. Il modello generale dell'URL di base dell'API è https://api-id.region.amazonaws.com/stageName. Ad esempio, l'URL di base dell'API (beags1mnid) creato nella regione us-west-2 e distribuito nella fase test è https://beags1mnid.execute-api.us-west-2.amazonaws.com/test.

Test dell'API in una fase di distribuzione

Sono disponibili diversi modi per testare un'API distribuita. Per le richieste GET che utilizzano solo variabili di percorso URL o parametri di stringa di query, puoi immettere l'URL di risorsa dell'API nel browser. Per gli altri metodi, occorre utilizzare utilità di test dell'API REST più avanzate, come POSTMAN o cURL.

Per testare l'API tramite cURL
  1. Apri una finestra terminale sul tuo computer locale connesso a Internet.

  2. Per testare POST /Seattle?time=evening:

    Copia il comando cURL seguente e incollalo nella finestra terminale.

    curl -v -X POST \ 'https://beags1mnid.execute-api.us-west-2.amazonaws.com/test/Seattle?time=evening' \ -H 'content-type: application/json' \ -H 'day: Thursday' \ -H 'x-amz-docs-region: us-west-2' \ -d '{ "callerName": "John" }'

    Dovresti visualizzare una risposta di operazione riuscita con il payload seguente:

    {"greeting":"Good evening, John of Seattle. Happy Thursday!"}

    Se modifichi POST in PUT in questa richiesta di metodo, otterrai la stessa risposta.

Elimini

Se non hai più bisogno delle funzioni Lambda create per questa procedura dettagliata, puoi eliminarle in questa fase. Puoi anche eliminare le risorse IAM associate.

avvertimento

Se intendi completare le altre procedure guidate di questa serie, non eliminare il ruolo di esecuzione o di invocazione Lambda. Se elimini una funzione Lambda su cui si basano le API, tali API smetteranno di funzionare. L'eliminazione di una funzione Lambda non può essere annullata. Se desideri utilizzare di nuovo la funzione Lambda, dovrai ricrearla.

Se elimini una risorsa IAM su cui si basa una funzione Lambda, tale funzione e le API basate su di essa smetteranno di funzionare. L'eliminazione di una risorsa IAM non può essere annullata. Se desideri utilizzare di nuovo la risorsa IAM, dovrai ricrearla.

Per eliminare la funzione Lambda
  1. Accedere alla AWS Management Console e aprire la console AWS Lambda all’indirizzo https://console.aws.amazon.com/lambda/.

  2. Nell'elenco delle funzioni scegli GetStartedLambdaIntegration, Operazioni e quindi Elimina funzione. Quando viene richiesto, scegliere nuovamente Delete (Elimina).

Per eliminare le risorse IAM associate
  1. Aprire la console IAM all'indirizzo https://console.aws.amazon.com/iam/.

  2. In Details (Dettagli) scegliere Roles (Ruoli).

  3. Nell'elenco dei ruoli scegli GetStartedLambdaIntegrationRole, Operazioni del ruolo e quindi Elimina ruolo. Per eliminare il ruolo utilizzando la console, attieniti alla procedura seguente.