erouter
erouter — это высокопроизводительная и расширяемая библиотека http-маршрутизации с нулевым копированием памяти, строгим порядком сопоставления маршрутизации, низким дублированием кода, групповой маршрутизацией, функциями промежуточного программного обеспечения, параметрами по умолчанию, сопоставлением констант, сопоставлением переменных, сопоставлением подстановочных знаков, сопоставлением проверки переменных, подстановочными знаками. Проверьте сопоставление и маршрутизацию на основе хоста.
на основеeudoreРазделение маршрутов фреймворка, модификация механизма промежуточного программного обеспечения и удаление MVC.
RouterRadix
RouterRadix реализован с использованием radix-дерева, с нулевым копированием памяти, строгим порядком сопоставления маршрутизации, групповой маршрутизацией, функциями промежуточного программного обеспечения, параметрами по умолчанию, сопоставлением констант, сопоставлением переменных и функциями сопоставления подстановочных знаков.
example:
package main
import "log"
import "net/http"
import "github.com/eudore/erouter"
func main() {
router := erouter.NewRouterRadix()
router.AddMiddleware("ANY", "", func(h erouter.Handler) erouter.Handler {
return func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
log.Printf("%s %s route: %s", r.Method, r.URL.Path, p.GetParam("route"))
h(w, r, p)
}
})
router.Any("/*", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("hello\n"))
})
router.Get("/api/*action version=v0", func(w http.ResponseWriter, _ *http.Request, p erouter.Params) {
w.Write([]byte("access api " + p.GetParam("version") +": " + p.GetParam("action") + "\n"))
})
router.Get("/api/v1/*action version=v1", func(w http.ResponseWriter, _ *http.Request, p erouter.Params) {
w.Write([]byte("access api " + p.GetParam("version") +": " + p.GetParam("action") + "\n"))
})
apiv2 := router.Group("/api/v2 version=v2")
apiv2.Any("/*action", func(w http.ResponseWriter, _ *http.Request, p erouter.Params) {
w.Write([]byte("access api " + p.GetParam("version") +": " + p.GetParam("action") + "\n"))
})
http.ListenAndServe(":8080", router)
}
Тестовая команда:
curl 127.0.0.1:8080/get
curl 127.0.0.1:8080/api/getuser
curl 127.0.0.1:8080/api/v1/getuser
curl 127.0.0.1:8080/api/v2/getuser
RouterFull
Основанный на расширении RouterRadix, RouterFull реализует функции проверки и сопоставления переменных, а также проверки и сопоставления с подстановочными знаками.
Использование: после обычных переменных и подстановочных знаков используйте символ «|» для разделения, за которым следует правило проверки, isnum — функция проверки, min:100 — функция динамической проверки, min — имя функции динамической проверки, а ':' - это параметр; если он начинается с '^', это обычная проверка и заканчивается '$'.
Примечание. Не используйте пробелы в регулярных выражениях, это приведет к ошибкам сегментации параметров, используйте \u002 вместо пробелов.
:num|isnum
:num|min:100
:num|^0.*$
*num|isnum
*num|min:100
*num|^0.*$
example:
package main
import "net/http"
import "github.com/eudore/erouter"
func main() {
router := erouter.NewRouterFull()
router.Any("/*", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("hello\n"))
})
router.Get("/:num|^0.*$", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("first char is '0', num is: " + p.GetParam("num") + "\n"))
})
router.Get("/:num|min:100", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("num great 100, num is: " + p.GetParam("num") + "\n"))
})
router.Get("/:num|isnum", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("num is: " + p.GetParam("num") + "\n"))
})
router.Get("/*var|^E.*$", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("first char is 'E', var is: " + p.GetParam("var") + "\n"))
})
http.ListenAndServe(":8080", router)
}
Тестовая команда:
curl 127.0.0.1:8080/get
curl 127.0.0.1:8080/012
curl 127.0.0.1:8080/123
curl 127.0.0.1:8080/12
curl 127.0.0.1:8080/Erouter/123
RouterHost
RouterHost основан на сопоставлении узлов и реализует функцию маршрутизации на основе узлов путем выбора соответствующего подмаршрутизатора узла для выполнения регистрации и сопоставления.
В настоящее время используется сопоставление обхода, функция сопоставления хостаpath.Match, будущие правила сопоставления сохраняют только подстановочные знаки '*' и константы.
Использование: вам необходимо зарегистрировать подмаршрутизаторы в соответствии с правилами доменного имени для хост-маршрутизатора.При регистрации маршрутов используйте параметр хоста для сопоставления зарегистрированных маршрутизаторов для добавления маршрутов и используйте запрошенный хост для сопоставления зарегистрированных маршрутов при сопоставлении.
example:
package main
import "net/http"
import "github.com/eudore/erouter"
func main() {
router := erouter.NewRouterHost().(*erouter.RouterHost)
router.RegisterHost("*.example.com", erouter.NewRouterRadix())
router.Any("/*", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("hello\n"))
})
router.Get("/* host=*.example.com", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
w.Write([]byte("host is " + r.Host + ", match host: " + p.GetParam("host") + "\n"))
})
http.ListenAndServe(":8080", router)
}
Тестовая команда:
curl 127.0.0.1:8080
curl -XPUT 127.0.0.1:8080
curl -H 'Host: www.example.com' 127.0.0.1:8080
curl -H 'Host: www.example.com' -XPUT 127.0.0.1:8080
curl -H 'Host: www.example.com' -Xput 127.0.0.1:8080
Benchmark
Используйте GithubApi дляКонтрольный тест производительности, производительность сопоставления Erouter составляет всего 60% от производительности httprouter, но он обладает характеристиками строгого порядка сопоставления маршрутизации, простоты расширения и перезаписи и низкой сложности кода.
Тестовая команда:
go get github.com/eudore/web-framework-benchmark
go test -bench=router github.com/eudore/web-framework-benchmark
Результаты теста:
goos: linux
goarch: amd64
pkg: github.com/eudore/web-framework-benchmark
BenchmarkHttprouterStatic-2 50000 25518 ns/op 1949 B/op 157 allocs/op
BenchmarkHttprouterGitHubAPI-2 30000 57961 ns/op 16571 B/op 370 allocs/op
BenchmarkHttprouterGplusAPI-2 500000 2747 ns/op 813 B/op 24 allocs/op
BenchmarkHttprouterParseAPI-2 300000 3886 ns/op 963 B/op 42 allocs/op
BenchmarkErouterRadixStatic-2 30000 44147 ns/op 2412 B/op 157 allocs/op
BenchmarkErouterRadixGitHubAPI-2 20000 63756 ns/op 2501 B/op 203 allocs/op
BenchmarkErouterRadixGplusAPI-2 500000 2653 ns/op 173 B/op 13 allocs/op
BenchmarkErouterRadixParseAPI-2 300000 4523 ns/op 323 B/op 26 allocs/op
BenchmarkErouterFullStatic-2 30000 43923 ns/op 2413 B/op 157 allocs/op
BenchmarkErouterFullGitHubAPI-2 20000 65698 ns/op 2503 B/op 203 allocs/op
BenchmarkErouterFullGplusAPI-2 500000 2582 ns/op 173 B/op 13 allocs/op
BenchmarkErouterFullParseAPI-2 300000 5990 ns/op 323 B/op 26 allocs/op
PASS
ok github.com/eudore/web-framework-benchmark 19.934s
Api
Перечисляет основные используемые методы, конкретные ссылкиДокументация.
Определение интерфейса маршрутизатора:
type (
// Params读写请求处理中的参数。
Params interface {
GetParam(string) string
AddParam(string, string)
SetParam(string, string)
}
// Erouter处理一个请求的方法,在http.HandlerFunc基础上增加了Parmas。
Handler func(http.ResponseWriter, *http.Request, Params)
// 定义请求处理中间件函数,通过传入处理然后返回一个处理,使用装饰器组装处理请求。
Middleware func(Handler) Handler
// The route is directly registered by default. Other methods can be directly registered using the RouterRegister interface.
//
// 路由默认直接注册的方法,其他方法可以使用RouterRegister接口直接注册。
RouterMethod interface {
Group(string) RouterMethod
AddHandler(string, string, Handler) RouterMethod
AddMiddleware(string, string, ...Middleware) RouterMethod
NotFound(Handler)
MethodNotAllowed(Handler)
Any(string, Handler)
Delete(string, Handler)
Get(string, Handler)
Head(string, Handler)
Options(string, Handler)
Patch(string, Handler)
Post(string, Handler)
Put(string, Handler)
}
// Router core interface, performing routing, middleware registration, and processing http requests.
//
// 路由器核心接口,执行路由、中间件的注册和处理http请求。
RouterCore interface {
RegisterMiddleware(string, string, []Middleware)
RegisterHandler(string, string, Handler)
ServeHTTP(http.ResponseWriter, *http.Request)
}
// The router interface needs to implement two methods: the router method and the router core.
//
// 路由器接口,需要实现路由器方法、路由器核心两个接口。
Router interface {
RouterCore
RouterMethod
}
)
NewRouter
В настоящее время существует три реализации, каждая из которых реализует интерфейс маршрутизатора.
func NewRouterRadix() Router
func NewRouterFull() Router
func NewRouterHost() Router
router1 := erouter.NewRouterRadix()
router2 := erouter.NewRouterFull()
router3 := erouter.NewRouterHost()
Group
func Group(path string) RouterMethod
Группа реализует группировку маршрутизаторов.
router := erouter.NewRouterRadix()
apiv1 := router.Group("/api/v1 version=v1")
apiv1.Get("/*", ...)
AddHandler
func AddHandler(method string, path string, handler Handler) RouterMethod
AddHandler используется для добавления новых маршрутов.
router := erouter.NewRouterRadix()
router.AddHandle("GET", "/*", ...)
AddMiddleware
func AddMiddleware(method string, path string, midds ...Middleware) RouterMethod
AddMiddleware добавляет ПО промежуточного слоя обработки к текущему методу маршрутизации.
router := erouter.NewRouterRadix()
router.AddMiddleware("ANY", "", func(h erouter.Handler) erouter.Handler {
return func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
// befor执行
...
// 调用next处理汇总函数
h(w, r, p)
// after执行
...
}
})
NotFound
func NotFound(Handler)
Настройте маршрутизатор 404 для обработки.
MethodNotAllowed
func MethodNotAllowed(Handler)
Настройка маршрутизатора 405 ручек.
Any
func Any(path string, handler Handler)
Зарегистрируйте метод Any, который эквивалентен методу AddHandler со значением «ЛЮБОЙ».
Коллекция методов Any — это router.RouterAllMethod, а новые методы расширения Radix и Full не поддерживаются.
Get
func Get(path string, handler Handler)
Регистрация метода Get, эквивалентного методу AddHandler, называется «GET», а функции метода, такие как post и put, аналогичны.
router := erouter.NewRouterRadix()
router.Get("/*", func(w http.ResponseWriter, r *http.Request, p erouter.Params) {
// 执行处理
})