Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
W tym samouczku użyjesz flagi funkcji wariantu do zarządzania doświadczeniami dla różnych segmentów użytkowników w przykładowej aplikacji Cytat dnia. Używasz flagi funkcji wariantowej wspomnianej w sekcji Użyj flag funkcji wariantu. Przed kontynuowaniem upewnij się, że utworzyłeś flagę funkcji o nazwie Greeting w swoim magazynie konfiguracji aplikacji.
Wymagania wstępne
- Konto Azure z aktywną subskrypcją. Utwórz je bezpłatnie.
- Magazyn usługi App Configuration, jak pokazano w samouczku dotyczącym tworzenia magazynu konfiguracji aplikacji.
- Przejdź do wersji 1.21 lub nowszej. Aby uzyskać informacje na temat instalowania języka Go, zobacz stronę Pobierania Języka Go.
- Dostawca języka Go usługi Azure App Configuration w wersji 1.1.0 lub nowszej.
- Biblioteka Go zarządzania funkcjami w wersji 1.1.0 lub nowszej.
- Postępuj zgodnie z samouczkiem Używanie flag funkcji wariantu i utwórz flagę funkcji wariantu o nazwie Greeting (Powitanie).
Konfigurowanie aplikacji internetowej Go Gin
Utwórz nowy katalog dla projektu Go i przejdź do niego:
mkdir quote-of-the-day cd quote-of-the-dayZainicjuj nowy moduł języka Go:
go mod init quote-of-the-dayZainstaluj wymagane pakiety Języka 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/azappconfigUtwórz katalog szablonów dla szablonów HTML i dodaj wymagane pliki HTML:
mkdir templatesDodaj następujące pliki szablonów HTML z repozytorium GitHub i umieść je w
templateskatalogu:-
index.html- Szablon strony głównej -
login.html- Szablon strony logowania
-
Utwórz plik o nazwie
appconfig.goz następującą zawartością. Możesz nawiązać połączenie z magazynem App Configuration przy użyciu identyfikatora Entra firmy Microsoft (zalecane) lub parametrów połączenia.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 }
Używanie flagi funkcji wariantu
Utwórz plik o nazwie
main.goo następującej zawartości: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() }Włącz odświeżanie konfiguracji i flagi funkcji z usługi Azure App Configuration przy użyciu oprogramowania pośredniczącego.
// 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 //... ...Skonfiguruj trasy z następującą zawartością:
// 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 //... ...Zaktualizuj
main.goprzy użyciu następującej zawartości.// 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 // ... ...
Kompilowanie i uruchamianie aplikacji
Ustaw zmienną środowiskową na potrzeby uwierzytelniania i uruchom aplikację:
go mod tidy go run .Otwórz przeglądarkę i przejdź do
http://localhost:8080adresu . Wybierz pozycję Zaloguj się w prawym górnym rogu, aby zalogować się jako usera@contoso.com.
Po zalogowaniu zostanie wyświetlony długi komunikat powitania dla elementu usera@contoso.com.
Kliknij Wyloguj i zaloguj się jako userb@contoso.com, aby zobaczyć prostą wiadomość powitalną.
Uwaga / Notatka
Ważne jest, aby w tym samouczku używać dokładnie tych nazw. O ile funkcja została skonfigurowana zgodnie z oczekiwaniami, obaj użytkownicy powinni zobaczyć różne warianty.
Dalsze kroki
Aby dowiedzieć się więcej na temat zarządzania funkcjami w języku Go, przejdź do następujących dokumentów: