スキップしてメイン コンテンツに移動

Gin初心者のミドルウェア入門

Gin初心者のミドルウェア入門

Gin初心者のためのミドルウェア入門

GoでWebアプリを作る際に人気のフレームワーク、Ginは高速でシンプルな設計が特徴です。ミドルウェアはリクエストとレスポンスの間で共通処理を実行する仕組みで、認証やログ、エラーハンドリングなどを一元管理できます。Gin初心者が最初に触れるべきミドルウェアは、リクエストのロギングとエラーハンドリングを行うものです。

Ginではミドルウェアは gin.HandlerFunc 型の関数として定義し、ルーターに登録します。以下は簡単な例です。

func MyMiddleware(c *gin.Context) {
    // ここでリクエスト情報を取得
    c.Next() // 次のハンドラへ
    // ここでレスポンス情報を取得
}

このように c.Next() を呼び出すことで、ミドルウェアチェーンの次のハンドラへ処理を渡します。Gin初心者はこの流れを理解することで、後の複雑な処理もスムーズに実装できます。

r.Useでチェーンを構築する

Ginのルーターは r := gin.New() で作成し、r.Use() メソッドでミドルウェアを登録します。r.Use は複数のミドルウェアを順に実行するチェーンを構築します。例えば、ログとエラーハンドリングを同時に有効にしたい場合は次のように書きます。

r := gin.New()
r.Use(gin.Logger())
r.Use(gin.Recovery())
r.GET("/ping", func(c *gin.Context) {
    c.JSON(200, gin.H{"message": "pong"})
})

この例では gin.Logger()gin.Recovery() がチェーンに追加され、全てのリクエストでログが出力され、パニックが発生した際に安全にレスポンスが返されます。r.Use の順序は重要で、先に登録したミドルウェアが先に実行されます。

gin.Loggerとgin.Recoveryでログとエラーハンドリング

Ginに組み込まれている gin.Logger() はリクエストのメソッド、パス、ステータスコード、処理時間などを標準出力に出力します。デバッグ時に非常に便利で、ログレベルを細かく制御したい場合はカスタムミドルウェアを作成することも可能です。

一方、gin.Recovery() はパニックが発生した際に自動的に回復し、500ステータスでレスポンスを返します。これにより、サーバーがクラッシュするリスクを低減できます。エラーハンドリングを一元化したい場合は、gin.RecoveryWithWriter を使ってカスタムログ出力先を指定することもできます。

r.Use(gin.RecoveryWithWriter(gin.DefaultWriter, func(c *gin.Context, err interface{}) {
    // カスタムエラーログ
    log.Printf("panic: %v", err)
}))

このように、ログとエラーハンドリングをミドルウェアチェーンに組み込むことで、共通処理を一箇所にまとめ、コードの可読性と保守性を向上させます。

認証と共通処理の実装例

認証を行うミドルウェアは、リクエストヘッダーからトークンを取得し、検証した後に c.Set でユーザー情報をコンテキストに保存します。以下は簡易的なJWT認証ミドルウェアの例です。

func AuthMiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        token := c.GetHeader("Authorization")
        if token == "" {
            c.AbortWithStatusJSON(401, gin.H{"error": "token required"})
            return
        }
        // ここでトークン検証(省略)
        userID := "12345" // 例
        c.Set("userID", userID)
        c.Next()
    }
}

このミドルウェアを r.Use(AuthMiddleware()) で登録すると、全てのルートで認証が必須になります。認証後に共通処理として、リクエストごとにログを出力したり、ユーザー情報を取得してレスポンスに含めることができます。

さらに、特定のルートだけに認証を適用したい場合は、ルートグループを作成してミドルウェアを追加します。

auth := r.Group("/api")
auth.Use(AuthMiddleware())
auth.GET("/profile", func(c *gin.Context) {
    userID, _ := c.Get("userID")
    c.JSON(200, gin.H{"user": userID})
})

このように、ミドルウェアをチェーンで組み合わせることで、認証、ログ、エラーハンドリング、共通処理を柔軟に管理できます。Gin初心者はまず基本的なミドルウェアを作成し、r.Use でチェーンを構築する練習をすると良いでしょう。

この記事はAIによって作成されました。

コメント