{"id":1332,"date":"2020-04-17T13:15:22","date_gmt":"2020-04-17T11:15:22","guid":{"rendered":"https:\/\/blog.besharp.it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/"},"modified":"2021-03-17T15:14:12","modified_gmt":"2021-03-17T14:14:12","slug":"come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere","status":"publish","type":"post","link":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/","title":{"rendered":"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere"},"content":{"rendered":"

Al momento il paradigma Serverless<\/strong> \u00e8 uno delle modalit\u00e0 pi\u00f9 diffuse di implementazione di nuove applicazioni sia Web based che Mobile<\/strong>. Diversamente dall’architettura classica in cui il back-end \u00e8 esposto da uno o pi\u00f9 server Web costantemente connessi al database, il back-end di un’applicazione Serverless<\/strong> viene in genere distribuito utilizzando servizi FaaS<\/strong> (Function as a Service<\/strong>) e il database \u00e8 di solito uno dei nuovi database NoSQL gestiti e scalabili, che possono essere interrogati direttamente utilizzando chiamate API HTTPS.\u00a0<\/span><\/p>\n

Su Amazon Web Services un’architettura come questa \u00e8 in genere implementata utilizzando AWS Lambda<\/a> Functions (FaaS) e DynamoDB (database NoSQL). Se \u00e8 necessario un database SQL (ad es. per strutture dati complesse e\/o fortemente gerarchiche) DynamoDB pu\u00f2 essere sostituito da Aurora Serverless<\/a>, un database Postgres (e MySQL) compatibile e scalabile automaticamente, completamente gestito da AWS che pu\u00f2 anche essere interrogato tramite chiamate API HTTPS utilizzando il nuovo servizio AWS RDS DataApis<\/a>.<\/span><\/p>\n

In una tipica applicazione API REST<\/strong>, le funzioni Lambda sono in genere invocate tramite AWS API Gateway<\/strong> che riceve le richieste https dai client degli utenti, recupera i parametri e li inoltra alle funzioni Lambda che eseguono la logica di business e infine restituiscono una risposta all’API Gateway che pu\u00f2 ulteriormente modificarla e decorarla, prima di rispondere al client. In questa configurazione, l’autenticazione<\/strong> degli utenti viene spesso gestita tramite AWS Cognito che \u00e8 un servizio di registrazione, accesso e controllo degli accessi gestito da AWS. Se si utilizza Cognito, API Gateway pu\u00f2 essere configurato per inoltrare le richieste alle funzioni Lambda<\/strong> solo se sono fornite di un token JWT di Cognito valido nell’header Authorization: la funzione Lambda dovr\u00e0 poi occuparsi di gestire l’autorizzazione dell’utente (questo utente ha il permesso di eseguire questa azione su quella risorsa?) ricavando l\u2019identit\u00e0 dell\u2019utente e\/o i suoi permessi dal token JWT di Cognito.\u00a0<\/span><\/p>\n

A volte potrebbe essere utile chiamare l’API Gateway utilizzando l’autenticazione AWS IAM (tramite Cognito Identity Pools) anzich\u00e9 l’autenticazione Cognito di base: in questo modo, le APIs della nostra applicazione saranno protette dallo stesso algoritmo di firma IAM v4 estremamente sicuro utilizzato da AWS per proteggere le proprie API: tutte le chiamate HTTPS ai servizi di AWS (ad es. S3, SQS, ecc.) sono firmate usando questo algoritmo. Inoltre, utilizzando l’associazione tra i gruppi di Cognito e i ruoli IAM, possiamo eseguire diversi tipi di autorizzazione di base direttamente a livello di API Gateway e non verr\u00e0 nemmeno addebitato alcun costo per richieste non autorizzate!<\/span><\/p>\n

 <\/p>\n

\"Sketch
Sketch of a typical AWS serverless application<\/figcaption><\/figure>\n

Questi tipi di configurazione sono ormai estremamente comuni e sono stati ampiamente discussi in questo blog, tuttavia non ci siamo mai occupati dell\u2019altro tipo di integrazioni con il backend delle applicazioni moderne: GraphQL.<\/strong><\/span><\/p>\n

GraphQL \u00e8 un paradigma relativamente nuovo introdotto da Facebook nel 2015 per gestire l’interazione tra frontend e backend.<\/strong> La sua filosofia \u00e8 significativamente diversa dal paradigma REST: mentre in una tipica applicazione RESTful utilizziamo i verbi HTTP (GET, POST, PUT, PATCH, DELETE) per definire il tipo di azione che stiamo eseguendo con una specifica chiamata API e usiamo path parameters, query parameters e il corpo della richiesta (in formato JSON) per specificare l’argomento dell’azione in corso, in GraphQL tutte le chiamate HTTP sono in realt\u00e0 chiamate POST<\/strong> al backend e il tipo di azione da eseguire \u00e8 completamente definito nel corpo della richiesta API . GraphQL definisce il suo linguaggio specifico per il body delle richieste, il quale definisce solo tre tipi di azioni: query, mutations e subscriptions.<\/strong> Le query vengono utilizzate per recuperare informazioni su un’entit\u00e0, le mutations vengono utilizzate per modificare o creare un’entit\u00e0 esistente mentre le sottoscrizioni consentono al cliente di ricevere notifiche tramite Websocket per eventi specifici (ad esempio, le mutazioni di un’entit\u00e0 eseguite da altri utenti). Contrariamente al paradigma REST, che di solito \u00e8 molto rigido, il linguaggio GraphQL \u00e8 molto pi\u00f9 dinamico e consente al frontend di richiedere direttamente le entit\u00e0 (e i singoli campi delle entit\u00e0) di cui ha bisogno senza la necessit\u00e0 che il backend gestisca direttamente il filtro: il backend deve solo essere conforme allo standard GraphQL.<\/span><\/p>\n

Solo per dare un rapido esempio di come funziona questo linguaggio supponiamo che il front-end abbia bisogno di un elenco di utenti esistenti, la richiesta sar\u00e0 simile alla seguente:<\/span><\/p>\n

query listUsers<\/span>{<\/span> \r\n    listUsers<\/span>(<\/span>\r\n        limit<\/span>:<\/span> 2<\/span>\r\n        )<\/span>\r\n        {<\/span>\r\n            items <\/span>{<\/span>\r\n                user_id<\/span>,<\/span> \r\n                email<\/span>,<\/span>\r\n            }<\/span>\r\n        }<\/span>\r\n}<\/span><\/pre>\n

Questo torner\u00e0 una lista di utenti (\u00e8 gestita anche la paginazione tramite un nextToken).<\/p>\n

{\r\n    \"data\": {\r\n        \"listUsers\": {\r\n            \"items\": [\r\n                {\r\n                    \"user_id\": \"B2EF3212E32F423E\",\r\n                    \"email\": \"test.graph@besharp.it\"\r\n                },\r\n                {\r\n                    \"user_id\": \"A2EF4512E32F45RK\",\r\n                    \"email\": \"test.full@besharp.it\"\r\n                }\r\n            ],\r\n            \"nextToken\": \"tyJ3ZXJzaW9uIjoyLCJ0b2tl\"\r\n        }\r\n    }\r\n}<\/pre>\n

Ora vogliamo creare un nuovo utente:
\nRequest:<\/p>\n

mutation createUser \r\n{\r\n    createUser(\r\n    input: \r\n    {\r\n        email: \"test@besharp.it\"\r\n    }\r\n        ) \r\n        {\r\n            user_id, \r\n            email\r\n        }\r\n    \r\n}\r\n<\/pre>\n

Questa mutazione creer\u00e0 il nuovo utente o restituir\u00e0 un’eccezione se gi\u00e0 esiste.<\/strong>
\nUno dei vantaggi di GraphQL \u00e8 che il frontend pu\u00f2 ottenere esattamente le informazioni di cui ha bisogno minimizzando il numero di chiamate API<\/strong> e il peso delle risposte: ad esempio se vogliamo solo il nome di un utente e non ci importa dell’email:
\nRequest:<\/p>\n

query getUser{ \r\n    getUser(user_id: \"A2EF4512E32F45RK\")\r\n    {\r\n        name\r\n    }\r\n}<\/pre>\n

Response:<\/p>\n

{\r\n    \"data\": {\r\n        \"getUser\": {\r\n            \"name\": \"Test Full\"\r\n        }\r\n    }\r\n}<\/pre>\n

Se invece dovessimo avere anche bisogno del suo user id:<\/p>\n

query getUser{ \r\n    getUser(user_id: \"A2EF4512E32F45RK\")\r\n    {\r\n        user_id\r\n  email\r\n        name\r\n    }\r\n}<\/pre>\n

Response:<\/p>\n

{\r\n    \"data\": {\r\n        \"getUser\": {\r\n            \"user_id\": \"A2EF4512E32F45RK\"\r\n            \"email\": \"test.full@besharp.it\",\r\n            \"name\": \"Test Full\"\r\n        }\r\n    }\r\n}<\/pre>\n

Inoltre, GraphQL \u00e8 stato sviluppato per consentire al frontend di recuperare dati da fonti eterogenee. Ad esempio, pensiamo ad un’entit\u00e0 \u2018utente\u2019 che ha anche altre propriet\u00e0 oltre a quelle finora considerate: l’utente potrebbe essere memorizzato in un database relazionale (ad esempio Aurora Serverless Postgres) ma potrebbe avere un campo GraphQL che descrive la sua localit\u00e0 geografica (con relative propriet\u00e0) che \u00e8 memorizzata in DynamoDB, inoltre a livello di GraphQL potremmo aggiungere un campo “Meteo locale” alla localit\u00e0 che recupera i dati delle previsioni meteorologiche locali da un’API di terze parti e che \u00e8 popolato a runtime quando viene eseguita una query GetUser o ListUser.<\/p>\n

Mentre le funzionalit\u00e0 del linguaggio GraphQL sono eccezionali, \u00e8 sempre stato molto difficile configurare un back-end GraphQL utilizzando il paradigma serverless prima del rilascio di AWS AppSync. Questo nuovo servizio AWS ha infatti lo stesso ruolo di API Gateway per un’applicazione RESTful: riceve le chiamate API, controlla l’Autenticazione – Autorizzazione e le inoltra alla Lambda corretta o ad altri servizi di back-end. AppSync inoltre fa ancora di pi\u00f9: \u00e8 possibile scrivere un backend personalizzato minimale utilizzando i modelli VTL (Apache Velocity) per collegare query e mutazioni direttamente alle origini dati (DynamoDB, Aurora Serverless, AWS ElasticSearch, API di terze parti). Per query e mutazioni pi\u00f9 complicate \u00e8 ovviamente necessario un backend \u2018reale\u2019 (ad es. per la crittografia custom per un campo del database). In questo caso, AppSync, proprio come Api Gateway, pu\u00f2 richiamare una funzione Lambda per eseguire le operazioni necessarie e quindi utilizzare la risposta (o le risposte) per ricostruire il JSON finale che deve essere restituito al client.<\/p>\n

\"Sketch
Sketch of a typical AWS GraphQL (AppSync) serverless application<\/figcaption><\/figure>\n

La bellezza di questo approccio \u00e8 che possiamo configurare AppSync per chiamare una funzione lambda<\/strong> ogni volta che deve popolare un campo particolare di una data entit\u00e0 oppure popolare una intera entit\u00e0. Quindi se eseguiamo una query di list, per ogni risultato restituito, una Lambda dedicata pu\u00f2 essere eseguita per valutare un campo specifico, ad esempio il campo delle previsioni del tempo personalizzate nell’esempio sopra, mentre gli altri campi proverranno direttamente dai database. Questo \u00e8 il motivo per cui la risposta sar\u00e0 sempre molto rapida<\/strong> anche per le query che richiedono un numero elevato di operazioni personalizzate, dato che tali operazioni verranno sempre parallelizzate. Va comunque tenuto conto del fatto\u00a0 che, poich\u00e9 le funzioni lambda sono fatturate per numero di esecuzione e per tempo di esecuzione totale, le query mal progettate possono comportare costi di AWS elevati ed imprevisti, perci\u00f2, in generale, \u00e8 sempre utile impiegare il tempo necessario per pianificare accuratamente la corretta query e l’utilizzo previsto delle Lambda.<\/span><\/p>\n

Sfortunatamente il prezzo da pagare per l’elevata configurabilit\u00e0 e flessibilit\u00e0 di AppSync \u00e8 la complessit\u00e0 e la \u201cverbosit\u00e0\u201d della sua configurazione:<\/strong> anche per un progetto molto semplice con una manciata di entit\u00e0 e una o due tabelle Dynamo \u00e8 infatti necessario un file di schema lungo e dettagliato che descrive tutte le entit\u00e0, le loro eventuali relazioni e come devono essere eseguite le mutazioni e le query. Inoltre, per ogni query e mutazione devono essere creati 2 file vtl (Velocity), uno per l’analisi della richiesta e uno per l’analisi dell’output. Se si desidera utilizzare una funzione lambda o una catena di funzioni lambda (risolutori di pipeline), per popolare o recuperare un campo o un’entit\u00e0, la complessit\u00e0 della configurazione aumenta in modo significativo cos\u00ec come lo sforzo necessario per mantenere e testare il progetto. Inoltre, creare e aggiornare l\u2019infrastructure as Code (IaC) di un insieme di configurazioni cos\u00ec ampio, fortemente integrato e spesso in rapida evoluzione in un modo rapido, ripetibile e affidabile pu\u00f2 essere un compito estremamente complesso.<\/span><\/p>\n

Per semplificare la gestione del progetto \u00e8 quindi necessario l’utilizzo di un framework per automatizzare la creazione delle parti banali e ripetitive<\/strong> delle configurazioni di AppSync. Il framework Serverless<\/strong><\/a> (molto diffuso) ha un plug-in AppSync dedicato<\/a>, tuttavia il suo utilizzo non \u00e8 molto pi\u00f9 semplice o pi\u00f9 veloce della creazione manuale del CloudFormation nativo per AppSync.\u00a0<\/span><\/p>\n

Ci\u00f2 che abbiamo scoperto dopo svariati test \u00e8 che una miscela di CloudFormation\/Troposphere nativi\u00a0 con il framework AWS Amplify pu\u00f2 risolvere il problema. Amplify \u00e8 una piattaforma di sviluppo per creare rapidamente applicazioni Web e Mobile utilizzando i servizi AWS Serverless<\/strong> (Lambda, API Gateway, Appsync, Dynamo, SQS, ecc.) in modo trasparente. Sebbene sia spesso troppo limitato per un’applicazione complessa del mondo reale e, in generale, pi\u00f9 che altro pensato per sviluppatori con conoscenze di AWS molto limitate che vogliono configurare rapidamente un’applicazione funzionante sfruttando i pi\u00f9 moderni servizi serverless, la sua integrazione con AppSync<\/strong> \u00e8 molto ben fatta e consente agli sviluppatori di configurare rapidamente un’integrazione GraphQL basata su DynamoDB (o Aurora) senza tutte le complessit\u00e0 e la verbosit\u00e0 descritte precedentemente. Inoltre, rende davvero semplice e facile sfruttare AWS Cognito per l\u2019autenticazione e l’autorizzazione. E se Cognito da solo non dovesse soddisfare le vostre esigenze, \u00e8 anche possibile usare la IAM authentication, tramite i Cognito Identity Pools.<\/span><\/p>\n

Ecco come abbiamo creato un back-end AppSync con Amplify e CloudFormation<\/strong> in modo rapido, affidabile e facilmente gestibile: prima di tutto \u00e8 necessario installare Amplify Cli come descritto nella documentazione di Amplify<\/a>. Dopo aver fatto ci\u00f2, \u00e8 possibile seguire la guida e continuare a la creazione di un progetto Amplify in una cartella dedicata tramite i comandi:<\/span><\/p>\n

amplify configure\r\namplify init\r\namplify add api -> choose GraphQL<\/pre>\n

Tutti i comandi sono interattivi: scegli le opzioni pi\u00f9 adatte alle tue esigenze! Dopo aver creato il progetto GraphQL api sar\u00e0 necessario modificare il file schema.graphql<\/strong> nella cartella api\/backend\/: questo \u00e8 l’unico file che \u00e8 necessario modificare se l’applicazione non ha bisogno di integrazioni complicate! La sintassi di questo file \u00e8 quella del linguaggio GraphQL con alcune annotazioni<\/a> personalizzate di Amplify. Utilizzando queste annotazioni \u00e8 possibile definire quali entit\u00e0 sone tabella Dynamo, creare Global Secondary Indexes, connessioni ad altre tabelle, campi personalizzati che usano le lambda come data source, impostare il livello di autorizzazione per ciascuna entit\u00e0 usando il token JWT di Cognito e molto altro ancora!
\nQuando si \u00e8 soddisfatti della propria configurazione di GraphQL \u00e8 possibile eseguire:<\/p>\n

amplify push<\/pre>\n

E Amplify creer\u00e0 ed eseguir\u00e0 i template CloudFormation per creare o aggiornare AppSync!<\/strong><\/p>\n

Nonostante le varie opzioni disponibili in Amplify GraphQL nel caso di progetti complessi, probabilmente sar\u00e0 necessario usare alcune funzionalit\u00e0 di AppSync non presenti di default tuttavia questo non \u00e8 un problema: quando si esegue amplify push viene generata una cartella di build<\/strong> (.gitignored) e contiene la versione corrente di cloudFormation, tuttavia esiste anche una cartella api\/backend \/\/ stacks che contiene un cloudFormation json (CustomResources.json) senza risorse: \u00e8 possibile aggiungere qui ulteriori risorse<\/a> custom. \u00c8 anche possibile usare Troposphere<\/strong><\/a> per creare questo file, sfruttando cos\u00ec le funzionalit\u00e0 avanzate di Python nella creazione del modello CloudFormation. Nel caso fossero anche necessari anche file VTL personalizzati \u00e8 possibile aggiungerli<\/a> alla cartella api\/backend\/\/resolvers.<\/p>\n

Dopo l’entusiasmo iniziale dei primi rilasci di solito iniziano tuttavia ad emergere i problemi legati all\u2019uso di Amplify. Infatti \u00e8 necessario mantenere vari componenti diversi: il file schema.graphql; la configurazione CloudFormation\/Troposphere per le risorse personalizzate e i file VTL custom. Se si \u00e8 scelto di usare Troposphere sar\u00e0 anche necessario ricordare di eseguire lo script per creare i file yml di CloudFormation prima di eseguire amplify push.<\/p>\n

Sono perci\u00f2 necessari ulteriori passaggi di automazione:<\/strong> la soluzione pi\u00f9 elegante \u00e8 certamente la creazione di una pipeline<\/strong> (AWS CodePipeline) per eseguire il deploy della nostra applicazione GraphQL. La Source della pipeline pu\u00f2 essere il repository AWS CodeCommit del progetto Amplify, oppure qualsiasi altro repository git (GitHub e Bitbucket sono supportati di default mentre altre configurazioni git lo sono tramite integrazioni custom).
\nPer far ci\u00f2 iniziamo ripulendo tutto ci\u00f2 che Amplify ha creato nel nostro account. Ricreeremo tutto da zero senza usare amplify push. Le risorse da eliminare sono gli stack Amplify di CloudFormation, i bucket S3 relativi all’amplificazione e l’applicazione Amplify nella console di AWS Amplify.<\/p>\n

Dopo aver pulito l\u2019account AWS si pu\u00f2 rimuovere tutto dal progetto, esclusa la cartella backend mentre il file team-provider-info.json dovrebbe essere riempito con un json vuoto (basta scrivere {}). Ora \u00e8 possibile creare un file buildspec.yml nella directory principale che verr\u00e0 utilizzato da AWS CodeBuild:<\/p>\n

version: '0.2'\r\nphases:\r\n    install:\r\n        runtime-versions:\r\n            python: 3.7\r\n            nodejs: 12\r\n        commands:\r\n            - npm install -g @aws-amplify\/cli\r\n            - pip install -r requirements.txt\r\n    build:\r\n        commands:\r\n            - echo \"{ \\\"projectPath\\\": \\\"$(pwd)\\\", \\\"envName\\\": \\\"${ENVIRONMENT}\\\"}\" > amplify\/.config\/local-env-info.json\r\n            - amplify api gql-compile<\/pre>\n

Questi comandi creeranno i file di CloudFormation e i VTL<\/strong> nella cartella build senza eseguirli. A questo punto sar\u00e0 solo necessario aggiungere al codebuild config la variabile ENVIRONMENT che identifica l’ambiente per cui stiamo eseguendo la build e utilizzare il file principale di CloudFormation nella cartella build come output di codebuild (build\/cloudformation-template.json). Nel caso si stia usando Troposphere \u00e8 anche necessario aggiungere uno step aggiuntivo per compilare Python in CloudFormation. Bisogna infine caricare gli altri modelli di CloudFormation e i file VTL in un bucket S3 di propria scelta.
\nIl flusso \u00e8 quello mostrato nell’immagine seguente:<\/p>\n

\"\"<\/p>\n

L’ultimo passaggio della CodePipeline consiste nell’eseguire il modello di CloudFormation<\/strong> (output di codebuild) in uno step di deploy dedicato. CloudFormation si occuper\u00e0 di scaricare gli altri template da s3 e di eseguirli come stack nested.<\/span><\/p>\n

Ora hai il tuo progetto GraphQL personalizzato, configurabile e facilmente gestibile<\/strong> supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!<\/span><\/p>\n

Se ti \u00e8 piaciuta questa soluzione e desideri avere ulteriori dettagli, non esitare a scrivere nei commenti o a contattarci<\/a>!<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"

Al momento il paradigma Serverless \u00e8 uno delle modalit\u00e0 pi\u00f9 diffuse di implementazione di nuove applicazioni sia Web based che […]<\/p>\n","protected":false},"author":9,"featured_media":1324,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[481],"tags":[283,356,275,285,271,287,267],"yoast_head":"\nCome gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere - Proud2beCloud Blog<\/title>\n<meta name=\"description\" content=\"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!\" \/>\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\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/\" \/>\n<meta property=\"og:locale\" content=\"it_IT\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere\" \/>\n<meta property=\"og:description\" content=\"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!\" \/>\n<meta property=\"og:url\" content=\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/\" \/>\n<meta property=\"og:site_name\" content=\"Proud2beCloud Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-04-17T11:15:22+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-03-17T14:14:12+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2020\/04\/copertine-blog-Appsync-32.png\" \/>\n\t<meta property=\"og:image:width\" content=\"834\" \/>\n\t<meta property=\"og:image:height\" content=\"625\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Matteo Moroni\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:title\" content=\"Gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere\" \/>\n<meta name=\"twitter:description\" content=\"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/blog.besharp.it\/wp-content\/uploads\/2020\/04\/copertine-blog-Appsync-32.png\" \/>\n<meta name=\"twitter:label1\" content=\"Scritto da\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matteo Moroni\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tempo di lettura stimato\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minuti\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/\",\"url\":\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/\",\"name\":\"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere - Proud2beCloud Blog\",\"isPartOf\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/#website\"},\"datePublished\":\"2020-04-17T11:15:22+00:00\",\"dateModified\":\"2021-03-17T14:14:12+00:00\",\"author\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/0b3e69eb2dcb125d58476b906ec1c7bc\"},\"description\":\"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!\",\"breadcrumb\":{\"@id\":\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/#breadcrumb\"},\"inLanguage\":\"it-IT\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.besharp.it\/it\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere\"}]},{\"@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\/0b3e69eb2dcb125d58476b906ec1c7bc\",\"name\":\"Matteo Moroni\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"it-IT\",\"@id\":\"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/acad790b9bb4c6d62e076ecdc1debb35?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/acad790b9bb4c6d62e076ecdc1debb35?s=96&d=mm&r=g\",\"caption\":\"Matteo Moroni\"},\"description\":\"DevOps e Solution Architect di beSharp, mi occupo di sviluppare soluzioni Saas, Data Analysis, HPC e di progettare architetture non convenzionali a complessit\u00e0 divergente. Appassionato di informatica e fisica, da sempre lavoro nella prima e ho un PhD nella seconda. Parlare di tutto ci\u00f2 che \u00e8 tecnico e nerd mi rende felice!\",\"url\":\"https:\/\/blog.besharp.it\/it\/author\/matteo-moroni\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere - Proud2beCloud Blog","description":"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!","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\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/","og_locale":"it_IT","og_type":"article","og_title":"Gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere","og_description":"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!","og_url":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/","og_site_name":"Proud2beCloud Blog","article_published_time":"2020-04-17T11:15:22+00:00","article_modified_time":"2021-03-17T14:14:12+00:00","og_image":[{"width":834,"height":625,"url":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2020\/04\/copertine-blog-Appsync-32.png","type":"image\/png"}],"author":"Matteo Moroni","twitter_card":"summary_large_image","twitter_title":"Gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere","twitter_description":"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!","twitter_image":"https:\/\/blog.besharp.it\/wp-content\/uploads\/2020\/04\/copertine-blog-Appsync-32.png","twitter_misc":{"Scritto da":"Matteo Moroni","Tempo di lettura stimato":"12 minuti"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/","url":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/","name":"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere - Proud2beCloud Blog","isPartOf":{"@id":"https:\/\/blog.besharp.it\/it\/#website"},"datePublished":"2020-04-17T11:15:22+00:00","dateModified":"2021-03-17T14:14:12+00:00","author":{"@id":"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/0b3e69eb2dcb125d58476b906ec1c7bc"},"description":"Realizziamo un progetto GraphQL personalizzato, configurabile e gestibile supportato da Appsync e Dynamo e deployato con Amplify e CloudFormation!","breadcrumb":{"@id":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/#breadcrumb"},"inLanguage":"it-IT","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.besharp.it\/it\/come-gestire-un-app-graphql-su-aws-usando-appsync-amplify-e-troposphere\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.besharp.it\/it\/"},{"@type":"ListItem","position":2,"name":"Come gestire un App GraphQL su AWS usando AppSync Amplify e Troposphere"}]},{"@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\/0b3e69eb2dcb125d58476b906ec1c7bc","name":"Matteo Moroni","image":{"@type":"ImageObject","inLanguage":"it-IT","@id":"https:\/\/blog.besharp.it\/it\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/acad790b9bb4c6d62e076ecdc1debb35?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/acad790b9bb4c6d62e076ecdc1debb35?s=96&d=mm&r=g","caption":"Matteo Moroni"},"description":"DevOps e Solution Architect di beSharp, mi occupo di sviluppare soluzioni Saas, Data Analysis, HPC e di progettare architetture non convenzionali a complessit\u00e0 divergente. Appassionato di informatica e fisica, da sempre lavoro nella prima e ho un PhD nella seconda. Parlare di tutto ci\u00f2 che \u00e8 tecnico e nerd mi rende felice!","url":"https:\/\/blog.besharp.it\/it\/author\/matteo-moroni\/"}]}},"_links":{"self":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/posts\/1332"}],"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\/9"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/comments?post=1332"}],"version-history":[{"count":0,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/posts\/1332\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/media\/1324"}],"wp:attachment":[{"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/media?parent=1332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/categories?post=1332"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.besharp.it\/it\/wp-json\/wp\/v2\/tags?post=1332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}