[ITA] Primi passi con le Azure Functions
Tags: azure, azurefunctions, serverless
Published: 2021-12-16 07:33:16

Le **Azure Functions** sono una soluzione di **serverless computing** fornita da Azure, consentono l'esecuzione di codice in cloud senza il provisioning dell'infrastruttura.

Le funzioni possono essere scritte usando **diversi linguaggi di programmazione:** C#, Java, JavaScript, PowerShell, Python, Typescript, Rust e Go.

Il codice viene eseguito in risposta a diversi  tipi di evento detti **trigger** come ad esempio una chiamata http utilizzando **HttpTrigger**, all'arrivo di un nuovo messaggio in uno dei sistemi di code di Azure, alla creazione di un blob o in base ad un intervallo di tempo prestabilito.

In [questa pagina](https://azure.microsoft.com/it-it/services/functions) della documentazione di Microsoft si possono trovare tutti i trigger utilizzabili nel servizio.

E' possibile sviluppare le Azure Functions tramite **Visual Studio** e **Visual Studio Code.**

Lo scopo di questo articolo è quello di creare il setup minimo allo sviluppo di una funzione di "Hello World" come mia reference futura e come aiuto a chi dovesse utilizzare per la prima volta questo servizio di Azure.
# Setup ambiente di sviluppo

Per questo tutorial utilizerò **Visual Studio Code** e **Typescript**, la funzione avrà un **trigger http** ed eseguirà una chiamata http per recuperare il prezzo attuale di BTC da restituire al chiamante.

## Prerequisiti

- Una subscription ad Azure (Esiste anche un piano gratuito ottimo per provare i servizi di Azure)
- Visual Studio Code
- nodejs con versione ≥ 14
- Estensione "[Azure Functions](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions)" di VS Code
- [Azure Functions Core Tools](https://docs.microsoft.com/it-it/azure/azure-functions/functions-run-local?tabs=v4%2Cwindows%2Ccsharp%2Cportal%2Cbash%2Ckeda#install-the-azure-functions-core-tools)

## Creazione del servizio su Azure

Dal portale di Azure creare una nuova risorsa di tipo "**Function App**".

![Creazione risorsa portale azure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h5v3m3jkolteogqdft5b.png)

Cliccare su "**Create**" e popolare i campi richiesti scegliendo la propria **subscription** e un **resource group** al quale associare la nuova risorsa. 

I resource group non sono altro che contenitori di risorse.

Volendo creare la funzione in Typescript scelgo come runtime di esecuzione Node.js.

A questo punto è possibile spostarsi sulla tab successiva "Hosting".

Per poter funzionare, il servizio, ha necessità di uno spazio di archiviazione in questa tab è possibile selezionarne uno già esistente o crearne uno nuovo dedicato, in questo caso ne creerò uno dedicato.

Come sistema operativo si può anche lasciare il default (Windows) ma in questo caso scelgo linux e come piano "**Consumption**".

Non è scopo di questa guida approfondire i piani di Azure Functions ma la scelta serverless in generale consente di non avere costi fissi ma pagare solo a consumo, ha inoltre una quota gratuita piuttosto consistente. 

Unica pecca è il cold start che in alcuni casi può essere penalizzante. Il piano serverless infatti non prevede una funzione sempre attiva e pronta a gestire le richieste in ingresso, può quindi capitare che il primo avvio di una funzione sia piuttosto lento.

[Maggiori informazioni qui](https://azure.microsoft.com/en-us/blog/understanding-serverless-cold-start/)

![Creazione Function App 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1bm98dzzi7lnmzsnul0k.png)

![Creazione Function App 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pdn9yapxlzs8fod08pa9.png)

![Creazione Function App 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ekni26gbaurxpe5hbkjg.png)

## Connettere VS Code

Tramite le estensioni di VS Code "**Azure Tools**" e "**Azure Functions**" è possibile autenticarsi ad **Azure** di modo da gestire il deploy delle proprie funzioni direttamente dall'IDE.

Cliccare sull'icona dell'estensione, spostarsi nella sezione **FUNCTIONS** scegliere "Sign In".

Una volta autenticati dovrebbe essere visibile il servizio di Azure Functions creato al punto precedente.

![Autenticazione estensione Azure su VS Code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/otqfclyvjq0pae7odlwk.png)

# Creazione progetto

Tramite le estensioni è possibile creare il progetto direttamente da VS Code.

![Creazione progetto Azure Function da VS Code 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kw1zvoyb7cfrnsgcbp5l.png)

![Creazione progetto Azure Function da VS Code 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqevfnepj2i13l5jc2ev.png)

Scegliere **Typescript**, allo step successivo verrà richiesta la tipologia di trigger. Scegliere **Http trigger.**

![Creazione progetto Azure Function da VS Code 3](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cp2w0ro90z3rzw08t9ld.png)

Negli step successivi scegliere:

**Function Name:** HttpTriggerPrice

**Authorization Level:** Function

**Open Project:** Open in current window

Il tipo di autorizzazione "Function" forza l'esecuzione alle sole richieste autenticate tramite una chiave specifica generata dal portale. 

[Maggiori informazioni qui.](https://docs.microsoft.com/en-us/azure/azure-functions/security-concepts)

A questo punto il progetto è pronto per essere editato.

Lanciare il comando per installare le dipendenze.

```bash
npm install
```

# Sviluppo funzione

La cli di Azure durante lo scaffolding del progetto crea una funzione di **Hello World**

```tsx
import { AzureFunction, Context, HttpRequest } from "@azure/functions"

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    context.log('HTTP trigger function processed a request.');
    const name = (req.query.name || (req.body && req.body.name));
    const responseMessage = name
        ? "Hello, " + name + ". This HTTP triggered function executed successfully."
        : "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";

    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };

};

export default httpTrigger;
```

E' possibile eseguire la funzione facendo il deploy sul servizio di Azure ma la **cli** contiene anche un emulatore che rispecchia esattamente il comportamento del servizio in cloud dando la possibilità di sviluppare localmente e offline.

## Avviare l'emulatore locale

Per avviare l'emulatore è sufficiente lanciare il comando 

```bash
npm start
```

Nel package.json il comando è associato al seguente comando della cli

```bash
func start
```

All'avvio nel terminale viene visualizzato l'endpoint locale utilizzabile per testare la funzione.

![Output terminale emulatore azure functions](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g09u4lt4e43egt35pnt3.png)

Visitando il link con [Postman](https://www.postman.com/) o con il browser la funzione risponderà con un messaggio.

## Recuperare il prezzo di BTC ed esporlo tramite la funzione

Come detto in precedenza andremo a consumare un API terza per recuperare il prezzo attuale di BTC.

Per questo breve esempio utilizzeremo le api pubbliche di **CoinGeko.**

Come prima cosa dobbiamo installare una libreria che ci consenta di gestire in modo semplice le chiamate http, io uso [axios](https://axios-http.com/).

```bash
npm install axios
```

L'endpoint che richiameremo è:

```jsx
https://api.coingecko.com/api/v3/exchange_rates
```

Questa API è pubblica e fornisce il prezzo di bitcoin in relazione ad altre monete, nel nostro caso in relazione al valore di USD.

L'api risponde con un json di questo tipo:

```jsx
{"rates":{ 
	"btc":{"name":"Bitcoin","unit":"BTC","value":1.0,"type":"crypto"},
  "eth":{"name":"Ether","unit":"ETH","value":12.486,"type":"crypto"},
  "ltc":{"name":"Litecoin","unit":"LTC","value":271.838,"type":"crypto"},
  "usd":{"name":"US Dollar","unit":"$","value":58870.611,"type":"fiat"},
	...
}}
```

Una volta recuperati i dati dovremo quindi accedere alla sezione "usd" e scegliere il campo "value".

A questo punto il codice della funzione potrebbe diventare simile al seguente:

```jsx
import { AzureFunction, Context, HttpRequest } from "@azure/functions"
import axios from "axios";

const httpTrigger: AzureFunction = async function (context: Context, req: HttpRequest): Promise<void> {
    const apiEndpoint = `https://api.coingecko.com/api/v3/exchange_rates`;
    const request = await axios.get(apiEndpoint);
    const data = request.data;
    const usdValue = data?.rates["usd"]?.value;
    const responseMessage = usdValue;
    context.res = {
        // status: 200, /* Defaults to 200 */
        body: responseMessage
    };

};

export default httpTrigger;
```

Lo so lo so, questo codice non è pronto per la produzione 😅 ma rende l'idea di quello che si può fare con le funzioni. Da qui si può aggiungere gestione dell'errore, eventuali autenticazioni, interazioni con altri servizi, calcoli e così via...

# Deploy

Eseguire il deploy utilizzando VS Code è davvero un'operazione semplicissima. Dalla tab dell'estensione dedicata ai servizi Azure si può selezionare la propria funzione locale e cliccare su "Deploy to Function App" e seguire il wizard di deploy selezionando la subscription e il servizio function app creato in precedenza.

A questo punto la funzione dovrebbe essere stata rilasciata in cloud! 🥳

Dal portale di Azure, nella function app è possiibile selezionare la nostra funzione e recuperare l'URL per effettuare qualche test.

![Visualizzare la azure function tramite il portale di Azure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hx3n7iz31e5qy6t6nnnf.png)

Cliccare sulla funzione e poi su Get Function Url.

![Recuperare il link alla funzione dal portale di Azure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ta4gwzl46kv722am1t73.png)
 

Provare il link nel browser e il gioco è fatto.

> Notare che l'url copiato contiene un codice che è la function key utilizzata per l'autenticazione.
[Più informazioni qui](https://docs.microsoft.com/it-it/azure/azure-functions/security-concepts)
> 

L'argomento Azure Functions non finisce qui, ci sarebbe molto altro da coprire, dall'autenticazione al monitoring, alle diverse tipologie di trigger ecc..

Spero comunque che questi appunti possano essere utili a prendere dimestichezza con il servizio.