Övning – Anslut Express.js till Azure Database for PostgreSQL

Slutförd

Den här övningen beskriver hur du skapar och konfigurerar en Express.js-baserad webbtjänst som ger åtkomst till Azure Database for PostgreSQL.

I den här övningen kommer du att:

  • Skapa en Exempelwebbapp för Node.js Express.
  • Anslut Node.js Express-webbappen till Azure Database for PostgreSQL.
  • Konfigurera Node.js Express-vägar för åtkomst till Azure Database for PostgreSQL.
  • Verifiera funktionerna i Node.js Express-webbtjänsten.

Förutsättningar

För att utföra den här övningen behöver du:

  • En Azure-prenumeration
  • Ett Microsoft-konto eller ett Microsoft Entra-konto med rollen Global administratör i Microsoft Entra-klientorganisationen som är associerad med Azure-prenumerationen och med rollen Ägare eller Deltagare i Azure-prenumerationen.
  • För att ha slutfört den första övningen i den här modulen. Du använder Azure PostgreSQL-databasen som du skapade och konfigurerade i den övningen.

Skapa en Exempelwebbapp för Node.js Express

Du börjar med att skapa en Node.js Express-exempelwebbapp och tillämpa inkrementella ändringar för att implementera önskade funktioner.

  1. Om det behövs startar du en webbläsare från datorn, går till Azure-portalen och loggar in för att komma åt den Azure-prenumeration som du använde i den första övningen i den här modulen.

  2. I Azure-portalen startar du en Bash-session i Cloud Shell genom att välja dess ikon i verktygsfältet bredvid söktextrutan.

  3. I Bash-sessionen i Cloud Shell-fönstret kör du följande kommandon för att initiera ett Node.js-projekt i en ny katalog:

    mkdir -p cna-express && cd cna-express
    npm init -y
    

    Kommentar

    Då skapas en package.json som innehåller alla beroenden för projektet.

  4. Kör följande kommando för att lägga till Express.js som projektets beroende:

    npm install express
    
  5. Kör följande kommando för att skapa en fil med namnet index.js i mappen can-express :

    touch ./index.js
    
  6. Kör följande kommando för att öppna den nyligen skapade filen index.js i kodredigeraren :

    code index.js
    
  7. Använd kodredigeraren för att lägga till följande innehåll i index.js-filen och spara filen:

    const express = require('express')
    const port = process.env.PORT || 8080
    const app = express()
    app.use(express.json());
    app.listen(port, () => console.log(`Sample app is listening on port ${port}!`))
    

    Kommentar

    Om du vill spara en fil i kodredigeraren använder du tangentkombinationen ctrl+s . Om du vill stänga redigeringsfönstret använder du tangentkombinationen ctrl+q eller menyn till höger i fönstret.

    Skriptet anropar appen och konfigurerar den så att den lyssnar på TCP-port 8080 och accepterar den JSON-formaterade brödtexten för HTTP-begäranden. Från och med Express 4.16+, app.use(express.json()) krävs för JSON-parsning.

    Användningen av process.env.PORT är specifik för containrar i Azure App Service, som anger miljövariabeln PORT i Node.js-containern och skickar inkommande begäranden till det portnumret. För att ta emot begäranden bör appen lyssna på den porten med hjälp av process.env.PORT (därav användningen av const port = process.env.PORT || 8080).

    Kommentar

    Du använder Azure App Service i den här övningen för att underlätta testning av Node.js Express-funktionerna. Du kan också containerisera appen och distribuera den med Kubernetes och AKS enligt vad som visades i en tidigare modul.

  8. Om du vill tillåta att skriptet körs använder du kodredigeraren för att ändra den automatiskt genererade package.json-filen genom att ersätta dess befintliga innehåll med följande innehåll:

    {
      "name": "node-express",
      "version": "1.0.0",
      "description": "Node.js express sample",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "start": "nodemon index.js"
      },
      "author": "",
      "license": "ISC",
      "dependencies": {
        "body-parser": "^1.19.0",
        "express": "^4.17.1",
        "http": "0.0.0",
        "morgan": "^1.10.0"
      },
      "devDependencies": {
        "nodemon": "^2.0.2"
      }
    }
    

