### Complete Example: Route Grouping and Middleware Source: https://github.com/go-pkgz/routegroup/blob/master/README.md A comprehensive example demonstrating the creation of route groups, application of middleware at different levels, and handling of routes. ```go package main import ( "net/http" "github.com/go-pkgz/routegroup" ) func main() { router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware) // handle the /hello route router.Handle("GET /hello", helloHandler) // create a new group for the /api path apiRouter := router.Mount("/api") // add middleware apiRouter.Use(loggingMiddleware, corsMiddleware) // route handling apiRouter.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, API!")) }) // add another group with its own set of middlewares protectedGroup := router.Group() protectedGroup.Use(authMiddleware) protectedGroup.HandleFunc("GET /protected", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Protected API!")) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Registering Middleware on a Bundle Source: https://context7.com/go-pkgz/routegroup/llms.txt Illustrates how to add middleware to a bundle using the Use method. Middleware is applied in order and must be called before route registration. This example shows global middleware and group-specific middleware. ```go func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Printf("[LOG] %s %s (pattern: %s)\n", r.Method, r.URL.Path, r.Pattern) next.ServeHTTP(w, r) }) } func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") == "" { http.Error(w, "unauthorized", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) } func main() { router := routegroup.New(http.NewServeMux()) // Apply logging globally before registering any routes router.Use(loggingMiddleware) // Group with additional auth middleware api := router.Group() api.Use(authMiddleware) // applied to all api routes api.HandleFunc("GET /users", usersHandler) api.HandleFunc("DELETE /users/{id}", deleteUserHandler) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Create Root Bundle with Middleware and Routes Source: https://context7.com/go-pkgz/routegroup/llms.txt Demonstrates creating a root bundle using routegroup.New, applying global middleware, and registering a route. The bundle itself is an http.Handler suitable for http.ListenAndServe. ```go package main import ( "fmt" "net/http" "github.com/go-pkgz/routegroup" ) func main() { mux := http.NewServeMux() router := routegroup.New(mux) router.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("request:", r.Method, r.URL.Path) next.ServeHTTP(w, r) }) }) router.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }) // router itself is http.Handler http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Manage Middleware Scope with Use and With Source: https://context7.com/go-pkgz/routegroup/llms.txt Demonstrates middleware ordering rules. `Use` applies global middleware before any routes are registered (panics otherwise). `With` or `Group` can be used to attach scoped middleware after routes have been registered on the parent bundle. ```go func main() { mux := http.NewServeMux() router := routegroup.New(mux) // ✅ Global middleware before any routes router.Use(loggingMiddleware) // ✅ Public route on root router.HandleFunc("GET /health", healthHandler) // ✅ With() is safe after root routes — returns a new bundle router.With(authMiddleware).HandleFunc("GET /me", meHandler) // ✅ Child group's Use is independent of root's locked state admin := router.Group() admin.Use(adminMiddleware) // fine — no routes on admin yet admin.HandleFunc("GET /admin", adminHandler) // ❌ This would panic — routes already registered on router: // router.Use(someOtherMiddleware) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Serve Static Files with HandleFiles Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Serves static files from a specified directory using a route prefix. This is a convenient wrapper around http.FileServer. ```go router.HandleFiles("/static/", http.Dir("assets/static")) ``` -------------------------------- ### Create and Derive Route Groups with Middlewares Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Demonstrates creating a base router with common middlewares and deriving child groups that inherit these middlewares. Use this to ensure all routes share foundational middleware like logging or CORS. ```go router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware, corsMiddleware) apiGroup := router.Group() apiGroup.Use(apiMiddleware) apiGroup.Handle("GET /hello", helloHandler) apiGroup.Handle("GET /bye", byeHandler) router.Mount("/admin").Route(func(b *routegroup.Bundle) { b.Use(adminMiddleware) b.Handle("POST /do", doHandler) }) http.ListenAndServe(":8080", router) ``` -------------------------------- ### Serve Static Files with Bundle.HandleFiles Source: https://context7.com/go-pkgz/routegroup/llms.txt HandleFiles wraps http.FileServer to serve static files from a directory, automatically stripping the path prefix. It can be used on the root router or mounted groups. ```go func main() { router := routegroup.New(http.NewServeMux()) // Serve files from ./assets/static under /static/ router.HandleFiles("/static/", http.Dir("assets/static")) // e.g., GET /static/app.js → serves ./assets/static/app.js // Can also be used on a mounted group adminRouter := router.Mount("/admin") adminRouter.Use(authMiddleware) adminRouter.HandleFiles("/assets/", http.Dir("admin/dist")) // e.g., GET /admin/assets/style.css → serves ./admin/dist/style.css http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Create New Route Group Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Initialize a new route group with an http.ServeMux. No base path is set initially. ```go func main() { mux := http.NewServeMux() group := routegroup.New(mux) } ``` -------------------------------- ### Create Static File Server Handler Source: https://github.com/go-pkgz/routegroup/blob/master/README.md This function returns an http.HandlerFunc that serves static files from the embedded "assets/static" directory. It uses http.StripPrefix to handle URL paths correctly. Ensure the 'assets' variable is accessible and contains the embedded file system. ```go func (s *Service) fileServerHandlerFunc() http.HandlerFunc { staticFS, err := fs.Sub(assets, "assets/static") // error is always nil if err != nil { panic(err) // should never happen we load from embedded FS } return func(w http.ResponseWriter, r *http.Request) { webFS := http.StripPrefix(s.rootURL+"/static/", http.FileServer(http.FS(staticFS))) webFS.ServeHTTP(w, r) } } ``` -------------------------------- ### Define Service Routes with Middleware and Static File Serving Source: https://github.com/go-pkgz/routegroup/blob/master/README.md This function sets up all routes for a service, including authentication, user management, and admin functionalities. It applies common middlewares and serves static files from an embedded file system. Use this to configure the main routing for your application. ```go func (s *Service) Routes() http.Handler { router := routegroup.Mount(http.NewServeMux(), s.rootURL) // make a bundle with the rootURL base path // add common middlewares router.Use(rest.Maybe(handlers.CompressHandler, func(*http.Request) bool { return !s.skipGZ })) router.Use(rest.Throttle(s.limitActiveReqs)) router.Use(s.middleware.securityHeaders(s.skipSecurityHeaders)) // prepare csrf middleware csrfMiddleware := s.middleware.csrf(s.skipCSRFCheck) // add open routes router.HandleFunc("GET /login", s.loginPageHandler) router.HandleFunc("POST /login", s.loginCheckHandler) router.HandleFunc("GET /logout", s.logoutHandler) // add routes with auth middleware router.Group().Route(func(auth *routegroup.Bundle) { auth.Use(s.middleware.Auth()) auth.HandleFunc("GET /update", s.pwdUpdateHandler) auth.With(csrfMiddleware).HandleFunc("PUT /update", s.pwdUpdateHandler) }) // add admin routes router.Mount("/admin").Route(func(admin *routegroup.Bundle) { admin.Use(s.middleware.Auth("admin")) admin.Use(s.middleware.AdminOnly) admin.HandleFunc("GET /", s.admin.renderHandler) admin.With(csrfMiddleware).Route(func(csrf *routegroup.Bundle) { crsf.HandleFunc("DELETE /sessions", s.admin.deleteSessionsHandler) crsf.HandleFunc("POST /user", s.admin.addUserHandler) crsf.HandleFunc("DELETE /user", s.admin.deleteUserHandler) }) }) router.HandleFunc("GET /static/*", s.fileServerHandlerFunc()) // serve static files return router } ``` -------------------------------- ### Create Root Bundle with Base Path Prefix Source: https://context7.com/go-pkgz/routegroup/llms.txt Shows how to create a root bundle with a base path prefix using routegroup.Mount. All routes registered on this bundle will be automatically prefixed with the specified path. ```go func main() { // All routes on this bundle will be under /api router := routegroup.Mount(http.NewServeMux(), "/api") router.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) { // handles GET /api/users w.Write([]byte(`[{"id":1,"name":"Alice"}]`)) }) router.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) { // handles POST /api/users w.WriteHeader(http.StatusCreated) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Bundle.Use Source: https://context7.com/go-pkgz/routegroup/llms.txt Adds one or more middleware functions to the bundle's stack. Middleware is applied in the order added. Must be called before any route registration on the same bundle. ```APIDOC ## Bundle.Use ### Description Adds one or more middleware functions to the bundle's stack. Middleware is applied in the order added. **Must be called before any route registration on the same bundle** — calling `Use` after routes panics. ### Method `func (b *Bundle) Use(middleware ...func(http.Handler) http.Handler)` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Printf("[LOG] %s %s (pattern: %s)\n", r.Method, r.URL.Path, r.Pattern) next.ServeHTTP(w, r) }) } func authMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get("Authorization") == "" { http.Error(w, "unauthorized", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) } func main() { router := routegroup.New(http.NewServeMux()) // Apply logging globally before registering any routes router.Use(loggingMiddleware) // Group with additional auth middleware api := router.Group() api.Use(authMiddleware) // applied to all api routes api.HandleFunc("GET /users", usersHandler) api.HandleFunc("DELETE /users/{id}", deleteUserHandler) http.ListenAndServe(":8080", router) } ``` ### Response #### Success Response (200) None #### Response Example None ``` -------------------------------- ### Bundle.HandleFiles Source: https://context7.com/go-pkgz/routegroup/llms.txt Serve static files from a directory. Helper that wraps `http.FileServer` and registers a static file handler on the bundle, automatically stripping the path prefix. ```APIDOC ## Bundle.HandleFiles — Serve static files from a directory Helper that wraps `http.FileServer` and registers a static file handler on the bundle, automatically stripping the path prefix. ### Method Signature `func (b *Bundle) HandleFiles(path string, root http.FileSystem)` ### Parameters - **path** (string) - The URL path prefix, e.g., `"/static/"`. - **root** (http.FileSystem) - The file system root, e.g., `http.Dir("assets/static")`. ### Example Usage ```go router.HandleFiles("/static/", http.Dir("assets/static")) adminRouter.HandleFiles("/assets/", http.Dir("admin/dist")) ``` ``` -------------------------------- ### Create New Bundle with Scoped Middleware using With Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `With` to create a new bundle with additional middleware. This is safe to use after routes have been registered on the parent bundle, as it does not modify the original. ```go func main() { router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware) // Register a public route on router router.HandleFunc("GET /health", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("ok")) }) // With returns a new bundle — safe to use after routes are on router router.With(authMiddleware).HandleFunc("GET /profile", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("private profile")) }) // Chain multiple middlewares inline router.With(authMiddleware, csrfMiddleware).HandleFunc("POST /profile", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Handle Root Path with Bundle.HandleRoot/HandleRootFunc Source: https://context7.com/go-pkgz/routegroup/llms.txt Use HandleRoot or HandleRootFunc to register a handler for a bundle's exact base path, avoiding the default 301 redirect for root paths. Supports different HTTP methods. ```go func main() { router := routegroup.New(http.NewServeMux()) api := router.Mount("/api") v1 := api.Mount("/v1") users := v1.Mount("/users") // GET /api — no redirect from /api/ api.HandleRoot("GET", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"message":"API root"}`)) })) // GET /api/v1/users — direct match, no trailing-slash redirect users.HandleRoot("GET", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`{"users":[]}`)) })) // POST /api/v1/users — different method on same path users.HandleRootFunc("POST", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":"new"}`)) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Derive Child Bundle with Path Prefix using Mount Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `Mount` to create a new bundle that inherits middleware and appends a path prefix. Routes registered on the returned bundle are prefixed with the combined base path. ```go func main() { router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware) // /api group api := router.Mount("/api") api.Use(corsMiddleware) // /api/v1 sub-group v1 := api.Mount("/v1") v1.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) { // handles GET /api/v1/users w.Write([]byte(`{"version":"v1","users":[]}`)) }) // /api/v2 sub-group v2 := api.Mount("/v2") v2.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) { // handles GET /api/v2/users w.Write([]byte(`{"version":"v2","users":[]}`)) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Panic: Calling Use After Routes Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Demonstrates an incorrect usage where `Use` is called after routes have been registered on the same bundle, which will result in a panic. ```go mux := http.NewServeMux() router := routegroup.New(mux) router.HandleFunc("/r", func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusOK) }) // This will panic: Use called after routes were registered on this bundle router.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // global header w.Header().Set("X-Global", "true") next.ServeHTTP(w, r) }) }) ``` -------------------------------- ### Preferred: Scoped Middleware with With Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Illustrates the preferred method of adding scoped middleware using `With`. This creates a new bundle where middleware can be added before registering routes, preventing interference with existing routes. ```go mux := http.NewServeMux() router := routegroup.New(mux) // Global middleware (optional), add before any root routes router.Use(loggingMiddleware) // Scoped middleware using With: returns a new bundle on which we can add routes api := router.With(authMiddleware) api.HandleFunc("GET /items", itemsHandler) api.HandleFunc("POST /items", createItem) // Or using Group + Use before routes admin := router.Group() admin.Use(adminOnly) admin.HandleFunc("GET /dashboard", dashboardHandler) ``` -------------------------------- ### Configure Bundle using Callback Function with Route Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `Route` to pass the bundle into a configuration function. This is useful for organizing route definitions and co-locating middleware and routes. ```go func main() { router := routegroup.New(http.NewServeMux()) // On the root bundle, Route auto-creates a child group router.Route(func(b *routegroup.Bundle) { b.Use(loggingMiddleware, corsMiddleware) b.HandleFunc("GET /hello", helloHandler) b.HandleFunc("GET /bye", byeHandler) }) // Chain Mount + Route for mounted groups router.Mount("/admin").Route(func(admin *routegroup.Bundle) { admin.Use(authMiddleware, adminOnlyMiddleware) admin.HandleFunc("GET /", adminDashboardHandler) admin.HandleFunc("DELETE /users/{id}", deleteUserHandler) // Nested scoped group using With inside Route admin.With(csrfMiddleware).Route(func(csrf *routegroup.Bundle) { csrf.HandleFunc("POST /users", createUserHandler) csrf.HandleFunc("PUT /users/{id}", updateUserHandler) }) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### routegroup.New Source: https://context7.com/go-pkgz/routegroup/llms.txt Creates a new root Bundle that wraps an existing http.ServeMux. The returned bundle implements http.Handler and can be passed directly to http.ListenAndServe. ```APIDOC ## routegroup.New ### Description Creates a new root `Bundle` backed by the provided `*http.ServeMux`. The returned bundle implements `http.Handler` and can be passed directly to `http.ListenAndServe`. ### Method `routegroup.New(mux *http.ServeMux) *routegroup.Bundle` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go package main import ( "fmt" "net/http" "github.com/go-pkgz/routegroup" ) func main() { mux := http.NewServeMux() router := routegroup.New(mux) router.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("request:", r.Method, r.URL.Path) next.ServeHTTP(w, r) }) }) router.HandleFunc("GET /hello", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello, World!")) }) // router itself is http.Handler http.ListenAndServe(":8080", router) } ``` ### Response #### Success Response (200) None (returns an http.Handler) #### Response Example None ``` -------------------------------- ### Add Routes with Middleware Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Apply middleware to a route group and then add individual routes. Middleware is applied to all routes within the group. ```go group.Use(loggingMiddleware, corsMiddleware) group.Handle("/hello", helloHandler) group.Handle("/bye", byeHandler) ``` -------------------------------- ### Handle Root Paths Without Trailing Slashes Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Demonstrates how to use `HandleRoot` and `HandleRootFunc` to manage requests to the root path of mounted groups without a trailing slash. This avoids redirects, especially for non-GET requests. ```go // Create mounted groups apiGroup := router.Mount("/api") v1Group := apiGroup.Mount("/v1") usersGroup := v1Group.Mount("/users") // Handle the root paths (no trailing slashes) apiGroup.HandleRoot("GET", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // This handles requests to "/api" (without trailing slash) w.Write([]byte("API Documentation")) })) usersGroup.HandleRoot("GET", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // This handles requests to "/api/v1/users" (without trailing slash) w.Write([]byte("List users")) })) // Different HTTP methods can be handled separately usersGroup.HandleRoot("POST", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // This handles POST requests to "/api/v1/users" w.Write([]byte("Create user")) })) ``` -------------------------------- ### Derive Child Bundle with Shared Base Path and Middleware using Group Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `Group` to create a new bundle that inherits the parent's base path and middleware. Additional middleware can be added to the child without affecting the parent. ```go func main() { router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware) // Public routes directly on router router.HandleFunc("GET /login", loginHandler) // Authenticated group — inherits loggingMiddleware, adds authMiddleware authed := router.Group() authed.Use(authMiddleware) authed.HandleFunc("GET /dashboard", dashboardHandler) authed.HandleFunc("GET /settings", settingsHandler) // Admin group — adds further restriction on top of authed admin := authed.Group() // inherits logging + auth admin.Use(adminOnlyMiddleware) admin.HandleFunc("GET /admin/users", listUsersHandler) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Bundle.HandleRoot / Bundle.HandleRootFunc Source: https://context7.com/go-pkgz/routegroup/llms.txt Handle a mounted group's root path without redirect. Registers a handler for the bundle's exact base path, avoiding the `301` redirect that `"/"` patterns trigger. ```APIDOC ## Bundle.HandleRoot / Bundle.HandleRootFunc — Handle a mounted group's root path without redirect Registers a handler for the bundle's exact base path (without trailing slash), avoiding the `301` redirect that `"/"` patterns trigger in `http.ServeMux`. ### Method Signatures `func (b *Bundle) HandleRoot(method string, handler http.Handler)` `func (b *Bundle) HandleRootFunc(method string, handler func(http.ResponseWriter, *http.Request))` ### Parameters - **method** (string) - The HTTP method, e.g., `"GET"`, `"POST"`. - **handler** (http.Handler or func(http.ResponseWriter, *http.Request)) - The handler or handler function to register. ### Example Usage ```go api.HandleRoot("GET", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ... })) users.HandleRootFunc("POST", func(w http.ResponseWriter, r *http.Request) { ... }) ``` ``` -------------------------------- ### Bundle.Handle Source: https://context7.com/go-pkgz/routegroup/llms.txt Registers an http.Handler for the given pattern, wrapping it with the bundle's middleware stack. Supports Go 1.22 method+path syntax. ```APIDOC ## Bundle.Handle — Register an `http.Handler` on the bundle Registers an `http.Handler` for the given pattern, wrapping it with the bundle's middleware stack. Supports Go 1.22 method+path syntax (`"GET /path"`). ### Method Signature `func (b *Bundle) Handle(pattern string, handler http.Handler)` ### Parameters - **pattern** (string) - The route pattern, e.g., `"GET /users/{id}"`. - **handler** (http.Handler) - The handler to register. ### Example Usage ```go api.Handle("GET /users/{id}", &userHandler{}) api.Handle("POST /users", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ... })) ``` ``` -------------------------------- ### routegroup.Mount Source: https://context7.com/go-pkgz/routegroup/llms.txt Creates a root Bundle with a base path prefix, so all routes registered on it are automatically prefixed. ```APIDOC ## routegroup.Mount ### Description Package-level constructor that creates a `Bundle` with a base path, so all routes registered on it are automatically prefixed. ### Method `routegroup.Mount(mux *http.ServeMux, basePath string) *routegroup.Bundle` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go func main() { // All routes on this bundle will be under /api router := routegroup.Mount(http.NewServeMux(), "/api") router.HandleFunc("GET /users", func(w http.ResponseWriter, r *http.Request) { // handles GET /api/users w.Write([]byte(`[{"id":1,"name":"Alice"}]`)) }) router.HandleFunc("POST /users", func(w http.ResponseWriter, r *http.Request) { // handles POST /api/users w.WriteHeader(http.StatusCreated) }) http.ListenAndServe(":8080", router) } ``` ### Response #### Success Response (200) None (returns an http.Handler) #### Response Example None ``` -------------------------------- ### Apply Middleware to Specific Routes Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Apply middleware to individual routes within a group using the `With` method, without affecting the group's main middleware stack. ```go apiGroup.With(corsMiddleware, apiMiddleware).Handle("GET /hello", helloHandler) ``` -------------------------------- ### Register http.HandlerFunc with Bundle.HandleFunc Source: https://context7.com/go-pkgz/routegroup/llms.txt HandleFunc is a convenience method for registering a plain function as a handler. Middleware applied to the bundle will wrap the handler. Supports Go 1.22 path parameter syntax. ```go func main() { router := routegroup.New(http.NewServeMux()) api := router.Mount("/api") api.Use(loggingMiddleware) api.HandleFunc("GET /items", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Write([]byte(`[{"id":1,"name":"widget"}]`)) }) api.HandleFunc("GET /items/{id}", func(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") // Go 1.22+ path parameter w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `{"id":"%s","name":"widget"}`, id) }) api.HandleFunc("DELETE /items/{id}", func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNoContent) }) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Create Nested Route Group with Mount Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Use the Mount method to create a nested route group with a specific path prefix. Middleware can be applied to this nested group. ```go apiGroup := routegroup.Mount(mux, "/api") apiGroup.Use(loggingMiddleware, corsMiddleware) apiGroup.Handle("/v1", apiV1Handler) apiGroup.Handle("/v2", apiV2Handler) ``` -------------------------------- ### Allowed: Parent Use After Child Routes Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Shows a valid scenario where a parent router's `Use` method is called after child bundle routes are registered. This is allowed because the parent has not registered its own routes yet and the middleware will apply globally. ```go mux := http.NewServeMux() router := routegroup.New(mux) child := router.Group() child.HandleFunc("/child", func(w http.ResponseWriter, _ *http.Request) { w.Write([]byte("ok")) }) // Parent has not registered its own routes yet; this is allowed and will apply globally router.Use(func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("X-Parent", "true") next.ServeHTTP(w, r) }) }) ``` -------------------------------- ### Alternative Usage with Route Bundle Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Use the `Route` method to define middleware and routes within a callback function. This creates an isolated group. ```go router := routegroup.New(http.NewServeMux()) router.Route(func(b *routegroup.Bundle) { b.Use(loggingMiddleware, corsMiddleware) b.Handle("GET /hello", helloHandler) b.Handle("GET /bye", byeHandler) }) http.ListenAndServe(":8080", router) ``` -------------------------------- ### Register http.Handler with Bundle.Handle Source: https://context7.com/go-pkgz/routegroup/llms.txt Use Handle to register an http.Handler implementation for a given pattern. Supports Go 1.22 method+path syntax. Middleware applied to the bundle will wrap the handler. ```go type userHandler struct{} func (h *userHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { id := r.PathValue("id") fmt.Fprintf(w, `{"id":"%s"}`, id) } func main() { router := routegroup.New(http.NewServeMux()) api := router.Mount("/api") api.Use(loggingMiddleware) // Register http.Handler implementations api.Handle("GET /users/{id}", &userHandler{}) // Handler with method constraint api.Handle("POST /users", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusCreated) w.Write([]byte(`{"id":"new"}`)) })) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Bundle.NotFoundHandler Source: https://context7.com/go-pkgz/routegroup/llms.txt Set a custom 404 handler. Registers a custom handler for requests that match no route. ```APIDOC ## Bundle.NotFoundHandler — Set a custom 404 handler Registers a custom handler for requests that match no route. Only invoked for true `404 Not Found` — requests to valid paths with wrong methods still return the native `405 Method Not Allowed` with the `Allow` header intact. ### Method Signature `func (b *Bundle) NotFoundHandler(handler http.Handler)` ### Parameters - **handler** (http.Handler) - The custom 404 handler. ### Example Usage ```go router.NotFoundHandler(func(w http.ResponseWriter, r *http.Request) { ... }) ``` ``` -------------------------------- ### Bundle.HandleFunc Source: https://context7.com/go-pkgz/routegroup/llms.txt Convenience method to register a plain function as a handler, wrapping it with the bundle's middleware stack. ```APIDOC ## Bundle.HandleFunc — Register an `http.HandlerFunc` on the bundle Convenience method to register a plain function as a handler, wrapping it with the bundle's middleware stack. ### Method Signature `func (b *Bundle) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))` ### Parameters - **pattern** (string) - The route pattern, e.g., `"GET /items/{id}"`. - **handler** (func(http.ResponseWriter, *http.Request)) - The handler function to register. ### Example Usage ```go api.HandleFunc("GET /items", func(w http.ResponseWriter, r *http.Request) { ... }) api.HandleFunc("GET /items/{id}", func(w http.ResponseWriter, r *http.Request) { ... }) ``` ``` -------------------------------- ### Set Custom 404 Handler with Bundle.NotFoundHandler Source: https://context7.com/go-pkgz/routegroup/llms.txt NotFoundHandler registers a custom handler for requests that result in a 404 Not Found status. Global middlewares applied to the bundle are also applied to this custom handler. ```go func main() { router := routegroup.New(http.NewServeMux()) router.Use(loggingMiddleware) router.HandleFunc("GET /hello", helloHandler) // Custom 404 — global middlewares are applied to this handler too router.NotFoundHandler(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusNotFound) fmt.Fprintf(w, `{"error":"route %s %s not found"}`, r.Method, r.URL.Path) }) // GET /hello → 200 from helloHandler // POST /hello → 405 Method Not Allowed (native mux behavior, NOT custom 404) // GET /unknown → 404 from custom NotFoundHandler (with loggingMiddleware applied) http.ListenAndServe(":8080", router) } ``` -------------------------------- ### Set Custom NotFoundHandler Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Configure a custom handler to be executed when no route matches the incoming request. This handler will have global middlewares applied. ```go group.NotFoundHandler(func(w http.ResponseWriter, _ *http.Request) { http.Error(w, "404 page not found, something is wrong!", http.StatusNotFound) } ``` -------------------------------- ### Apply Middleware to a Single Handler with routegroup.Wrap Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `routegroup.Wrap` to apply one or more middlewares to an `http.Handler` without creating a bundle. This is useful when only a single route requires middleware. ```go func main() { mux := http.NewServeMux() // Apply middlewares to a single handler directly on the stdlib mux mux.HandleFunc("/public", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("public")) }) mux.Handle("/private", routegroup.Wrap( http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("private")) }), loggingMiddleware, authMiddleware, // additional middlewares applied in order... )) http.ListenAndServe(":8080", mux) } ``` -------------------------------- ### Introspect Handler and Pattern with Bundle.Handler Source: https://context7.com/go-pkgz/routegroup/llms.txt Use `router.Handler(req)` to look up the handler and pattern for a given request. This is useful for introspection in tests or for middleware that needs the matched route information. ```go func main() { router := routegroup.New(http.NewServeMux()) router.HandleFunc("GET /users/{id}", userHandler) // Introspect routing in tests or middleware req := httptest.NewRequest("GET", "/users/42", nil) h, pattern := router.Handler(req) fmt.Println(pattern) // "GET /users/{id}" _ = h } ``` -------------------------------- ### Wrap Single HTTP Handler with Middlewares Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Applies one or more middlewares to a single http.Handler without creating a route group. Useful for applying specific middleware to an isolated route. ```go mux := http.NewServeMux() mux.HandleFunc("/hello", routegroup.Wrap(helloHandler, loggingMiddleware, corsMiddleware)) http.ListenAndServe(":8080", mux) ``` -------------------------------- ### Functional Style Route Grouping Source: https://github.com/go-pkgz/routegroup/blob/master/README.md Chain the `Route` method after `Group` for a functional style of defining isolated route groups with their own middleware. ```go router := routegroup.New(http.NewServeMux()) router.Group().Route(func(b *routegroup.Bundle) { b.Use(loggingMiddleware, corsMiddleware) b.Handle("GET /hello", helloHandler) b.Handle("GET /bye", byeHandler) }) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.