{"id":274,"date":"2018-09-11T09:40:19","date_gmt":"2018-09-11T07:40:19","guid":{"rendered":"https:\/\/blog.besharp.it\/?p=274"},"modified":"2021-03-17T12:11:46","modified_gmt":"2021-03-17T11:11:46","slug":"go-serverless-pt1","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/","title":{"rendered":"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS"},"content":{"rendered":"

Negli ultimi anni, il termine \u201cServerless\u201d<\/strong> ha preso sempre pi\u00f9 piede nell\u2019ambito IT.<\/p>\n

L\u2019ennesima buzzword? Oppure \u00e8 davvero possibile sviluppare un\u2019applicazione che non utilizzi alcun server, come questa parola suggerirebbe? Cerchiamo di chiarire questo possibile equivoco…<\/p>\n

Serverless \u00e8 un paradigma Cloud<\/strong> che permette l\u2019esecuzione di applicazioni in maniera agnostica rispetto all\u2019infrastruttura sottostante. Grazie a servizi Cloud come (ad esempio) AWS Lambda, API Gateway ed EKS,<\/strong> si possono sviluppare applicazioni per le quali le operazioni di provisioning, scalabilit\u00e0 e gestione siano svolte in maniera trasparente ed automatizzata, senza l\u2019intervento manuale di chi scrive il codice.<\/p>\n

Questa nuova tecnologia ha numerosi vantaggi che migliorano sia l\u2019esperienza dell\u2019utente che quella dello sviluppatore e saperli sfruttare \u00e8 fondamentale per realizzare soluzioni competitive, altamente scalabili e performanti.<\/p>\n

In questa serie di 3 articoli illustreremo come sia possibile costruire un sistema di file sharing<\/strong> completo di login, \u201cdrag and drop\u201d e condivisione dei file mediante link, sfruttando le potenzialit\u00e0 della tecnologia serverless e i servizi messi a disposizione da AWS.<\/p>\n

Amazon mette a disposizione una vasta gamma di servizi gestiti<\/strong> che \u00e8 possibile sfruttare per implementare rapidamente architetture completamente serverless: realizzeremo quindi un\u2019infrastruttura cos\u00ec come rappresentata nell\u2019illustrazione sottostante, per poi analizzare nel dettaglio come configurare i trigger necessari per rispondere agli eventi, come l\u2019upload dei file.<\/p>\n

\"\"<\/p>\n

L\u2019applicazione si comporr\u00e0 di un front-end statico e di una serie di API di back-end, entrambi protetti da autenticazione. Le informazioni sui file e le condivisioni saranno salvate su un database di tipo chiave-valore, mentre tutti i file verranno salvati su object storage.<\/p>\n

C\u2019\u00e8 un punto interessante che vale la pena sottolineare: gli upload degli utenti saranno effettuati direttamente sull’object storage mediante un apposito meccanismo di autorizzazione. Questo permetter\u00e0 all\u2019applicazione di scalare in modo rapido<\/strong> all’aumento delle richieste, minimizzando le risorse da preallocare ed i relativi costi.<\/p>\n

Per realizzare questa soluzione andremo ad impiegare alcuni dei servizi Serverless pi\u00f9 interessanti, come S3<\/strong> per lo storage degli oggetti, DynamoDB<\/strong> come base dati, Lambda<\/strong> per l\u2019esecuzione delle API di back-end, Api Gateway<\/strong> per esporre le API, CloudFront<\/strong> come CDN per servire il front-end e Cognito<\/strong> per i servizi di registrazione e autenticazione degli utenti.<\/p>\n

Affronteremo anche il tema del deploy automatico del codice realizzando una pipeline di Continuous Deployment\/Continuous Integration<\/strong> che consenta di rilasciare in modo agile ed automatico le modifiche al software.<\/p>\n

\"\"<\/p>\n

Nello specifico saranno realizzate due pipeline separate per gestire la CD\/CI di back-end e front-end. Quella del back-end utilizzer\u00e0 un template di CloudFormation per effettuare il provisioning delle funzioni Lambda e aggiornare il codice, mentre quella del front-end provveder\u00e0 alla copia degli asset sull\u2019apposito bucket e a gestire la CDN con le invalidazioni necessarie.<\/p>\n

Andiamo ora ad illustrare i servizi utilizzati in funzione delle scelte progettuali.<\/p>\n

Amazon S3<\/h3>\n

\u201cAmazon S3 \u00e8 uno storage di oggetti creato per memorizzare e ripristinare qualsiasi volume di dati da qualsiasi origine. \u00c8 un servizio che offre un’infrastruttura di storage estremamente durevole, altamente disponibile e scalabile in modo illimitato a costi ridotti.\u201d<\/p><\/blockquote>\n

Sfrutteremo S3 sia come sorgente per i file che compongono il Front-End dell\u2019applicazione sia come storage per i file caricati dall\u2019utente. L\u2019utilizzo di questo servizio permette di avere spazio virtualmente illimitato altamente disponibile e a costi ridotti.<\/p>\n

Per rendere l\u2019implementazione pi\u00f9 sicura utilizzeremo 2 Bucket separati, allo scopo di partizionare meglio i permessi e tenere fortemente isolato lo storage applicativo da quello dei dati degli utenti.
\nIl Bucket riservato agli asset statici sar\u00e0 la sorgente per la CDN utilizzata per distribuire il frontend ai client.<\/p>\n

CloudFront<\/h3>\n

\u201cAmazon CloudFront \u00e8 una rete per la distribuzione di contenuti o CDN (Content Delivery Network) globale, che permette la distribuzione di dati, video, applicazioni e API agli utenti con latenza minima e velocit\u00e0 di trasferimento elevata.\u201d<\/p><\/blockquote>\n

Utilizzeremo CloudFront per servire il Fornt-end della nostra applicazione. Oltre a migliorare le performance e l\u2019esperienza utente, permette anche di ottenere protezione da attacchi di tipo DDoS<\/strong> e di abbattere i costi di accesso ad S3 per file che vengono richiesti frequentemente.<\/p>\n

DynamoDB<\/h3>\n

\u201cAmazon DynamoDB \u00e8 un database non relazionale che fornisce prestazioni affidabili su qualsiasi scala. Si tratta di un database multi-master, multiregione e completamente gestito che fornisce latenza costante di pochi millisecondi e sicurezza integrata, backup e ripristino e cache in memoria.\u201d<\/p><\/blockquote>\n

La scelta di DynamoDB su altri validi DBMS \u00e8 dovuta principalmente dal fatto che l\u2019applicazione salva metadati relativi ai file caricati e alla loro condivisione, dove tutto \u00e8 fortemente \u201cfile centrico\u201d. La struttura dei dati \u00e8 calzante con il modello chiave valore di DynamoDB, condizione resa possibile tra l\u2019altro dalla delega della gestione dell\u2019autorizzazione e dell\u2019anagrafica utenti a Cognito.<\/p>\n

Inoltre, scegliendo di utilizzare DynamoDB, l\u2019applicazione beneficia in modo quasi del tutto automatico di una base dati facilmente e automaticamente scalabile orizzontalmente, full managed<\/strong> e altamente disponibile.<\/p>\n

Cognito<\/h3>\n

\u201cAmazon Cognito permette di aggiungere strumenti di registrazione, accesso e controllo degli accessi alle app Web e per dispositivi mobili in modo rapido e semplice. Amazon Cognito permette di ricalibrare le risorse per milioni di utenti e supporta l’accesso con provider di identit\u00e0 social quali Facebook, Google e Amazon e provider di identit\u00e0 aziendali tramite SAML 2.0.\u201d<\/p><\/blockquote>\n

Abbiamo scelto di delegare l\u2019autenticazione e la gestione dell\u2019anagrafica utenti ad un servizio gestito. Questo consente di limitare la superficie d\u2019attacco del servizio che stiamo costruendo, aumentare le possibilit\u00e0 di login e autenticazione e disporre di una integrazione rapidissima e bullet proof con API gateway. Quest’ultima permette di ridurre i costi in quanto tutto l\u2019effort di autenticazione viene effettuato dal gateway e non incide sul tempo di calcolo delle Lambda. Inoltre, eventuali tentativi di login errati o chiamate effettuate con token scaduti o errati non raggiungeranno mai l\u2019applicazione ma saranno gestiti direttamente sul perimetro esterno dell\u2019architettura.<\/p>\n

L\u2019anagrafica gestita consente anche di annullare il traffico sulla base dati per reperire le principali informazioni sugli utenti, sgrava dal mantenimento e dalla messa in sicurezza delle tabelle con dati sensibili e alla gestione delle credenziali.<\/p>\n

Lambda<\/h3>\n

\u201cAWS Lambda consente di eseguire codice senza dover effettuare il provisioning n\u00e9 gestire server. Le tariffe sono calcolate in base ai tempi di elaborazione, perci\u00f2 non viene addebitato alcun costo quando il codice non \u00e8 in esecuzione.\u201d<\/p><\/blockquote>\n

Il back-end sar\u00e0 sviluppato interamente con AWS Lambda. Questa tecnologia, principe della filosofia serverless, permette di pagare per singola esecuzione, e solo per il tempo effettivamente utilizzato, annullando i costi di idle, lo spreco di potenza di calcolo e risparmiandoci di dover configurare e testare una adeguata politica di auto scaling.<\/p>\n

Api Gateway<\/h3>\n

\u201cAmazon API Gateway \u00e8 un servizio completamente gestito che semplifica agli sviluppatori creazione, pubblicazione, manutenzione, monitoraggio e protezione delle API su qualsiasi scala.\u201d<\/p><\/blockquote>\n

In questo caso si tratta di una scelta naturale, solo AWS Api Gateway dispone di tutti gli hook e le integrazioni necessarie ad un inserimento seamless ed efficace nell\u2019architettura applicativa. Lo scopo principale \u00e8 quello di fornire un’interfaccia altamente disponibile, performante ed affidabile alle funzioni lambda del backend. Permette inoltre di integrare Cognito per autenticare le chiamate e passare al backend solo quelle correttamente autenticate e legittime, bloccando di fatto tutte le richieste non valide. Un altro vantaggio \u00e8 quello di poter integrare facilmente cloudfront per conservare in cache le risposte del backend per risparmiare in termini di tempo di calcolo<\/strong> e aumentando allo stesso tempo la responsivit\u00e0 dell\u2019applicazione riducendo la latenza.<\/p>\n

Nei prossimi articoli esamineremo in dettaglio la struttura dell\u2019applicazione, l\u2019infrastruttura serverless e i trigger da configurare per rispondere agli eventi importanti per l\u2019applicazione.<\/p>\n

Stay tuned!<\/p>\n

Leggi la seconda parte<\/a> | Leggi la terza parte<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"

Negli ultimi anni, il termine \u201cServerless\u201d ha preso sempre pi\u00f9 piede nell\u2019ambito IT. L\u2019ennesima buzzword? Oppure \u00e8 davvero possibile sviluppare […]<\/p>\n","protected":false},"author":6,"featured_media":361,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[477],"tags":[263,364,360,267],"yoast_head":"\nGo Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS - Proud2beCloud Blog<\/title>\n<meta name=\"description\" content=\"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Go Serverless! Parte 1: realizziamo un\u2019applicazione Serverless di File Sharing.\" \/>\n<meta property=\"og:description\" content=\"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/\" \/>\n<meta property=\"og:site_name\" content=\"Proud2beCloud Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-09-11T07:40:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-17T11:11:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2018\/09\/SERVERLESS_Tavola-disegno-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"4267\" \/>\n\t<meta property=\"og:image:height\" content=\"3200\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Alessandro Gaggia\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Go Serverless! Parte 1: realizziamo un\u2019applicazione Serverless di File Sharing.\" \/>\n<meta name=\"twitter:description\" content=\"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2018\/09\/SERVERLESS_Tavola-disegno-1.png\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Alessandro Gaggia\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/\",\"url\":\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/\",\"name\":\"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS - Proud2beCloud Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/#website\"},\"datePublished\":\"2018-09-11T07:40:19+00:00\",\"dateModified\":\"2021-03-17T11:11:46+00:00\",\"author\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/f27fc12d10867c6ea6e0158ce4dd8924\"},\"description\":\"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.besharp.it\/it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.besharp.it\/it\/#website\",\"url\":\"https:\/\/blog.besharp.it\/it\/\",\"name\":\"Proud2beCloud Blog\",\"description\":\"il blog di beSharp\",\"alternateName\":\"Proud2beCloud Blog\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.besharp.it\/it\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"it-IT\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/f27fc12d10867c6ea6e0158ce4dd8924\",\"name\":\"Alessandro Gaggia\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/f58dc28050f26409e22ab60346d06220?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/f58dc28050f26409e22ab60346d06220?s=96&d=mm&r=g\",\"caption\":\"Alessandro Gaggia\"},\"description\":\"Head of software development di beSharp, Full-Stack developer, mi occupo di garantire lo stato dell\u2019arte di tutta la nostra codebase. Scrivo codice in quasi ogni linguaggio, ma prediligo Typescript. Respiro Informatica, Game design, Cinema, Fumetti e buona cucina. Disegno per passione!\",\"url\":\"https:\/\/blog.besharp.it\/it\/author\/alessandro-gaggia\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS - Proud2beCloud Blog","description":"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/","og_locale":"it_IT","og_type":"article","og_title":"Go Serverless! Parte 1: realizziamo un\u2019applicazione Serverless di File Sharing.","og_description":"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.","og_url":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/","og_site_name":"Proud2beCloud Blog","article_published_time":"2018-09-11T07:40:19+00:00","article_modified_time":"2021-03-17T11:11:46+00:00","og_image":[{"width":4267,"height":3200,"url":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2018\/09\/SERVERLESS_Tavola-disegno-1.png","type":"image\/png"}],"author":"Alessandro Gaggia","twitter_card":"summary_large_image","twitter_title":"Go Serverless! Parte 1: realizziamo un\u2019applicazione Serverless di File Sharing.","twitter_description":"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.","twitter_image":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2018\/09\/SERVERLESS_Tavola-disegno-1.png","twitter_misc":{"Scritto da":"Alessandro Gaggia","Tempo di lettura stimato":"6 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/","url":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/","name":"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS - Proud2beCloud Blog","isPartOf":{"@id":"https:\/\/blog.besharp.it\/it\/#website"},"datePublished":"2018-09-11T07:40:19+00:00","dateModified":"2021-03-17T11:11:46+00:00","author":{"@id":"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/f27fc12d10867c6ea6e0158ce4dd8924"},"description":"Go Serverless! Parte 1 - realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS: analisi dei servizi AWS utilizzati.","breadcrumb":{"@id":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.besharp.it\/it\/go-serverless-pt1\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.besharp.it\/it\/"},{"@type":"ListItem","position":2,"name":"Go Serverless! Parte 1: realizziamo un\u2019applicazione di File Sharing basata sui servizi di AWS"}]},{"@type":"WebSite","@id":"https:\/\/blog.besharp.it\/it\/#website","url":"https:\/\/blog.besharp.it\/it\/","name":"Proud2beCloud Blog","description":"il blog di beSharp","alternateName":"Proud2beCloud Blog","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.besharp.it\/it\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"it-IT"},{"@type":"Person","@id":"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/f27fc12d10867c6ea6e0158ce4dd8924","name":"Alessandro Gaggia","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/f58dc28050f26409e22ab60346d06220?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f58dc28050f26409e22ab60346d06220?s=96&d=mm&r=g","caption":"Alessandro Gaggia"},"description":"Head of software development di beSharp, Full-Stack developer, mi occupo di garantire lo stato dell\u2019arte di tutta la nostra codebase. Scrivo codice in quasi ogni linguaggio, ma prediligo Typescript. Respiro Informatica, Game design, Cinema, Fumetti e buona cucina. Disegno per passione!","url":"https:\/\/blog.besharp.it\/it\/author\/alessandro-gaggia\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/posts\/274"}],"collection":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/comments?post=274"}],"version-history":[{"count":0,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/posts\/274\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/media\/361"}],"wp:attachment":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/media?parent=274"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/categories?post=274"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/tags?post=274"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}