API Gateway Mapping

API Gateway  - API Gateway Diagram - API Gateway Mapping

Quando si utilizza il sistema di API Gateway di AWS, a volte, si ha la necessità di integrare i dati in arrivo dalla chiamata (passati dall’utente) a dati fissi oppure si ha la necessità di riorganizzare i dati in modo differente per poi poterli passare alla funziona Lambda.
Tramite il linguaggio VTL (Velocity Template Language) è possibile strutturare la mappa di integrazione con logiche personalizzate. Vediamo un esempio di integrazione semplice, dove ad ogni parametro in arrivo dalla chiamata, corrisponde un parametro passato alla Lambda.

#set($payload = $util.parseJson($input.json('$')))
{
    "pin": "demo",
    "action": "managealarm",
    "type": "$input.path('$.type')",
    "eventid": "$input.path('$.eventid')",
    "userid": "$input.path('$.userid')"
}

Non sembra di molta utilità, poiché non è dinamico e vincolato a parametri fissi, ma serve principalmente per aggiungere alcune chiave/valore specifici della chiamata.
Sicuramente più interessante è la possibilità di rendere dinamica la costruzione del JSON da restituire alla Lambda.

#set($payload = $util.parseJson($input.json('$')))
{
    "pin": "demo",
    "action": "command",
    "comname": "nome comando",
    "type": 2,
    "code": "$input.path('$.code')",
    "userid": "$input.path('$.userid')",
    "values": {
        #foreach($body in $payload.entrySet())
            #if ($body.key == "values")
                #foreach($valu in $body.value.entrySet())
                "$valu.key": "$valu.value"#if($foreach.hasNext),#end
                #end
            #end
        #end
    }
}

In questo caso, oltre ai parametri aggiuntivi con chiave e valore fissi e a quelli con chiave fissa ma con valore dinamico, si può vedere la costruzione dell’oggetto values in modo dinamico e si possono anche introdurre dei controlli, per esempio se il dato è valorizzato.


http://velocity.apache.org/engine/devel/index.html

VTL

Handlebars e Nodejs su AWS Lambda

Programming code on a monitor.  - coding - Handlebars e Nodejs su AWS Lambda

Helpers di Handlebars in Nodejs per template complessi

Mi sono ritrovato a dover creare delle pagine html statiche recuperando i dati da un database tramite la creazione di una funzione Lambda su AWS. La soluzione che mi è parsa subito la migliore è stata quella di scegliere di utilizzare la libreria https://handlebarsjs.com/ che permette la creazione di un template e la sostituzione all’interno di singoli riferimenti o di parti più complesse.

Non avendo mai utilizzato gli helpers di Handlebars, ho iniziato la ricerca online per trovare qualche suggerimento. Di seguito riporto i passaggi seguiti per l’utilizzo all’interno di una funzione Lambda, messi insieme sfruttando quanto trovato online e dopo alcuni ragionamenti personali.

Necessità:

  • scrivere una funziona async/wait che recuperato un template, sostituisca tutte le occorrenze e restituisca un html usabile per essere salvato in un file html su S3
  • utilizzare gli helpers per la sostituzione di occorrenze complesse, sia da dati statici (file json) sia da dati dinamici recuperati da database

Alla funzione, richiamata in modo asincrono, vengono passati i dati dinamici recuperati dal database. All’interno di un blocco try/catch richiama gli helpers e il template elabora i dati e restituisce un html pronto ad essere salvato su S3 per essere pubblicato online.

const document = fs.readFileSync('template-tpl.html', 'utf-8');
const menuJson = require("menu.json");
async function getHtmlPageContent(pack){
    try {
        require("hb-helpers.js")(handlebars, pack);
        const template = handlebars.compile(document);
        let data = {};
        data.itemsMenu = menuJson;
        const html = template(data);
        return html;
    } catch (error) {
        console.log('HBS ERROR', error);
        return context.fail(error);
    }
}

Fuori dalla funzione, in fase di impostazione, avevo dichiarato due costanti: la prima contenente il template html, la seconda contenente la struttura json del menù. Per prima cosa nella funzione, richiamo un file js esterno contenente gli helpers:

require("hb-helpers.js")(handlebars, pack);

e gli passo l’oggetto handlebars (oggetto della libreria) e i valori dinamici ottenuti dal database utilizzati nell’helpers per la gestione delle lingue. Quindi compilo il template html nella costante template e imposto la variabile itemsMenu dell’oggetto data con i valori del json per costruire il menu.

const template = handlebars.compile(document);
let data = {};
data.itemsMenu = menuJson;

A questo punto fondo l’oggetto data con il template per ottenere l’html completo che la funzione restituirà.

const html = template(data);
return html;

Successivamente analizziamo nel dettaglio alcuni particolari dei singoli file utilizzati.

Template HTML – (template-tpl.html)

<div class="navbar-collapse collapse float-right nav-main-collapse">
   <nav class="nav-main">
      <ul id="topMain" class="nav nav-pills nav-main">
          {{#each itemsMenu}}
              {{menuItem}}
          {{/each}}
      </ul>
  </nav>
</div>

Blocco html del menu contenente i tag di Handlebars per iterare sull’oggetto itemsMenu (variabile dell’oggetto data contenente il json), dove menuItem è l’oggetto che verrà utilizzato dall’helpers per la sostituzione con le singole voci di menu.

Helpers – (hb-helpers.js)

function hbsHelpers(hbs, pack) {
   //MENU
   hbs.registerHelper('menuItem', function() {
     var text    = hbs.escapeExpression(this.text),
         liClass = hbs.escapeExpression(this.liClass),
         href    = hbs.escapeExpression(this.url),
         aClass  = hbs.escapeExpression(this.aClass),
         spanClass  = hbs.escapeExpression(this.spanClass);
     return new hbs.SafeString(
       '<li class="'+liClass+'"><a href="'+href+'" class="'+aClass+'"><span class="trn '+spanClass+'">'+text+'</span></a></li>'
     );
   });
}
module.exports = hbsHelpers;

La funzione hbsHelpers con la registrazione dell’helpers menuItem. Questo helper recupera dal json (oggetto data.itemsMenu) i valori per text, liClass, href, aClass e spanClass e li utilizza per la costruzione della voce di menu.

Json del menu – (menu.json)

[
    {
        "text": "HOME",
        "icon": "",
        "liClass": "",
        "aClass": "",
        "spanClass": "theme-color",
        "url": "/index.html"
    },
    {
        "text": "TOUR",
        "icon": "",
        "liClass": "",
        "aClass": "",
        "spanClass": "theme-color",
        "url": "/tour.html"
    }
]

Un semplicissimo json contenente i valori per la costruzione del menu.

In conclusione, sfruttando le potenzialità di Handlebars e dei suoi helpers, è possibile costruire un html partendo da un template complesso.