Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
Neste tutorial, você usa um sinalizador de recurso variante para gerenciar experiências para diferentes segmentos de usuário em um aplicativo de exemplo, Cotação do Dia. Você utiliza o sinalizador de recurso variante criado em Usar sinalizadores de recurso variante. Antes de continuar, certifique-se de criar o sinalizador de recurso variante chamado Saudação na sua loja de configuração de aplicativos.
Pré-requisitos
- Uma conta do Azure com uma assinatura ativa. Crie um gratuitamente.
- Uma loja de configuração de aplicativos, conforme mostrado no tutorial para criar uma loja.
- Go versão 1.21 ou posterior. Para obter informações sobre como instalar o Go, consulte a página de downloads Go.
- Provedor do Azure App Configuration Go v1.1.0 ou posterior.
- Biblioteca do Feature Management Go v1.1.0 ou posterior.
- Siga o tutorial Usar sinalizadores de recurso variante e crie o sinalizador de recurso variante chamado Saudação.
Configurar uma aplicação Web Go Gin
Crie um novo diretório para seu projeto Go e navegue até ele:
mkdir quote-of-the-day cd quote-of-the-dayInicialize um novo módulo Go:
go mod init quote-of-the-dayInstale os pacotes Go necessários:
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/azappconfigCrie um diretório de modelos para seus modelos HTML e adicione os arquivos HTML necessários:
mkdir templatesAdicione os seguintes arquivos de modelo HTML do repositório GitHub e coloque-os
templatesno diretório:-
index.html- O modelo de página inicial -
login.html- O modelo de página de login
-
Crie um arquivo nomeado
appconfig.gocom o seguinte conteúdo. Você pode se conectar à sua loja de configuração de aplicativos usando a ID do Microsoft Entra (recomendado) ou uma cadeia de conexão.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 }
Usar o sinalizador de recurso variante
Crie um arquivo nomeado
main.gocom o seguinte conteúdo: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() }Habilite a atualização da configuração e do sinalizador de recursos da Configuração do Aplicativo do Azure com o 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() } } // The rest of existing code //... ...Configure as rotas com o seguinte conteúdo:
// 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 //... ...Atualize o
main.gocom o seguinte conteúdo:// 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 // ... ...
Criar e executar o aplicativo
Defina a variável de ambiente para autenticação e execute o aplicativo:
go mod tidy go run .Abra o navegador e navegue até
http://localhost:8080. Selecione Login no canto superior direito para entrar como usera@contoso.com.
Uma vez conectado, você verá uma longa mensagem de saudação para usera@contoso.com.
Clique em Logout e faça login como userb@contoso.com, você verá a mensagem de saudação simples.
Observação
É importante para o propósito deste tutorial usar esses nomes exatamente. Desde que o recurso tenha sido configurado conforme o esperado, os dois usuários devem ver variantes diferentes.
Próximos passos
Para saber mais sobre o gerenciamento de recursos no Go, continue para os seguintes documentos: