Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
V tomto kurzu použijete příznak variantní funkce ke správě prostředí pro různé uživatelské segmenty v ukázkové aplikaci Citát dne. Použijete příznak varianty vytvořený v příznaku Použít variantní funkce. Než budete pokračovat, ujistěte se, že vytvoříte příznak funkce pro variantu s názvem Greeting (Pozdrav) ve vašem úložišti konfigurace aplikace.
Požadavky
- Účet Azure s aktivním předplatným. Vytvořte si ho zdarma.
- Úložiště konfigurace aplikací, jak je znázorněno v kurzu pro vytvoření úložiště.
- Přejděte na verzi 1.21 nebo novější. Informace o instalaci Go najdete na stránce ke stažení go.
- Poskytovatel Azure App Configuration Go verze 1.1.0 nebo novější.
- Knihovna Feature Management Go verze 1.1.0 nebo novější.
- Postupujte podle kurzu Použijte příznaky funkcí variant a vytvořte příznak funkce varianty s názvem Greeting.
Nastavení webové aplikace Go Gin
Vytvořte nový adresář pro projekt Go a přejděte do něj:
mkdir quote-of-the-day cd quote-of-the-dayInicializace nového modulu Go:
go mod init quote-of-the-dayNainstalujte požadované balíčky Go:
go get github.com/gin-gonic/gin go get github.com/gin-contrib/sessions go get github.com/gin-contrib/sessions/cookie go get github.com/microsoft/Featuremanagement-Go/featuremanagement go get github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfigVytvořte adresář šablon pro šablony HTML a přidejte požadované soubory HTML:
mkdir templatesPřidejte následující soubory šablon HTML z úložiště GitHub a umístěte je do
templatesadresáře:-
index.html- Šablona domovské stránky -
login.html- Šablona přihlašovací stránky
-
Vytvořte soubor s názvem
appconfig.gos následujícím obsahem. Ke službě App Configuration Store se můžete připojit pomocí Microsoft Entra ID (doporučeno) nebo připojovacího řetězce.package main import ( "context" "log" "os" "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration" "github.com/Azure/azure-sdk-for-go/sdk/azidentity" ) func loadAzureAppConfiguration(ctx context.Context) (*azureappconfiguration.AzureAppConfiguration, error) { // Get the endpoint from environment variable endpoint := os.Getenv("AZURE_APPCONFIG_ENDPOINT") if endpoint == "" { log.Fatal("AZURE_APPCONFIG_ENDPOINT environment variable is not set") } // Create a credential using DefaultAzureCredential credential, err := azidentity.NewDefaultAzureCredential(nil) if err != nil { log.Fatalf("Failed to create credential: %v", err) } // Set up authentication options with endpoint and credential authOptions := azureappconfiguration.AuthenticationOptions{ Endpoint: endpoint, Credential: credential, } // Set up options to enable feature flags options := &azureappconfiguration.Options{ FeatureFlagOptions: azureappconfiguration.FeatureFlagOptions{ Enabled: true, RefreshOptions: azureappconfiguration.RefreshOptions{ Enabled: true, }, }, } // Load configuration from Azure App Configuration appConfig, err := azureappconfiguration.Load(ctx, authOptions, options) if err != nil { log.Fatalf("Failed to load configuration: %v", err) } return appConfig, nil }
Použití výchozí funkce varianty
Vytvořte soubor s názvem
main.gos následujícím obsahem:package main import ( "context" "fmt" "log" "net/http" "strings" "github.com/Azure/AppConfiguration-GoProvider/azureappconfiguration" "github.com/gin-contrib/sessions" "github.com/gin-contrib/sessions/cookie" "github.com/gin-gonic/gin" "github.com/microsoft/Featuremanagement-Go/featuremanagement" "github.com/microsoft/Featuremanagement-Go/featuremanagement/providers/azappconfig" ) type Quote struct { Message string `json:"message"` Author string `json:"author"` } type WebApp struct { featureManager *featuremanagement.FeatureManager appConfig *azureappconfiguration.AzureAppConfiguration quotes []Quote } func main() { // Load Azure App Configuration appConfig, err := loadAzureAppConfiguration(context.Background()) if err != nil { log.Fatalf("Error loading Azure App Configuration: %v", err) } // Create feature flag provider featureFlagProvider, err := azappconfig.NewFeatureFlagProvider(appConfig) if err != nil { log.Fatalf("Error creating feature flag provider: %v", err) } // Create feature manager featureManager, err := featuremanagement.NewFeatureManager(featureFlagProvider, nil) if err != nil { log.Fatalf("Error creating feature manager: %v", err) } // Initialize quotes quotes := []Quote{ { Message: "You cannot change what you are, only what you do.", Author: "Philip Pullman", }, } // Create web app app := &WebApp{ featureManager: featureManager, appConfig: appConfig, quotes: quotes, } // Setup Gin with default middleware (Logger and Recovery) r := gin.Default() // Start server if err := r.Run(":8080"); err != nil { log.Fatalf("Failed to start server: %v", err) } fmt.Println("Starting Quote of the Day server on http://localhost:8080") fmt.Println("Open http://localhost:8080 in your browser") fmt.Println() }Povolte aktualizaci konfigurace a funkčních příznaků v Azure App Configuration pomocí middlewaru.
// Existing code // ... ... func (app *WebApp) refreshMiddleware() gin.HandlerFunc { return func(c *gin.Context) { go func() { if err := app.appConfig.Refresh(context.Background()); err != nil { log.Printf("Error refreshing configuration: %v", err) } }() c.Next() } } // The rest of existing code //... ...Nastavte trasy s následujícím obsahem:
// Existing code // ... ... func (app *WebApp) setupRoutes(r *gin.Engine) { // Setup sessions store := cookie.NewStore([]byte("secret-key-change-in-production")) store.Options(sessions.Options{ MaxAge: 3600, // 1 hour HttpOnly: true, Secure: false, // Set to true in production with HTTPS }) r.Use(sessions.Sessions("session", store)) r.Use(app.refreshMiddleware()) // Load HTML templates r.LoadHTMLGlob("templates/*.html") // Routes r.GET("/", app.homeHandler) r.GET("/login", app.loginPageHandler) r.POST("/login", app.loginHandler) r.GET("/logout", app.logoutHandler) } // Home page handler func (app *WebApp) homeHandler(c *gin.Context) { session := sessions.Default(c) username := session.Get("username") quote := app.quotes[0] var greetingMessage string var targetingContext featuremanagement.TargetingContext if username != nil { // Create targeting context for the user targetingContext = createTargetingContext(username.(string)) // Get the Greeting variant for the current user if variant, err := app.featureManager.GetVariant("Greeting", targetingContext); err != nil { log.Printf("Error getting Greeting variant: %v", err) } else if variant != nil && variant.ConfigurationValue != nil { // Extract the greeting message from the variant configuration if configValue, ok := variant.ConfigurationValue.(string); ok { greetingMessage = configValue } } } c.HTML(http.StatusOK, "index.html", gin.H{ "title": "Quote of the Day", "user": username, "greetingMessage": greetingMessage, "quote": quote, }) } func (app *WebApp) loginPageHandler(c *gin.Context) { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", }) } func (app *WebApp) loginHandler(c *gin.Context) { email := strings.TrimSpace(c.PostForm("email")) // Basic validation if email == "" { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", "error": "Email cannot be empty", }) return } if !strings.Contains(email, "@") { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login - Quote of the Day", "error": "Please enter a valid email address", }) return } // Store email in session session := sessions.Default(c) session.Set("username", email) if err := session.Save(); err != nil { log.Printf("Error saving session: %v", err) } c.Redirect(http.StatusFound, "/") } func (app *WebApp) logoutHandler(c *gin.Context) { session := sessions.Default(c) session.Clear() if err := session.Save(); err != nil { log.Printf("Error saving session: %v", err) } c.Redirect(http.StatusFound, "/") } // Helper function to create TargetingContext func createTargetingContext(userID string) featuremanagement.TargetingContext { targetingContext := featuremanagement.TargetingContext{ UserID: userID, Groups: []string{}, } if strings.Contains(userID, "@") { parts := strings.Split(userID, "@") if len(parts) == 2 { domain := parts[1] targetingContext.Groups = append(targetingContext.Groups, domain) // Add domain as group } } return targetingContext } // The rest of existing code //... ...Aktualizujte
main.gonásledujícím obsahem:// Existing code // ... ... r := gin.Default() // Setup routes app.setupRoutes(r) // Start server if err := r.Run(":8080"); err != nil { log.Fatalf("Failed to start server: %v", err) } // The rest of existing code // ... ...
Sestavení a spuštění aplikace
Nastavte proměnnou prostředí pro ověřování a spusťte aplikaci:
go mod tidy go run .Otevřete prohlížeč a přejděte na
http://localhost:8080. V pravém horním rohu vyberte možnost Přihlásit pro přihlášení jako usera@contoso.com.
Po přihlášení se zobrazí dlouhá zpráva s pozdravem pro usera@contoso.com.
Klikněte na Odhlásit se a přihlásit se jako userb@contoso.com, zobrazí se jednoduchá zpráva s pozdravem.
Poznámka:
Pro účely tohoto kurzu je důležité používat tyto názvy přesně. Pokud je funkce nakonfigurovaná podle očekávání, měli by dva uživatelé vidět různé varianty.
Další kroky
Další informace o správě funkcí v Go najdete v následujících dokumentech: