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.

Приоритет роутов

Приоритет роутов зависит от типов параметров и сегментов и не зависит от порядка объявления роутов:

  1. Сначала срабатывают статичные сегменты, к примеру, /users/.

  2. Затем именованные параметры, к примеру, :id.

  3. И в последнюю очередь "звездные" параметры, к примеру, *path.

Для понимания рассмотрим следующие роуты отсортированные по приоритету срабатывания:

  • /users/list - статичный роут.

  • /users/:id - роут с именованным параметром.

  • /users/*path - роут с "звездным" параметром.

Что дальше

Чтобы начать использовать BunRouter, обращайтесь к документации или сразу попробуйте запустить примеры.

BunRouter имеет множестов плагинов, к примеру, OpenTelemetry инструментация, которая поддерживает distributed tracing и метрики.

Используя трейсинг, вы можете мониторить производительность, используя полностью бесплатные tracing tools с открытым кодом.

Вы также можете экспортировать собранные метрики в Prometheus, чтобы затем отобразить их в Grafana.

Комментарии (2)


  1. hello_my_name_is_dany
    19.06.2022 16:35
    +6

    И чем это решение лучше, чем тот же fiber, который тоже похож на express, но только работает над fasthttp?


    1. devalio
      20.06.2022 06:53
      -1

      кажется, автор не писал, что "это решение лучше"
      на мой взгляд, это просто мини обзор