Anslut Node.js Express-webbappen till Azure Database for PostgreSQL

Därefter konfigurerar du den nyligen skapade Node.js Express-webbappen så att den ansluter till den cnainventory-databas som du skapade i föregående övning i den här modulen. För att göra detta använder du Sequelize, som är ett populärt JavaScript-bibliotek som tillhandahåller objektrelationsmappningsfunktionen, så att du kan mappa programmatiska konstruktioner till motsvarande databasschema.

  1. Från datorn går du till webbläsarfönstret som visar Azure-portalen i Bash-sessionen i Cloud Shell-fönstret och kör följande kommando för att lägga till Sequelize och motsvarande PostgreSQL-specifika paket i projektet:

    npm i sequelize pg pg-hstore
    
  2. Om du vill dra nytta av dessa nya funktioner använder du kodredigeraren för att lägga till följande rad i början av filen index.js :

    const Sequelize = require('sequelize')
    
  3. För att upprätta en anslutning till databasen måste du lägga till en anslutningssträng i det sequalize-specifika formatet i filen index.js efter raden du lade till i föregående steg. <server_name> Ersätt platshållaren med namnet på den Azure Database for PostgreSQL-server som du etablerade i föregående övning:

    const sequelize = new Sequelize('postgres://Student%40<server_name>:Pa55w0rd1234@<server_name>.postgres.database.azure.com:5432/cnainventory')
    

    Kommentar

    Användningen av %40 som escape-tecken mellan användarnamnet och servernamnet är specifikt för anslutningssträng för Azure Database for PostgreSQL.

  4. Med Sequelize-paketet inkluderat som ett krav och anslutningssträng konfigurerat kan du nu upprätta en anslutning till cnainventory-databasen genom att lägga till följande kod i filen index.js efter den som du lade till i föregående steg:

    sequelize
    .authenticate()
    .then(() => {
       console.log('Connection has been established successfully.');
    })
    .catch(err => {
       console.error('Unable to connect to the database:', err);
    });
    
  5. För att underlätta åtgärderna i inventeringstabellen som du skapade i föregående övning måste du lägga till i filen index.js, efter koden som du lade till i föregående steg, en Sequelize-specifik definition som matchar tabellformatet enligt nedan:

    const Inventory = sequelize.define('inventory', {
       id: { type: Sequelize.INTEGER, allowNull: false, primaryKey: true },
       name: { type: Sequelize.STRING, allowNull: false },
       quantity: { type: Sequelize.INTEGER },
       date: { type: Sequelize.DATEONLY, defaultValue: Sequelize.NOW }
    }, {
       freezeTableName: true,
       timestamps: false
    });
    

    Kommentar

    Alternativet timestamps: false krävs för att undanta en uppsättning tidsrelaterade kolumner från databasåtgärdernas omfång, som i det här fallet inte finns. Alternativet freezeTableName: true inaktiverar standardbeteendet för Sequelize, som automatiskt omvandlar alla modellnamn till plural.

Konfigurera Node.js Express-vägar för åtkomst till Azure Database for PostgreSQL

