Gérer les sessions avec Firestore


Ce tutoriel explique comment gérer des sessions sur App Engine.

De nombreuses applications requièrent une fonctionnalité de gestion de session pour l'authentification et le stockage des préférences utilisateur. Le package sessions de Gorilla Web Toolkit intègre une mise en œuvre basée sur un système de fichiers pour exécuter cette fonction. Cette mise en œuvre n'est toutefois pas adaptée à une application pouvant être diffusée depuis plusieurs instances. En effet, la session enregistrée dans une instance peut différer des autres instances. Le package gorilla/sessions intègre également une mise en œuvre basée sur les cookies. Toutefois, cette mise en œuvre nécessite le chiffrement des cookies et le stockage de la session entière sur le client plutôt qu'un ID de session, qui peut être trop volumineux pour certaines applications.

Objectifs

  • Écrire l'application
  • Exécuter l'application en local
  • Déployer l'application sur App Engine

Coûts

Dans ce document, vous utilisez les composants facturables suivants de Google Cloud :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût. Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, vous pouvez éviter de continuer à payer des frais en supprimant les ressources que vous avez créées. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  1. Connectez-vous à votre compte Google Cloud. Si vous débutez sur Google Cloud, créez un compte pour évaluer les performances de nos produits en conditions réelles. Les nouveaux clients bénéficient également de 300 $ de crédits gratuits pour exécuter, tester et déployer des charges de travail.
  2. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  3. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  4. Activez l'API Firestore

    Activer l'API

  5. Installez Google Cloud CLI.
  6. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  7. Dans Google Cloud Console, sur la page de sélection du projet, sélectionnez ou créez un projet Google Cloud.

    Accéder au sélecteur de projet

  8. Vérifiez que la facturation est activée pour votre projet Google Cloud.

  9. Activez l'API Firestore

    Activer l'API

  10. Installez Google Cloud CLI.
  11. Pour initialiser gcloudCLI, exécutez la commande suivante :

    gcloud init
  12. Mettez à jour les composants gcloud :
    gcloud components update
  13. Préparez votre environnement de développement.

Mettre en place le projet

  1. Dans votre fenêtre de terminal, clonez le dépôt de l'exemple d'application sur votre machine locale :

    git clone https://github.com/GoogleCloudPlatform/golang-samples.git
  2. Accédez au répertoire qui contient l'exemple de code :

    cd golang-samples/getting-started/sessions

Comprendre l'application Web

L'application affiche des messages d'accueil dans différentes langues pour chaque utilisateur. Les utilisateurs connus reçoivent toujours les messages d'accueil dans la même langue.

Fenêtres d'application affichant un message d'accueil dans différentes langues.

Pour que l'application puisse stocker les préférences d'un utilisateur, vous devez mettre en œuvre une méthode permettant de stocker les informations sur l'utilisateur actuel dans une session. Dans cet exemple d'application, les données de session sont stockées à l'aide de Firestore.

Vous pouvez utiliser firestoregorilla, un magasin de sessions compatible avec gorilla/sessions.

  1. L'application commence par importer des dépendances, puis définit un type app devant contenir un élément sessions.Store et un modèle HTML, et enfin définit la liste des messages d'accueil.

    
    // Command sessions starts an HTTP server that uses session state.
    package main
    
    import (
    	"context"
    	"fmt"
    	"html/template"
    	"log"
    	"math/rand"
    	"net/http"
    	"os"
    
    	"cloud.google.com/go/firestore"
    	firestoregorilla "github.com/GoogleCloudPlatform/firestore-gorilla-sessions"
    	"github.com/gorilla/sessions"
    )
    
    // app stores a sessions.Store. Create a new app with newApp.
    type app struct {
    	store sessions.Store
    	tmpl  *template.Template
    }
    
    // greetings are the random greetings that will be assigned to sessions.
    var greetings = []string{
    	"Hello World",
    	"Hallo Welt",
    	"Ciao Mondo",
    	"Salut le Monde",
    	"Hola Mundo",
    }
    
  2. Ensuite, l'application définit une fonction main, qui crée une instance app, enregistre le gestionnaire d'index et démarre le serveur HTTP. La fonction newApp crée l'instance app en initialisant un sessions.Store avec la fonction firestoregorilla.New.

    
    func main() {
    	port := os.Getenv("PORT")
    	if port == "" {
    		port = "8080"
    	}
    	projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
    	if projectID == "" {
    		log.Fatal("GOOGLE_CLOUD_PROJECT must be set")
    	}
    
    	a, err := newApp(projectID)
    	if err != nil {
    		log.Fatalf("newApp: %v", err)
    	}
    
    	http.HandleFunc("/", a.index)
    
    	log.Printf("Listening on port %s", port)
    	if err := http.ListenAndServe(":"+port, nil); err != nil {
    		log.Fatal(err)
    	}
    }
    
    // newApp creates a new app.
    func newApp(projectID string) (*app, error) {
    	ctx := context.Background()
    	client, err := firestore.NewClient(ctx, projectID)
    	if err != nil {
    		log.Fatalf("firestore.NewClient: %v", err)
    	}
    	store, err := firestoregorilla.New(ctx, client)
    	if err != nil {
    		log.Fatalf("firestoregorilla.New: %v", err)
    	}
    
    	tmpl, err := template.New("Index").Parse(`<body>{{.views}} {{if eq .views 1.0}}view{{else}}views{{end}} for "{{.greeting}}"</body>`)
    	if err != nil {
    		return nil, fmt.Errorf("template.New: %w", err)
    	}
    
    	return &app{
    		store: store,
    		tmpl:  tmpl,
    	}, nil
    }
    
  3. Le gestionnaire d'index obtient la session de l'utilisateur ou en crée une si nécessaire. Les nouvelles sessions se voient attribuer une langue aléatoire et un nombre de vues égal à 0. Ensuite, le nombre de vues est incrémenté d'une unité, la session est enregistrée et le modèle HTML écrit la réponse.

    
    // index uses sessions to assign users a random greeting and keep track of
    // views.
    func (a *app) index(w http.ResponseWriter, r *http.Request) {
    	if r.RequestURI != "/" {
    		return
    	}
    
    	// name is a non-empty identifier for this app's sessions. Set it to
    	// something descriptive for your app. It is used as the Firestore
    	// collection name that stores the sessions.
    	name := "hello-views"
    	session, err := a.store.Get(r, name)
    	if err != nil {
    		// Could not get the session. Log an error and continue, saving a new
    		// session.
    		log.Printf("store.Get: %v", err)
    	}
    
    	if session.IsNew {
    		// firestoregorilla uses JSON, which unmarshals numbers as float64s.
    		session.Values["views"] = float64(0)
    		session.Values["greeting"] = greetings[rand.Intn(len(greetings))]
    	}
    	session.Values["views"] = session.Values["views"].(float64) + 1
    	if err := session.Save(r, w); err != nil {
    		log.Printf("Save: %v", err)
    		// Don't return early so the user still gets a response.
    	}
    
    	if err := a.tmpl.Execute(w, session.Values); err != nil {
    		log.Printf("Execute: %v", err)
    	}
    }
    

    Le schéma suivant décrit la façon dont Firestore gère les sessions pour l'application App Engine.

    Schéma de principe : utilisateur, App Engine, Firestore.

