基于httprouter的路由模块
这个包是为了自己的go web项目 Bingo 所开发的模块之一,负责核心路由功能,这里将其抽出来作为单独包, 可以轻松的在其他项目中使用,而无需依赖 Bingo 框架
特性:
-
路由快速查找
-
动态路由传参
-
子路由支持(路由组)
-
中间件支持
bingo-router 基于 httprouter , 性能强劲, httprouter 拥有的特性,bingo-router也有,并且参考 Laravel 的 Pipeline 功能,为 bingo-router 添加中间件支持,可以快速实现拦截器等常见功能
后续准备加入的功能
-
会话管理
-
路由跳转
-
服务的平滑重启和关闭
-
工具方法补充(e.g.封装json返回等方法)
-
测试代码补充
go get -u github.com/silsuer/bingo-router
bingo-router 使用 glide 管理依赖,如果遇到无法 go install 问题,请先安装
glide后,去$PATH/src/github.com/silsuer/bingo-router目录下执行glide install命令安装依赖
bingo-router 已内置在 [Bingo](https://github.com/silsuer/bingo) 框架中,开箱即用,对于第三方项目:
- 初始化路由器对象
router:
// 创建一个路由器
router := bingo_router.New()路由器 Router 上挂载路由 Route,一个服务只能存在一个 Router,可存在多个Route,不要弄混
- 创建路由
route := bingo_router.NewRoute().Get("/").Target(func(c *bingo_router.Context) {
fmt.Fprint(c.Writer,"hello! bingo-router!")
})目前上下文对象context只是对 httprouter 中对象的一个简单封装,用法与 httprouter 完全一致:
type Context struct {
Writer http.ResponseWriter // 响应
Request *http.Request // 请求
Params Params //参数
}NewRoute 方法将会返回一个路由指针,可以调用:
-
Get()方法,设定为Get方法 -
Post()方法,设定为Get方法 -
Patch()方法,设定为Get方法 -
Put()方法,设定为Get方法 -
Delete()方法,设定为Get方法 -
Handle()方法,设定为Get方法 -
Target()方法,指定该路由所对应的方法 -
Middleware()方法,设定一个将在其中设置的中间件 -
MiddlewareGroup()方法,批量设置中间件 -
Prefix()方法,设置路由前缀,该前缀将对该路由的所有子路由有效,对当前路由无效 -
Mount()方法,设置子路由
- 将路由挂载到路由器中
router.Mount(route)路由器 Router 的
- 开启服务器
http.ListenAndServe(":8080", r)- 在浏览器中访问
http://localhost:8080, 可以看到输出hello, bingo-router!
使用 NewRoute() 方法之后将会获得一个 Route 对象指针,采用责任链模式,随意进行链式操作:
r2 := bingo_router.NewRoute().Get("/test").Middleware(func(c *bingo_router.Context, next func(c *bingo_router.Context)) {
fmt.Fprint(c.Writer,"middleware")
next(c)
}).Target(func(c *bingo_router.Context) {
fmt.Fprintln(c.Writer,"target")
})中间件是一种 MiddlewareHandle 类型的方法 func(c *Context, next func(c *Context))
Middleware 方法传入一个回调函数,该函数接受两个参数,第一个参数context 是上下文,是封装的http.ResponseWriter,*http.Request和httprouter.Params
第二个参数是 next 方法,用来指定何时跳入下一个中间件,主要是用来实现前置中间件和后置中间件功能,当执行 next 方法后,将会跳入下一个中间件,直到所有中间件运行完毕后,才会继续执行下面的代码
例如,上面的r2的效果是输出:
middleware
target
如果将中间件中的next() 方法向上提一行的话:
r2 := bingo_router.NewRoute().Get("/test").Middleware(func(c *bingo_router.Context, next func(c *bingo_router.Context)) {
next(c)
fmt.Fprint(c.Writer,"middleware")
}).Target(func(c *bingo_router.Context) {
fmt.Fprintln(c.Writer,"target")
})这样将会输出:
target
middleware这样就可以实现后置中间件的效果了,可以做一些访问完控制器方法之后的后续工作
当然,如果不在中间件中调用 next() 方法,请求就将在这个中间件中终止。
Route 对象的 MiddlewareGroup() 方法可以实现批量注册中间件的功能,传入一个 MiddlwareHandle 的数组即可,不再赘述
在 Laravel 中,我们经常会用到路由组的概念,可以方便的进行整体控制,在 bingo-router 中,我也实现了这样的功能,但是bingo-router中没有路由组的概念,可以使用子路由实现类似效果,
调用 Route 对象的 Mount 方法添加子路由:
bingo_router.NewRoute().Prefix("/api").Middleware(MiddlewareFunction).Mount(func(b *bingo_router.Builder) {
b.NewRoute().Get("/mount").Target(func(c *bingo_router.Context) {
fmt.Fprint(c.Writer, "hello mount")
})
b.NewRoute().Get("/mount2").Target(func(c *bingo_router.Context) {
fmt.Fprint(c.Writer, "hello mount2")
})
})Prefix 方法,传入一个字符串,这个字符串将作用在所有子路由路径前,例如上面的代码,我们最终的访问路径就是 /api/mount和/api/mount2
Mount 方法传入一个 Builder 指针,我们可以调用 Builder对象的 NewRoute() 方法为当前路由添加子路由,例如上面的代码,我们在访问 /api/mount和/api/mount2时都会经过我们指定的MiddlewareFunction 中间件
这个包还没有完全开发完成,后续会继续补充,也会在这两天内内置到 Bingo 框架中
请大家多多关注主框架 Bingo , 欢迎 STAR 、 PR