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 инструментация, которая поддерживает distributed tracing и метрики.
Используя трейсинг, вы можете мониторить производительность, используя полностью бесплатные tracing tools с открытым кодом.
Вы также можете экспортировать собранные метрики в Prometheus, чтобы затем отобразить их в Grafana.
hello_my_name_is_dany
И чем это решение лучше, чем тот же fiber, который тоже похож на express, но только работает над fasthttp?
devalio
кажется, автор не писал, что "это решение лучше"
на мой взгляд, это просто мини обзор