Routing
The λ Cosmos router builds on Go’s http.ServeMux and adds middleware composition, route groups, and generics support. In the framework package, the router is pre-configured with the Cosmos Handler type (handlers that return error).
type Router = router.Router[Handler]
type Middleware = router.Middleware[Handler]// which expands to: func(Handler) HandlerCreating a Router
Section titled “Creating a Router”import "github.com/studiolambda/cosmos/framework"
app := framework.New()This returns a *framework.Router, which is an alias for router.Router[framework.Handler]. It implements http.Handler so you can pass it directly to http.ListenAndServe.
Registering Routes
Section titled “Registering Routes”Register routes using HTTP method helpers:
app.Get("/users", listUsers)app.Post("/users", createUser)app.Get("/users/{id}", getUser)app.Put("/users/{id}", updateUser)app.Delete("/users/{id}", deleteUser)All standard HTTP methods are available: Get, Post, Put, Patch, Delete, Head, Options, Connect, Trace. There’s also Any for catching all methods and Method/Methods for custom method lists:
app.Any("/health", healthCheck)app.Method("PURGE", "/cache/{key}", purgeCache)app.Methods([]string{"GET", "HEAD"}, "/status", statusHandler)Path Parameters
Section titled “Path Parameters”Path parameters use Go’s standard {name} syntax:
app.Get("/users/{id}", func(w http.ResponseWriter, r *http.Request) error { id := r.PathValue("id") // ...})Wildcard parameters capture the rest of the path:
app.Get("/files/{path...}", func(w http.ResponseWriter, r *http.Request) error { path := r.PathValue("path") // e.g. "images/photo.jpg" // ...})Trailing Slashes
Section titled “Trailing Slashes”The router automatically handles trailing slash normalization. When you register /users, both /users and /users/ will match. This is handled transparently — you don’t need to register both patterns.
Route Groups
Section titled “Route Groups”Groups let you organize routes under a common prefix and share middleware:
api := app.Group("/api")api.Use(authMiddleware)
api.Get("/users", listUsers) // matches /api/usersapi.Get("/users/{id}", getUser) // matches /api/users/{id}Groups can be nested:
v1 := api.Group("/v1")v1.Get("/items", listItemsV1) // matches /api/v1/items
v2 := api.Group("/v2")v2.Get("/items", listItemsV2) // matches /api/v2/itemsGrouped Helper
Section titled “Grouped Helper”For inline group definitions, use Grouped:
app.Grouped("/admin", func(admin *framework.Router) { admin.Use(adminAuth) admin.Get("/dashboard", dashboard) admin.Get("/settings", settings)})This is equivalent to calling Group followed by the route registrations, but keeps the group scope visually contained.
Middleware
Section titled “Middleware”Middleware wraps handlers to add cross-cutting behavior. A Middleware is a function that takes a handler and returns a new handler:
type Middleware = func(Handler) HandlerApply middleware to a router or group with Use:
app.Use(middleware.Recover())app.Use(middleware.Logger(logger))Middleware runs in the order it’s registered. Apply middleware to a specific route by wrapping it inline with With:
app.Get("/admin", app.With(adminAuth)(adminHandler))See the Middleware page for the full list of built-in middleware.
Cloning
Section titled “Cloning”The Clone method creates a shallow copy of a router with the same prefix but independent middleware:
clone := app.Clone()clone.Use(extraMiddleware)// The original app is unaffectedUsing the Router Standalone
Section titled “Using the Router Standalone”If you don’t need the full framework (error-returning handlers, hooks), you can use the router module directly with any http.Handler implementation:
import "github.com/studiolambda/cosmos/router"
r := router.New[http.HandlerFunc]()
r.Get("/hello", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello"))})
http.ListenAndServe(":8080", r)The router is generic over any type that implements http.Handler, so you can use it with custom handler types in projects that don’t use the Cosmos framework layer.