Nu är du redo att konfigurera de vägar som ger läs- och skrivåtkomst till inventeringstabellen i cnainventory-databasen som hanteras av Azure Database for PostgreSQL-servern. För enkelhetens skull implementerar du bara två vägar, men proceduren för att konfigurera andra vägar liknar den implementering som du går igenom i den här uppgiften. Med den första vägen kan du lägga till enskilda inventeringsobjekt genom att anropa en HTTP POST-begäran med de lagerartikelvärden som ingår i begärandetexten, medan den andra vägen bearbetar HTTP GET-begäranden och returnerar en inventeringsartikel baserat på värdet för dess ID-attribut .

  1. Från datorn i webbläsarfönstret som visar Azure-portalen, i Bash-sessionen i Cloud Shell-fönstret, använder du kodredigeraren för att lägga till följande innehåll i slutet av filen index.js:

    app.post('/inventory', async (req, res) => {
    try {
       const newItem = new Inventory(req.body)
       await newItem.save()
       res.json({ inventory: newItem })
    } catch(error) {
       console.error(error)
    }})
    

    Kommentar

    Den här delen av skriptet hanterar HTTP POST-begäranden och lägger till en rad i inventeringstabellen som är ifylld med värdena för id-, namn- och kvantitetsattribut som ingår i begärandetexten. Värdet för datumattributet beräknas automatiskt baserat på det aktuella datumet. Åtgärden returnerar de nyligen tillagda värdena som en bekräftelse på en lyckad åtgärd.

  2. I kodredigeraren lägger du till följande innehåll i filen index.js efter skriptet som du lade till i föregående steg:

    app.get('/inventory/:id', async (req, res) => {
       const id = req.params.id
       try {
          const inventory = await Inventory.findAll({
          attributes: ['id', 'name', 'quantity', 'date'],
          where: {
             id: id
          }})
          res.json({ inventory })
       } catch(error) {
           console.error(error)
    }})
    

    Kommentar

    Den här delen av skriptet hanterar HTTP GET-begäranden och returnerar värdena för attributen id, namn, kvantitet och datum baserat på värdet för ID som ingår i begäran.

    Kommentar

    Detta ger ett fullt fungerande skript i följande format (om du tänker kopiera den här koden måste du ersätta varje förekomst av cnapostgresqldb namnet med namnet på PostgreSQL-servern):

    const Sequelize = require('sequelize')
    const sequelize = new Sequelize('postgres://Student%40postgresql-ek.postgres.database.azure.com:Pa55w0rd1234@postgresql-ek.postgres.database.azure.com:5432/cnainventory')
    sequelize
    .authenticate()
    .then(() => {
       console.log('Connection has been established successfully.');
    })
    .catch(err => {
       console.error('Unable to connect to the database:', err);
    });
    const Inventory = sequelize.define('inventory', {
       id: { type: Sequelize.INTEGER, allowNull: false, primaryKey: true },
       name: { type: Sequelize.STRING, allowNull: false },
       quantity: { type: Sequelize.INTEGER },
       date: { type: Sequelize.DATEONLY, defaultValue: Sequelize.NOW }
    }, {
       freezeTableName: true,
       timestamps: false
    });
    const express = require('express')
    const port = process.env.PORT || 8080
    const app = express()
    app.use(express.json());
    app.listen(port, () => console.log(`Sample app is listening on port ${port}!`))
    app.post('/inventory', async (req, res) => {
    try {
       const newItem = new Inventory(req.body)
       await newItem.save()
       res.json({ inventory: newItem })
    } catch(error) {
       console.error(error)
    }})
    app.get('/inventory/:id', async (req, res) => {
       const id = req.params.id
       try {
      const inventory = await Inventory.findAll({
          attributes: ['id', 'name', 'quantity', 'date'],
          where: {
             id: id
          }})
          res.json({ inventory })
       } catch(error) {
           console.error(error)
    }})
    

Verifiera funktionerna i Node.js Express-webbtjänsten

