slogan3

Ontwerp en Implementeer Middleware in Go voor Webapplicaties

description

Met deze prompt leer je hoe je middleware effectief inzet in Go-webapplicaties om herbruikbare en beheerbare code te schrijven voor gemeenschappelijke taken als logging en beveiliging. Dit voorkomt duplicatie en verbetert onderhoudbaarheid en veiligheid, wat lastig te bereiken is zonder middleware.

prompt

Help mij met het ontwerpen en implementeren van middleware in Go voor mijn webapplicatie. Leg uit hoe ik middleware inzet voor taken zoals logging, authenticatie en fou ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht en voorbeeldcode voor het ontwerpen en implementeren van middleware in Go met het `net/http` pakket. Middleware wordt gebruikt om functies zoals logging, authenticatie en foutafhandeling aan je request-verwerking toe te voegen op een gestructureerde manier. ### Structuur van Middleware in Go In Go wordt middleware vaak geïmplementeerd als een functie die een `http.Handler` neemt en een nieuwe `http.Handler` retourneert. Dit stelt je in staat om meerdere middleware achter elkaar te koppelen. ### Basis structuur ```go type Middleware func(http.Handler) http.Handler ``` ### Voorbeeld: Middleware functies 1. **Logging Middleware** ```go func LoggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() log.Printf("Started %s %s", r.Method, r.URL.Path) next.ServeHTTP(w, r) log.Printf("Completed %s in %v", r.URL.Path, time.Since(start)) }) } ``` 2. **Authenticatie Middleware** ```go func AuthMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") if token != "Bearer mijnsecrettoken" { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) } ``` 3. **Foutafhandelings Middleware** Deze middleware kan de response opvangen en aanpassen bij fouten, bijvoorbeeld door een gestandaardiseerd formaat te gebruiken. ```go func RecoveryMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { log.Printf("Panic: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } ``` ### Middleware koppelen Om meerdere middleware te gebruiken, kun je ze achter elkaar aan roepen: ```go func ChainMiddleware(handler http.Handler, middlewares ...Middleware) http.Handler { for _, m := range middlewares { handler = m(handler) } return handler } ``` ### Voorbeeld hoofdprogramma ```go package main import ( "log" "net/http" "time" ) // Middleware functies hier (zoals hierboven) // hoofd handler func HelloHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hallo, wereld!")) } func main() { // Basis handler baseHandler := http.HandlerFunc(HelloHandler) // Middleware keten handler := ChainMiddleware(baseHandler, RecoveryMiddleware, LoggingMiddleware, AuthMiddleware, ) http.Handle("/", handler) log.Println("Server gestart op :8080") http.ListenAndServe(":8080", nil) } ``` ### Samenvatting - Middleware in `net/http` wordt geïmplementeerd als functies die `http.Handler` omwikkelen. - Je kunt meerdere middleware achter elkaar gebruiken door ze te chainen. - Gebruik middleware voor logging, authenticatie, foutafhandeling, etc. - Deze aanpak houdt je code overzichtelijk en herbruikbaar. Wil je dat ik de code verder uitbreid of een specifiek voorbeeld uitwerk?
provider: deepseek
model: deepseek-chat
Zeker! Ik leg uit hoe je middleware kunt ontwerpen en implementeren in Go met het `net/http` package. ## Basisstructuur van Middleware Middleware in Go is een functie die een `http.Handler` accepteert en een nieuwe `http.Handler` retourneert: ```go type Middleware func(http.Handler) http.Handler ``` ## Algemene Applicatiestructuur ```go package main import ( "log" "net/http" "time" ) func main() { mux := http.NewServeMux() // Routes mux.HandleFunc("/", homeHandler) mux.HandleFunc("/api/protected", protectedHandler) // Middleware chain handler := chainMiddleware( mux, loggingMiddleware, authMiddleware, errorHandlingMiddleware, ) log.Println("Server gestart op :8080") http.ListenAndServe(":8080", handler) } func chainMiddleware(h http.Handler, middlewares ...Middleware) http.Handler { for _, middleware := range middlewares { h = middleware(h) } return h } ``` ## 1. Logging Middleware ```go func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { start := time.Now() // Wrap de ResponseWriter om status code te kunnen lezen wrapped := &responseWriter{w, http.StatusOK} next.ServeHTTP(wrapped, r) duration := time.Since(start) log.Printf("%s %s %d %v", r.Method, r.URL.Path, wrapped.status, duration) }) } type responseWriter struct { http.ResponseWriter status int } func (rw *responseWriter) WriteHeader(code int) { rw.status = code rw.ResponseWriter.WriteHeader(code) } ``` ## 2. Authenticatie Middleware ```go func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("Authorization") if token == "" { http.Error(w, "Unauthorized: Geen token aangeboden", http.StatusUnauthorized) return } // Simpele token validatie (vervang dit met echte authenticatie) if !isValidToken(token) { http.Error(w, "Unauthorized: Ongeldig token", http.StatusUnauthorized) return } // Voeg gebruikerinfo toe aan context user := getUserFromToken(token) ctx := context.WithValue(r.Context(), "user", user) r = r.WithContext(ctx) next.ServeHTTP(w, r) }) } func isValidToken(token string) bool { // Implementeer echte token validatie return token == "valid-token-123" } func getUserFromToken(token string) string { // Haal gebruikerinfo uit token return "gebruiker@example.com" } ``` ## 3. Foutafhandeling Middleware ```go func errorHandlingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { log.Printf("Panic opgevangen: %v", err) http.Error(w, "Interne serverfout", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) } ``` ## 4. CORS Middleware (Extra voorbeeld) ```go func corsMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization") if r.Method == "OPTIONS" { w.WriteHeader(http.StatusOK) return } next.ServeHTTP(w, r) }) } ``` ## Voorbeeld Handlers ```go func homeHandler(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Welkom bij de home pagina!")) } func protectedHandler(w http.ResponseWriter, r *http.Request) { // Haal gebruiker uit context user := r.Context().Value("user").(string) w.Write([]byte("Beveiligde content voor: " + user)) } ``` ## Alternatieve Aanpak met Struct Je kunt ook een middleware struct maken voor complexere scenario's: ```go type App struct { middleware []Middleware router *http.ServeMux } func NewApp() *App { return &App{ router: http.NewServeMux(), } } func (a *App) Use(middleware Middleware) { a.middleware = append(a.middleware, middleware) } func (a *App) HandleFunc(pattern string, handler http.HandlerFunc) { a.router.HandleFunc(pattern, handler) } func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) { var handler http.Handler = a.router for i := len(a.middleware) - 1; i >= 0; i-- { handler = a.middleware[i](handler) } handler.ServeHTTP(w, r) } ``` ## Gebruik van de Struct Aanpak ```go func main() { app := NewApp() app.Use(loggingMiddleware) app.Use(authMiddleware) app.Use(errorHandlingMiddleware) app.HandleFunc("/", homeHandler) app.HandleFunc("/api/data", dataHandler) http.ListenAndServe(":8080", app) } ``` ## Belangrijke Punten: 1. **Volgorde matters**: Middleware wordt uitgevoerd in de volgorde waarin ze worden toegevoegd 2. **Context gebruiken**: Gebruik context voor het doorgeven van data tussen middleware 3. **Error handling**: Zorg voor goede foutafhandeling in elke middleware 4. **Performance**: Middleware voegt overhead toe, houd het lichtgewicht Deze aanpak geeft je een flexibele en schaalbare middleware-structuur voor je Go webapplicatie!