配置路由之前必须初始一个路由实例,如:r := zweb.New()

支持的基础函数如下所示:

r.GET(path string, handle znet.Handler)
r.POST(path string, handle znet.Handler)
r.PUT(path string, handle znet.Handler)
r.DELETE(path string, handle znet.Handler)
r.PATCH(path string, handle znet.Handler)
r.HEAD(path string, handle znet.Handler)
r.OPTIONS(path string, handle znet.Handler)
// 如需注册一个可以响应任何 HTTP 请求的路由可以使用 Any
r.Any(path string, handle znet.Handler)

普通路由

r.GET("/hi", func(c *znet.Context) {
		c.String(200, "Hello world")
})

r.POST("/ping", func(c *znet.Context) error {
		c.String(200, "Hello ping")
    // 如果返回错误会忽略上面的输出,转而输出 500 + err.Error()
    // 可以通过 znet.RewriteErrorHandler 中间件自定义
		return nil
})

// 还可以直接返回固定内容
r.GET("/ping", "pong")

正则路由

r.GET("/info/{id:[\\d]+}", func(c *znet.Context) {
		id := c.GetParam("id")
		c.String(200, "Hello " + id)
})

// 内置了几个别名简写, :id :full(等同*)
// 如果非上面两个别名则等同 ([^\\/.]+)
// 上面写法可以简写为下面方式
r.GET("/info/:id", func(c *znet.Context) {
		// 注意::id 内置是只匹配数字的
		id := c.GetParam("id")
		c.String(200, "Hello " + id)
})

r.GET("/user/*", func(c *znet.Context) {
    // 注意:: 等同 .*
    // 其实也可以 /user/{*:.*}
		all:= c.GetParam("*")
		c.String(200, all)
})

r.GET("/user/:name", func(c *znet.Context) {
		// 注意::name 等同 ([^\\/.]+),不一定是要name 其他的英文字符也可以
		name:= c.GetParam("name")
		c.String(200, "Hello " + name)
})

// 多个匹配
r.GET(`/file/(?P<name>[\\w\\d-]+).(?P<ext>[a-zA-Z]+)`, func(c *znet.Context) {
		file := c.GetParam("name")+"."+c.GetParam("ext")
		c.String(200, file)
})

结构体路由

// 默认情况是把方法的名称转蛇形命名并且用 - 分隔的
// 有需要可以修改 znet.BindStructDelimiter = "_"
// 如果 BindStructDelimiter 为空则路由使用大驼峰而不是转蛇形命名

// 结构体 方法名:请求方式+路由(大驼峰)
type testController struct {}
// 路由组前缀
var prefix = "/test"

// 该方法在绑定路由之前执行
func (t *testController) Init(r *znet.Engine) error {
  // 这里可以手动绑定一些特殊路由或者中间件之类
  return nil
}

// Get /test/user
func (t *testController) GETUser(c *znet.Context) {}
// Post /test/user-info
func (t *testController) POSTUserInfo(c *znet.Context) {}

// 有三个特殊的前缀(ID,Full, Name)等同正则路由的 :id 与 :full(等同*)
// Get /test/user/:id
func (t *testController) IDGETUser(c *znet.Context) {}
// Get /test/user/:full
func (t *testController) FullGETUser(c *znet.Context) {}

// 绑定路由
err := r.BindStruct(prefix, &testController{})

中间件

支持直接给路由组或者单个路由注册

PS. 所有支持 net 标准库的中间件包都可使用

// r.Use(middleware ...znet.HandlerFunc)

// 给当前 r 注册一个中间件
r.Use(func(c *znet.Context) {
		// 执行下一个 Handler
		c.Next()
		// 获取需要输出的内容
		// c.PrevContent()
})

// 单独给 / 注册中间件,支持多个
r.GET("/", func(c *znet.Context) {
			c.String(200, "哈哈")
},func(c *znet.Context) {
		c.Log.Debug("中间件前置处理")
		c.Next()
		c.Log.Debug("中间件后置处理")
},func(c *znet.Context) {
		c.Log.Debug("第二个中间件前置处理")
		c.Next()
		c.Log.Debug("第二个中间件后置处理")
})

优先级中间件 znet.WrapFirstMiddleware

默认情况下中间件是按传递的顺序执行的,假如想把某个中间件的执行时机提升至前面可以这样:

r.Use(func(c *znet.Context) {
		c.Log.Debug(1)
		c.Next()
		c.Log.Debug(2)
})

r.GET("/", func(c *znet.Context) {
		c.String(200, "哈哈")
},znet.WrapFirstMiddleware(func(c *znet.Context) {
		c.Log.Debug(3)
		c.Next()
		c.Log.Debug(4)
}))

// 执行之后的打印顺序就是: 3, 1, 4, 2

静态文件