Du är äntligen redo att testa funktionerna i webbtjänsten. Du kan containerisera den just nu, men för enkelhetens skull distribuerar du den till en Azure App Service. Detta ger ett snabbt sätt att verifiera dess funktioner och se till att containerstorleken är ett genomförbart alternativ.

  1. I webbläsarfönstret som visar Azure-portalen, från Bash-sessionen i Cloud Shell-fönstret , kör du följande kommandon för att skapa en resursgrupp som ska vara värd för Azure-webbappen, till vilken du distribuerar Node.js Express-appen:

    RG1NAME=postgresql-db-RG
    LOCATION=$(az group show --resource-group $RG1NAME --query location --output tsv)
    RG2NAME=cna-express-RG
    az group create --name $RG2NAME --location $LOCATION
    
  2. Kör följande kommandon för att skapa en Azure App Service-plan på kostnadsfri nivå som ska vara värd för den nya Azure-webbappen:

    SPNAME=express-sp
    az appservice plan create --name $SPNAME --resource-group $RG2NAME --sku F1 --is-linux
    
  3. Kör följande kommandon för att skapa den nya Node.js-baserade Azure-webbappen och distribuera koden till den:

    WEBAPPNAME=express$RANDOM$RANDOM
    az webapp create --name $WEBAPPNAME --resource-group $RG2NAME --plan $SPNAME --runtime "NODE|12-lts"
    
    cd ~/cna-express
    git config --global user.email "user1@adatum.com"
    git config --global user.name "Adatum User1"
    git init
    git add -A
    git commit -m "Initial Commit"
    
    DEPLOYMENTUSER=m03User$RANDOM
    DEPLOYMENTPASS=m03Pass$RANDOM$RANDOM
    az webapp deployment user set --user-name $DEPLOYMENTUSER --password $DEPLOYMENTPASS
    
    echo $DEPLOYMENTUSER
    echo $DEPLOYMENTPASS
    
    RG2NAME=cna-express-RG
    WEBAPPNAME=$(az webapp list --resource-group $RG2NAME --query "[0].name" --output tsv)
    DEPLOYMENTURL=$(az webapp deployment source config-local-git --name $WEBAPPNAME --resource-group $RG2NAME --output tsv)
    
    git remote add azure $DEPLOYMENTURL
    
    git checkout -b master
    git commit -a -m "test"
    git push --set-upstream azure master
    

    Kommentar

    När du uppmanas att ange ett lösenord skriver du det lösenord som visas efter kommandot echo $DEPLOYMENTPASS .

    Kommentar

    Ignorera meddelanden som anger att huvudgrenen redan finns eller att inget har checkats in.

  4. Kör följande kommandon för att verifiera POST HTTP-routningen för Node.js Express-appen:

    RG2NAME=cna-express-RG
    WEBAPPNAME=$(az webapp list --resource-group $RG2NAME --query "[0].name" --output tsv)
    curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"id":3,"name":"ice cream","quantity":50}' \
    http://$WEBAPPNAME.azurewebsites.net/inventory
    

    Kommentar

    Kommandot ska returnera värdena för posterna i den nyligen tillagda tabellraden, inklusive det automatiskt genererade datumet. Det kan ta en till två minuter innan kommandot returnerar utdatavärdena.

  5. Om du vill verifiera GET HTTP-routningen för Node.js Express-appen öppnar du en annan flik i webbläsaren som visar Cloud Shell-fönstret , navigerar till Azure-portalen och använder textrutan Sök efter resurser, tjänster och dokument för att söka efter apptjänstens webbapp som du distribuerade. Gå till bladet Översikt , identifiera värdet för URL-egenskapen , lägg till strängen /inventory/3 i det URL-värdet, öppna en annan flik i samma webbläsarfönster och gå till den nyligen konstruerade URL-strängen för att visa motsvarande webbsida.

    Kommentar

    Sidan bör visa egenskaperna för objektet som du lade till i inventeringstabellenför cnainventory-databasen i föregående steg.

Resultat

Klar! Du har slutfört den andra övningen i den här modulen. I den här övningen skapade och konfigurerade du en Express.js-baserad webbtjänst som ger åtkomst till Azure Database for PostgreSQL. De resurser som du distribuerade i den här övningen måste slutföra nästa övning i den här modulen.