You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
109 lines
3.1 KiB
109 lines
3.1 KiB
# 背景
|
|
|
|
基于bm的handler机制,可以自定义很多middleware(中间件)进行通用的业务处理,比如用户登录鉴权。接下来就以鉴权为例,说明middleware的写法和用法。
|
|
|
|
# 写自己的中间件
|
|
|
|
middleware本质上就是一个handler,如下代码:
|
|
```go
|
|
// Handler responds to an HTTP request.
|
|
type Handler interface {
|
|
ServeHTTP(c *Context)
|
|
}
|
|
|
|
// HandlerFunc http request handler function.
|
|
type HandlerFunc func(*Context)
|
|
|
|
// ServeHTTP calls f(ctx).
|
|
func (f HandlerFunc) ServeHTTP(c *Context) {
|
|
f(c)
|
|
}
|
|
```
|
|
|
|
1. 实现了`Handler`接口,可以作为engine的全局中间件使用:`engine.User(YourHandler)`
|
|
2. 声明为`HandlerFunc`方法,可以作为router的局部中间件使用:`e.GET("/path", YourHandlerFunc)`
|
|
|
|
简单示例代码如下:
|
|
|
|
```go
|
|
type Demo struct {
|
|
Key string
|
|
Value string
|
|
}
|
|
// ServeHTTP implements from Handler interface
|
|
func (d *Demo) ServeHTTP(ctx *bm.Context) {
|
|
ctx.Set(d.Key, d.Value)
|
|
}
|
|
|
|
e := bm.DefaultServer(nil)
|
|
d := &Demo{}
|
|
|
|
// Handler使用如下:
|
|
e.Use(d)
|
|
|
|
// HandlerFunc使用如下:
|
|
e.GET("/path", d.ServeHTTP)
|
|
|
|
// 或者只有方法
|
|
myHandler := func(ctx *bm.Context) {
|
|
// some code
|
|
}
|
|
e.GET("/path", myHandler)
|
|
```
|
|
|
|
|
|
# 全局中间件
|
|
|
|
在blademaster的`server.go`代码中,有以下代码:
|
|
|
|
```go
|
|
func DefaultServer(conf *ServerConfig) *Engine {
|
|
engine := NewServer(conf)
|
|
engine.Use(Recovery(), Trace(), Logger())
|
|
return engine
|
|
}
|
|
```
|
|
|
|
会默认创建一个bm engine,并注册`Recovery(), Trace(), Logger()`三个middlerware,用于全局handler处理。优先级从前到后。
|
|
如果需要自定义默认全局执行的middleware,可以使用`NewServer`方法创建一个无middleware的engine对象。
|
|
如果想要将自定义的middleware注册进全局,可以继续调用Use方法如下:
|
|
|
|
```go
|
|
engine.Use(YourMiddleware())
|
|
```
|
|
|
|
此方法会将`YourMiddleware`追加到已有的全局middleware后执行。
|
|
|
|
# 局部中间件
|
|
|
|
先来看一段示例(代码再pkg/net/http/blademaster/middleware/auth模块下):
|
|
|
|
```go
|
|
func Example() {
|
|
myHandler := func(ctx *bm.Context) {
|
|
mid := metadata.Int64(ctx, metadata.Mid)
|
|
ctx.JSON(fmt.Sprintf("%d", mid), nil)
|
|
}
|
|
|
|
authn := auth.New(&auth.Config{DisableCSRF: false})
|
|
|
|
e := bm.DefaultServer(nil)
|
|
|
|
// "/user"接口必须保证登录用户才能访问,那么我们加入"auth.User"来确保用户鉴权通过,才能进入myHandler进行业务逻辑处理
|
|
e.GET("/user", authn.User, myHandler)
|
|
// "/guest"接口访客用户就可以访问,但如果登录用户我们需要知道mid,那么我们加入"auth.Guest"来尝试鉴权获取mid,但肯定会继续执行myHandler进行业务逻辑处理
|
|
e.GET("/guest", authn.Guest, myHandler)
|
|
|
|
// "/owner"开头的所有接口,都需要进行登录鉴权才可以被访问,那可以创建一个group并加入"authn.User"
|
|
o := e.Group("/owner", authn.User)
|
|
o.GET("/info", myHandler) // 该group创建的router不需要再显示的加入"authn.User"
|
|
o.POST("/modify", myHandler) // 该group创建的router不需要再显示的加入"authn.User"
|
|
|
|
e.Start()
|
|
}
|
|
```
|
|
|
|
|
|
-------------
|
|
|
|
[文档目录树](summary.md)
|
|
|