\ BunRouter is an extremely fast Golang router for Go with unique combination of features: \ * Middlewares allow to extract common operations from HTTP handlers into reusable functions. * Error handling allows to further reduce the size of HTTP handlers by handling errors in middlewares. * Routes priority enables meaningful matching priority for routing rules: first static nodes, then named nodes, lastly wildcard nodes. * net/http compatible API which means using minimal API without constructing huge wrappers that try to do everything: from serving static files to XML generation (for example, `gin.Context` or `echo.Context`). \ And yes, it is fast - see the benchmark results. ## Quickstart BunRouter uses a slightly enhanced version of http.HandlerFunc that accepts a `bunrouter.Request` and returns errors that you can handle with middlewares: \ ```go import "github.com/uptrace/bunrouter" router := bunrouter.New( bunrouter.Use(reqlog.NewMiddleware()), ) router.WithGroup("/api", func(g *bunrouter.Group) { g.GET("/users/:id", debugHandler) g.GET("/users/current", debugHandler) g.GET("/users/*path", debugHandler) }) func debugHandler(w http.ResponseWriter, req bunrouter.Request) error { // use req.Request to get *http.Request return bunrouter.JSON(w, bunrouter.H{ "route": req.Route(), "params": req.Params().Map(), }) } ``` \ But don't worry, BunRouter supports classical HTTP handlers too. \ BunRouter supports the following param types in routing rules: \ * `:param` is a named parameter that matches a single path segment (text between slashes). * `*param` is a wildcard parameter that matches everything and must always be at the end of the route. ## Middlewares Middlewares allow you to extract common functionality into a reusable function, for example, here is how you can write a middleware that logs processed requests: \ ```go func middleware(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { // you can initialize the middleware here // Return the middleware. return func(w http.ResponseWriter, req bunrouter.Request) error { rec := httptest.NewRecorder() // Pass the recorder instead of http.ResponseWriter. if err := next(rec, req); err != nil { fmt.Printf("%s %s failed: %s\n", req.Method, req.Route(), err) // Discard the error. return nil } fmt.Printf("%s %s returned %d\n", req.Method, req.Route(), rec.Code) } } ``` \ You can then install the middleware like this: \ ```go router.Use(middleware).WithGroup(...) ``` ## Error handling As you may have noticed, BunRouter's handlers return errors which you can then handle in middlewares: \ ```go func errorHandler(next bunrouter.HandlerFunc) bunrouter.HandlerFunc { return func(w http.ResponseWriter, req bunrouter.Request) error { // Call the next handler on the chain to get the error. err := next(w, req) switch err := err.(type) { case nil: // no error case HTTPError: // already a HTTPError w.WriteHeader(err.statusCode) _ = bunrouter.JSON(w, err) default: httpErr := NewHTTPError(err) w.WriteHeader(httpErr.statusCode) _ = bunrouter.JSON(w, httpErr) } return err // return the err in case there other middlewares } } ``` \ See [error handling](https://bunrouter.uptrace.dev/guide/golang-http-error-handling.html) for details. ## Routes priority Routing rules have a matching priority that is based on node types and does not depend on routes definition order: \ * Static nodes, for example, `/users/` * Named nodes, for example, `:id`. * Wildcard nodes, for example, `*path`. \ The following routes are sorted by their matching priority from the highest to the lowest: \ * `/users/list`. * `/users/:id`. * `/users/*path`. ## What's next? To get started, see the documentation and run examples. \ BunRouter comes with many plugins including OpenTelemetry instrumentation that enables distributed tracing and metrics. \ Using tracing, you can monitor performance using one of the open source tracing tools that work with OpenTelemetry. Many DataDog competitors also support OpenTelemetry. \ Besides, you can export metrics to Prometheus and visualize them using Grafana or a popular alternative.