### 快速使用
> Orange 框架中间件是一个用来过滤进入应用 HTTP 请求的工具。可以通过它来方便实现登陆状态校验,权限校验,CSRF验证等等。
实例化中间件以参数形式传递到路由组参数进行申明,该路由组下所有路由将依次执行中间件方法;
```
app.GroupRouter("/api", NewMiddleWare1(), NewMiddleWare2())`
```
### 内置中间件
#### 限速中间件
实例化限速中间件 `throttle.NewThrottle(maxQps, breakTime, ipSplit)`
- maxQps:触发限速 qps ,当请求达到配置的 qps 数值,后续请求直接返回429错误;
- breakTime:当触发限速后等待指定时长才能正常访问;
- ipSplit : 限速是否按 ip 来源区分,true 是, false 否, 按 ip 来源区分,则请求 qps 会根据各个 ip 分别计算,否则直接计算所有请求qps;
相关代码调用:
~~~
import (
"gitee.com/zhucheer/orange/app"
"gitee.com/zhucheer/orange/middlewares/throttle"
)
...
rateGp :=app.NewRouter("/rate", throttle.NewThrottle(5, time.Minute, true))
...
~~~
#### CSRF校验
orange 框架已经全局集成 CSRF 校验,通过配置进行开启或关闭,开启后,全局所有 POST 请求都将进行 CSRF校验;
~~~
[app]
...
csrfVerify = true # 开启校验
~~~
通过控制器 context 参数获取 CSRF-TOKEN,如下:
~~~
func ControllerFunc(c *app.Context) error {
c.ResponseHeader().Set("Content-Type", "application/text")
return c.ToString(c.CsrfToken)
}
~~~
### 异常捕获
在 golang 中如遇到严重的异常或 BUG,往往会导致程序出现 panic 报错,当出现 panic 后程序会终止后续处理,因此我们也无法获取自定义日志等信息,通常我们会通过 defer 和 recover() 来捕获 panic 异常,该内置中间件就是完成 panic 捕获并记录日志的功能;
使用方法:
~~~
import (
"gitee.com/zhucheer/orange/app"
"gitee.com/zhucheer/orange/middlewares/exception"
)
...
rateGp :=app.NewRouter("/rate", exception.NewPanicReader())
...
~~~
注册该中间件后,在web请求中如出现 panic 后页面会输出 500 错误,并且日志会记录一个 Critiacal 级别的错误,我们通过日志可以获取到对应异常具体信息。
#### 服务端跨域 CROS 中间件
目前框架已内置一个简单好用的跨域配置中间件,在开发中经常会遇到前端跨域请求,为求方便很多服务直接到 `nginx` 上配置一个响应头 `Access-Control-Allow-Origin:*` 这种方法虽能快速解决问题但也埋下了一定的安全隐患,星号配置会将所有来源的请求均通过。
使用内置的中间件可以将指定来源网站域名添加到列表即可,如下所示:
~~~
// 只允许 www.domain1.com,www.domain2.com 这两个网站进行跨域调用
commonGp := app.NewRouter("",cros.NewHandler("www.domain1.com","www.domain2.com"))
~~~
### 自定义中间件方法
中间件都放在 middleware 目录下,可以参考内置中间件进行开发;
下面是一个请求 header 头状态检测中间件示例:
```
package middleware
import (
"fmt"
"gitee.com/zhucheer/orange/app"
)
type VerifyHeader struct {
}
func NewVerifyHeader () *VerifyHeader {
return &VerifyHeader {}
}
// Func implements Middleware interface.
func (w VerifyHeader ) Func() app.MiddlewareFunc {
return func(next app.HandlerFunc) app.HandlerFunc {
return func(c *app.Context) error {
// 状态验证逻辑
fmt.Println("VerifyHeader middleware")
if c.Request().Header.Get("auth") == "" {
c.ResponseWrite([]byte("header verify middleware break"))
return errors.New("header verify middleware break")
}
return next(c)
}
}
}
...
// routes.go
app.GroupRouter("/api", middleware.NewVerifyHeader())`
```