Last active
May 4, 2025 12:38
-
-
Save didikz/98de868f20887285f5aabc80f4dddcfa to your computer and use it in GitHub Desktop.
Golang Middlewares
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // you need to create the module first by running | |
| // go mod init <yourpackage> | |
| package main | |
| import ( | |
| "context" | |
| "encoding/json" | |
| "errors" | |
| "log" | |
| "net/http" | |
| "os" | |
| "os/signal" | |
| "syscall" | |
| "time" | |
| ) | |
| type defaultResponse struct { | |
| Status string `json:"status"` | |
| Description string `json:"description"` | |
| } | |
| type errorResponse struct { | |
| Status int `json:"status"` | |
| Error string `json:"error"` | |
| Message string `json:"message"` | |
| } | |
| // Middleware type for cleaner middleware chaining | |
| type Middleware func(http.Handler) http.Handler | |
| // Chain creates a single middleware from multiple middlewares | |
| func Chain(middlewares ...Middleware) Middleware { | |
| return func(next http.Handler) http.Handler { | |
| for i := len(middlewares) - 1; i >= 0; i-- { | |
| next = middlewares[i](next) | |
| } | |
| return next | |
| } | |
| } | |
| func logMiddleware(next http.Handler) http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| log.Print("Executing logMiddleware") | |
| next.ServeHTTP(w, r) | |
| }) | |
| } | |
| func requestSignatureMiddleware(next http.Handler) http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| log.Print("Executing requestSignatureMiddleware") | |
| h := r.Header.Get("x-signature") | |
| if h == "" { | |
| resp := errorResponse{ | |
| Status: http.StatusUnauthorized, | |
| Error: "INVALID_MISSING_SIGNATURE", | |
| Message: "missing request signature", | |
| } | |
| j, _ := json.Marshal(resp) | |
| w.Header().Add("Content-Type", "application/json") | |
| w.WriteHeader(http.StatusUnauthorized) | |
| w.Write(j) | |
| return | |
| } | |
| next.ServeHTTP(w, r) | |
| }) | |
| } | |
| func rootHandler() http.Handler { | |
| return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | |
| resp := defaultResponse{ | |
| Status: "OK", | |
| Description: "Success", | |
| } | |
| j, _ := json.Marshal(resp) | |
| w.Header().Add("Content-Type", "application/json") | |
| w.Write(j) | |
| }) | |
| } | |
| func main() { | |
| mux := http.NewServeMux() | |
| // Create a chain of middlewares | |
| middlewareChain := Chain( | |
| func(next http.Handler) http.Handler { return logMiddleware(next) }, | |
| func(next http.Handler) http.Handler { return requestSignatureMiddleware(next) }, | |
| // Add more middlewares here as needed | |
| ) | |
| mux.Handle("GET /", middlewareChain(rootHandler())) | |
| s := &http.Server{ | |
| Addr: ":8080", | |
| Handler: mux, | |
| } | |
| stop := make(chan os.Signal, 1) | |
| signal.Notify(stop, os.Interrupt, syscall.SIGTERM) | |
| go func() { | |
| if err := s.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) { | |
| log.Fatal(err) | |
| } | |
| log.Println("Stopped serving new connections") | |
| }() | |
| <-stop | |
| log.Println("Shutting down gracefully...") | |
| shutdownCtx, shutdownRelease := context.WithTimeout(context.Background(), 10*time.Second) | |
| defer shutdownRelease() | |
| if err := s.Shutdown(shutdownCtx); err != nil { | |
| log.Printf("server shutdown error: %v\n", err) | |
| } | |
| log.Println("Server stoppped") | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment