中介層
本頁說明如何把 go-ip-sentry 接到 Gin 或 net/http、如何排除特定路徑,以及不經中介層直接呼叫 Check 的寫法。
三種接法
| 方式 | 簽章 | 失敗時 |
|---|---|---|
HTTPMiddleware |
func (i *IPGuardian) HTTPMiddleware(next http.Handler) http.Handler |
設定 Content-Type: application/json、寫入狀態碼與 {"error": "..."},不呼叫 next |
GinMiddleware |
func (i *IPGuardian) GinMiddleware() gin.HandlerFunc |
c.JSON(status, gin.H{"error": ...}) 後 c.Abort() |
Check |
func (i *IPGuardian) Check(r *http.Request, w http.ResponseWriter) IPGuardianResult |
由呼叫端決定 |
三者在通過時都已寫入 Session 與裝置 Cookie,必須在 handler 寫出 body 之前執行。
net/http
mux := http.NewServeMux()
mux.HandleFunc("/api/orders", ordersHandler)
log.Fatal(http.ListenAndServeTLS(":8443", "cert.pem", "key.pem", sentry.HTTPMiddleware(mux)))
Gin
r := gin.New()
r.Use(gin.Recovery())
api := r.Group("/api")
api.Use(sentry.GinMiddleware())
api.GET("/orders", listOrders)
if err := r.RunTLS(":8443", "cert.pem", "key.pem"); err != nil {
log.Fatal(err)
}
gin.Recovery() 建議保留:Redis 在評分階段失敗時 Check 會 panic(見 已知問題),Recovery 會把它轉成 500。
排除路徑
健康檢查、指標收集與固定週期輪詢會累積規律間隔與速率計數,應排除在外:
func protect(sentry *golangIPSentry.IPGuardian, next http.Handler) http.Handler {
guarded := sentry.HTTPMiddleware(next)
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case "/healthz", "/metrics":
next.ServeHTTP(w, r)
default:
guarded.ServeHTTP(w, r)
}
})
}
直接呼叫 Check
需要自訂回應格式(例如 HTML 錯誤頁)時:
func handler(sentry *golangIPSentry.IPGuardian) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
result := sentry.Check(r, w)
if !result.Success {
http.Error(w, http.StatusText(result.StatusCode), result.StatusCode)
return
}
w.Write([]byte("OK"))
}
}
IPGuardianResult.Error 包含用戶端 IP,直接回給用戶端前先確認是否符合隱私需求。