Supprimer des sessions

firestoregorilla ne supprime pas les sessions anciennes ou expirées. Vous pouvez supprimer les données de session dans la console Google Cloud ou mettre en œuvre une stratégie de suppression automatique. Si vous utilisez des solutions de stockage pour des sessions telles que Memcache ou Redis, les sessions expirées sont automatiquement supprimées.

Exécution locale

  1. Dans votre fenêtre de terminal, créez le fichier binaire sessions :

    go build
    
  2. Démarrez le serveur HTTP :

    ./sessions
    
  3. Affichez l'application dans votre navigateur Web :

    Cloud Shell

    Dans la barre d'outils Cloud Shell, cliquez sur Aperçu sur le Web Aperçu sur le Web et sélectionnez Prévisualiser sur le port 8080.

    Machine locale

    Dans votre navigateur, accédez à http://localhost:8080.

    L'un des cinq messages d'accueil suivants s'affiche : "Hello World", "Hallo Welt", "Hola mundo", "Salut le Monde" ou "Ciao Mondo". La langue change si vous ouvrez la page dans un autre navigateur ou en mode navigation privée. Vous pouvez consulter et modifier les données de session dans la console Google Cloud.

    Sessions Firestore dans la console Google Cloud

  4. Dans votre fenêtre de terminal, appuyez sur Control+C pour arrêter le serveur HTTP.

Déployer et exécuter l'application sur App Engine

Vous pouvez utiliser l'environnement standard App Engine pour créer et déployer une application qui s'exécute de manière fiable, même lorsqu'elle est soumise à une charge importante et doit gérer de grandes quantités de données.

Dans ce tutoriel, le serveur est déployé dans l'environnement standard App Engine.

Le fichier app.yaml contient la configuration d'environnement standard d'App Engine :

runtime: go112
  1. Déployez l'application sur App Engine :

    gcloud app deploy
    
  2. Dans votre navigateur Web, saisissez l'URL suivante :

    https://PROJECT_ID.REGION_ID.r.appspot.com

    Remplacez les éléments suivants :

Le message d'accueil est désormais diffusé par un serveur Web exécuté sur une instance App Engine.

Déboguer l'application

Si vous ne parvenez pas à vous connecter à votre application App Engine, vérifiez les éléments suivants :

  1. Vérifiez que les commandes de déploiement gcloud ont bien abouti et n'ont généré aucune erreur. Si des erreurs se sont produites (par exemple, message=Build failed), corrigez-les, puis essayez de redéployer l'application App Engine.
  2. Dans la console Google Cloud, accédez à la page Explorateur de journaux.

    Accéder à la page "Explorateur de journaux"

    1. Dans la liste déroulante Ressources sélectionnées récemment, cliquez sur Application App Engine, puis sur Tous les ID de module. La liste des requêtes correspondant à votre accès à l'application s'affiche. Si cette liste n'apparaît pas, vérifiez que vous avez bien sélectionné Tous les ID de module dans la liste déroulante. Si des messages d'erreur s'affichent dans la console Google Cloud, vérifiez que le code de votre application correspond au code décrit dans la section sur l'écriture de l'application Web.

    2. Assurez-vous que l'API Firestore est activée.

Effectuer un nettoyage

Supprimer le projet

  1. Dans la console Google Cloud, accédez à la page Gérer les ressources.

    Accéder à la page Gérer les ressources

  2. Dans la liste des projets, sélectionnez le projet que vous souhaitez supprimer, puis cliquez sur Supprimer.
  3. Dans la boîte de dialogue, saisissez l'ID du projet, puis cliquez sur Arrêter pour supprimer le projet.

Supprimer l'instance App Engine

  1. Dans la console Google Cloud, accédez à la page Versions pour App Engine.

    Accéder à la page "Versions"

  2. Cochez la case correspondant à la version de l'application autre que celle par défaut que vous souhaitez supprimer.
  3. Pour supprimer la version de l'application, cliquez sur  Supprimer.

Étapes suivantes