### 快速使用
> 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())`
```