Go の Gin のミドルウェア
Gin のミドルウェアは、リクエストの前後に処理を挟む仕組みだ。ロギング、認証、CORS、リカバリーなど様々な用途で使われる。
ミドルウェアの基本構造
Gin のミドルウェアは gin.HandlerFunc 型の関数だ。
func MyMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
// リクエスト処理前
fmt.Println("Before request")
c.Next() // 次のハンドラを実行
// リクエスト処理後
fmt.Println("After request")
}
}c.Next() を呼ぶと、チェーン内の次のハンドラが実行される。Next() の後に書いたコードは、後続のハンドラがすべて完了した後に実行される。
グローバルミドルウェア
すべてのルートに適用するミドルウェアは Use で登録する。
r := gin.New() // ミドルウェアなしのエンジン
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.Use(MyMiddleware())gin.Default() は gin.Logger() と gin.Recovery() が最初から設定されている。
グループへのミドルウェア適用
特定のルートグループにだけミドルウェアを適用できる。
// 認証が必要なルート
authorized := r.Group("/admin")
authorized.Use(AuthRequired())
{
authorized.GET("/dashboard", dashboard)
authorized.POST("/settings", updateSettings)
}
// 認証不要のルート
public := r.Group("/public")
{
public.GET("/info", getInfo)
}ロギングミドルウェアの実装
リクエストの処理時間を計測するミドルウェアを作ってみる。
func Logger() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
c.Next()
latency := time.Since(start)
status := c.Writer.Status()
log.Printf("[%d] %s %s - %v",
status, c.Request.Method, path, latency)
}
}c.Next() の前後で時間を計測することで、ハンドラの処理時間がわかる。
認証ミドルウェアの例
func AuthRequired() gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(401, gin.H{
"error": "Authorization header required",
})
return
}
user, err := validateToken(token)
if err != nil {
c.AbortWithStatusJSON(401, gin.H{
"error": "Invalid token",
})
return
}
// 後続のハンドラで使えるように値をセット
c.Set("user", user)
c.Next()
}
}c.Abort() や c.AbortWithStatusJSON() を呼ぶと、後続のハンドラは実行されない。
コンテキストへの値の受け渡し
ミドルウェアで設定した値は、後続のハンドラで取得できる。
// ミドルウェアで設定
c.Set("userID", 123)
// ハンドラで取得
userID, exists := c.Get("userID")
if exists {
id := userID.(int)
}
// 型安全に取得するヘルパー
func GetUserID(c *gin.Context) (int, bool) {
if v, ok := c.Get("userID"); ok {
if id, ok := v.(int); ok {
return id, true
}
}
return 0, false
}ミドルウェアの実行順序
ミドルウェアは登録した順に実行される。
r.Use(A())
r.Use(B())
r.Use(C())この場合、リクエスト時は A → B → C の順、レスポンス時は C → B → A の順(Next() 以降の処理)になる。
A の前処理
B の前処理
C の前処理
ハンドラ実行
C の後処理
B の後処理
A の後処理
組み込みミドルウェア
Gin には便利な組み込みミドルウェアがある。
リクエストのログを出力する。メソッド、パス、ステータス、レイテンシなどが記録される。
panic が発生しても 500 エラーを返してサーバーを継続させる。本番環境では必須。
サードパーティ製のミドルウェアも豊富で、CORS、JWT 認証、レートリミットなど多くの機能がパッケージとして提供されている。