Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In diesem Leitfaden verwenden Sie den Zielfilter, um ein Feature für Zielgruppen für Ihre Go Gin-Webanwendung zu bereitstellen. Weitere Informationen zum Zielfilter finden Sie unter Rollout von Features für Zielgruppen.
Prerequisites
- Ein Azure-Konto mit einem aktiven Abonnement. Erstellen Sie ein kostenloses Konto.
- Ein App-Konfigurationsspeicher, wie in der Anleitung zum Erstellen eines Speichers gezeigt.
- Ein Featureflag mit Zielfilter Erstellen Sie das Featureflag.
- Wechseln Sie zu 1.21 oder höher. Informationen zum Installieren von Go finden Sie auf der Seite "Go-Downloads".
- Azure App Configuration Go-Anbieter v1.1.0 oder höher.
Erstellen einer Webanwendung mit einem Featureflag
In diesem Abschnitt erstellen Sie eine Webanwendung, mit der Benutzende sich anmelden und das zuvor erstellte Featureflag Beta verwenden können.
Erstellen Sie ein neues Verzeichnis für Ihr Go-Projekt, und navigieren Sie dorthin:
mkdir gin-targeting-quickstart cd gin-targeting-quickstartInitialisieren eines neuen Go-Moduls:
go mod init gin-targeting-quickstartInstallieren Sie die erforderlichen Go-Pakete:
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/azappconfigErstellen Sie ein Vorlagenverzeichnis für Ihre HTML-Vorlagen, und fügen Sie die erforderlichen HTML-Dateien hinzu:
mkdir templatesFügen Sie die folgenden HTML-Vorlagendateien aus dem GitHub-Repository hinzu, und platzieren Sie sie im
templatesVerzeichnis:-
index.html- Die Homepagevorlage -
beta.html- Die Betaseitenvorlage -
login.html- Die Anmeldeseitenvorlage
-
Erstellen Sie eine Datei namens
appconfig.gomit folgendem Inhalt. Sie können eine Verbindung mit Ihrem App Configuration-Speicher entweder mithilfe von Microsoft Entra ID (empfohlen) oder mit einer Verbindungszeichenfolge herstellen.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 }
Verwenden von Zielgruppenausrichtung mit Feature-Flags
Erstellen Sie eine Datei namens
main.gomit folgendem Inhalt.package main import ( "context" "fmt" "log" "net/http" "strings" "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 WebApp struct { featureManager *featuremanagement.FeatureManager appConfig *azureappconfiguration.AzureAppConfiguration } 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) } // Create web app app := &WebApp{ featureManager: featureManager, appConfig: appConfig, } // 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 server on http://localhost:8080") fmt.Println("Open http://localhost:8080 in your browser") fmt.Println() }Aktivieren Sie die Aktualisierung von Konfigurations- und Featurekennzeichnungen aus der Azure-App-Konfiguration mit der Middleware.
// 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() } } func (app *WebApp) featureMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Get current user from session session := sessions.Default(c) username := session.Get("username") var betaEnabled bool var targetingContext featuremanagement.TargetingContext if username != nil { // Evaluate Beta feature with targeting context var err error targetingContext = createTargetingContext(username.(string)) betaEnabled, err = app.featureManager.IsEnabledWithAppContext("Beta", targetingContext) if err != nil { log.Printf("Error checking Beta feature with targeting: %v", err) } } c.Set("betaEnabled", betaEnabled) c.Set("user", username) c.Set("targetingContext", targetingContext) c.Next() } } // 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 { targetingContext.Groups = append(targetingContext.Groups, parts[1]) // Add domain as group } } return targetingContext } // The rest of existing code //... ...Richten Sie die Routen mit folgendem Inhalt ein:
// 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()) r.Use(app.featureMiddleware()) // Load HTML templates r.LoadHTMLGlob("templates/*.html") // Routes r.GET("/", app.homeHandler) r.GET("/beta", app.betaHandler) 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) { betaEnabled := c.GetBool("betaEnabled") user := c.GetString("user") c.HTML(http.StatusOK, "index.html", gin.H{ "title": "TestFeatureFlags", "betaEnabled": betaEnabled, "user": user, }) } // Beta page handler func (app *WebApp) betaHandler(c *gin.Context) { betaEnabled := c.GetBool("betaEnabled") if !betaEnabled { return } c.HTML(http.StatusOK, "beta.html", gin.H{ "title": "Beta Page", }) } func (app *WebApp) loginPageHandler(c *gin.Context) { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login", }) } func (app *WebApp) loginHandler(c *gin.Context) { username := c.PostForm("username") // Basic validation - ensure username is not empty if strings.TrimSpace(username) == "" { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login", "error": "Username cannot be empty", }) return } // Store username in session - any valid username is accepted session := sessions.Default(c) session.Set("username", username) session.Save() c.Redirect(http.StatusFound, "/") } func (app *WebApp) logoutHandler(c *gin.Context) { session := sessions.Default(c) session.Clear() session.Save() c.Redirect(http.StatusFound, "/") } // The rest of existing code //... ...Aktualisieren Sie das
main.gomit dem folgenden Inhalt:// 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 // ... ...Nach Abschluss der vorherigen Schritte sollte Ihre
main.goDatei nun die vollständige Implementierung enthalten, wie unten dargestellt:package main import ( "context" "fmt" "log" "net/http" "strings" "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 WebApp struct { featureManager *featuremanagement.FeatureManager appConfig *azureappconfiguration.AzureAppConfiguration } 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() } } func (app *WebApp) featureMiddleware() gin.HandlerFunc { return func(c *gin.Context) { // Get current user from session session := sessions.Default(c) username := session.Get("username") var betaEnabled bool var targetingContext featuremanagement.TargetingContext if username != nil { // Evaluate Beta feature with targeting context var err error targetingContext = createTargetingContext(username.(string)) betaEnabled, err = app.featureManager.IsEnabledWithAppContext("Beta", targetingContext) if err != nil { log.Printf("Error checking Beta feature with targeting: %v", err) } } c.Set("betaEnabled", betaEnabled) c.Set("user", username) c.Set("targetingContext", targetingContext) c.Next() } } // 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 { targetingContext.Groups = append(targetingContext.Groups, parts[1]) // Add domain as group } } return targetingContext } 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()) r.Use(app.featureMiddleware()) // Load HTML templates r.LoadHTMLGlob("templates/*.html") // Routes r.GET("/", app.homeHandler) r.GET("/beta", app.betaHandler) 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) { betaEnabled := c.GetBool("betaEnabled") user := c.GetString("user") c.HTML(http.StatusOK, "index.html", gin.H{ "title": "TestFeatureFlags", "betaEnabled": betaEnabled, "user": user, }) } // Beta page handler func (app *WebApp) betaHandler(c *gin.Context) { betaEnabled := c.GetBool("betaEnabled") if !betaEnabled { return } c.HTML(http.StatusOK, "beta.html", gin.H{ "title": "Beta Page", }) } func (app *WebApp) loginPageHandler(c *gin.Context) { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login", }) } func (app *WebApp) loginHandler(c *gin.Context) { username := c.PostForm("username") // Basic validation - ensure username is not empty if strings.TrimSpace(username) == "" { c.HTML(http.StatusOK, "login.html", gin.H{ "title": "Login", "error": "Username cannot be empty", }) return } // Store username in session - any valid username is accepted session := sessions.Default(c) session.Set("username", username) session.Save() c.Redirect(http.StatusFound, "/") } func (app *WebApp) logoutHandler(c *gin.Context) { session := sessions.Default(c) session.Clear() session.Save() c.Redirect(http.StatusFound, "/") } 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) } // Create web app app := &WebApp{ featureManager: featureManager, appConfig: appConfig, } // Setup Gin with default middleware (Logger and Recovery) 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) } fmt.Println("Starting server on http://localhost:8080") fmt.Println("Open http://localhost:8080 in your browser") fmt.Println() }
Zielfilter in Aktion
Legen Sie die Umgebungsvariable für die Authentifizierung fest , und führen Sie die Anwendung aus:
go mod tidy go run .Öffnen Sie ein Browserfenster, und wechseln Sie zu
http://localhost:8080. Anfänglich wird das Beta-Element nicht in der Symbolleiste angezeigt, weil die Option Standardprozentsatz auf 0 festgelegt ist.
Klicken Sie in der oberen rechten Ecke auf den Anmeldelink. Versuchen Sie, sich mit
test@contoso.comanzumelden.Nach der Anmeldung als
test@contoso.comwird das Beta-Element jetzt auf der Symbolleiste angezeigt, datest@contoso.comals Zielbenutzer angegeben ist.
Melden Sie sich jetzt ab und dann als
testuser@contoso.coman. Das Element Beta wird nicht auf der Symbolleiste angezeigt, datestuser@contoso.comals ausgeschlossene benutzende Person angegeben wird.
Nächste Schritte
Wenn Sie mehr über die Featurefilter erfahren möchten, fahren Sie mit den folgenden Dokumenten fort.
Weitere Informationen zur Go Feature Management-Bibliothek finden Sie im folgenden Dokument: