BunRouter это чрезвычайно быстрый Golang router с уникальной комбинацией возможностей:
Мидлвары (middlewares) позволяют вынести общий функционал из HTTP обработчиков в отдельные функции.
Встроенная обработка ошибок позволяет снизить размер HTTP функций и обрабатывать ошибки в мидлварах.
Минималистическое и совместимое АПИ, которое не пытается делать все сразу: от обработки статичный файлов до генерации XML (
gin.Contextиecho.Contextгрешат этим).
И да, он очень быстр, хотя и уступает роутам использующим fasthttp.
Введение
По умолчанию BunRouter использует слегка улучшенную версию http.HandlerFunc, которая принимает bunrouter.Request и возвращает ошибки:
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(), }) }
Но не пугайтесь, BunRouter также умеет работать и с классическими http.HandlerFunc.
BunRouter поддерживает всего 2 типа параметров в роутах:
:paramэто именованный параметр который совпадает с одним сегментом из пути (текстом между слэшами).*paramэто "звездный" параметр, которые совпадает со всем и всегда должен идти в конце роута.
К примеру, /users/:id совпадает с /users/123 и /users/foo-bar, но не с /users/foo/bar.
Мидлвары
Мидлвары позволяют вынести общий функционал в отдельные функции, к примеру, вы можете написать мидлвар, который логирует обработанные запросы:
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) } }
Мидлвары затем может использовать следующим образом:
router.Use(middleware).WithGroup(...) // либо group = group.Use(middleware)
Обработка ошибок
Как вы уже могли заметить, обработчики BunRouter возвращают ошибки, которые вы затем можете обработать в мидлварах:
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 } }
За деталями обращайтесь к документации по HTTP error handling.
Приоритет роутов
Приоритет роутов зависит от типов параметров и сегментов и не зависит от порядка объявления роутов:
Сначала срабатывают статичные сегменты, к примеру,
/users/.Затем именованные параметры, к примеру,
:id.И в последнюю очередь "звездные" параметры, к примеру,
*path.
Для понимания рассмотрим следующие роуты отсортированные по приоритету срабатывания:
/users/list- статичный роут./users/:id- роут с именованным параметром./users/*path- роут с "звездным" параметром.
Что дальше
Чтобы начать использовать BunRouter, обращайтесь к документации или сразу попробуйте запустить примеры.
BunRouter имеет множестов плагинов, к примеру, OpenTelemetry инструментация, которая поддерживает OpenTelemetry tracing и метрики.
Используя трейсинг, вы можете мониторить производительность, используя полностью бесплатные distributed tracing tools с открытым кодом.
Вы также можете экспортировать собранные метрики в Prometheus metrics, чтобы затем отобразить их в Grafana alternatives.
